quartz的使用
介绍
Quartz是一个完全由Java编写的开源作业调度框架,为在Java应用程序中进行作业调度提供了简单却强大的机制。Quartz允许开发人员根据时间间隔来调度作业。它实现了作业和触发器的多对多的关系,还能把多个作业与不同的触发器关联。
使用
最近项目需求需要用户设定自动执行的定时任务,因为用的springboot框架,所以结合springboot,
进行quartz在项目中的使用
所需依赖:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <!-- 要用最新版本,4.2.7.RELEASE --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>4.2.7.RELEASE</version> </dependency> <!-- tools --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> <!-- quartz 版本用:2.2.1以上--> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.2.1</version> </dependency> <!-- 该依赖必加,里面有sping对schedule的支持 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>4.2.7.RELEASE</version> </dependency>
|
在Spring中使用Quartz有两种方式实现:第一种是任务类继承QuartzJobBean,第二种则是在配置文件里定义任务类和要执行的方法,类和方法可以是普通类。很显然,第二种方式远比第一种方式来的灵活。这里采用的就是第二种方式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:task="http://www.springframework.org/schema/task" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd"> <!-- 使用MethodInvokingJobDetailFactoryBean,任务类可以不实现Job接口,通过targetMethod指定调用方法--> <bean id="taskJob" class="com.example.demo.utils.TestTask"/> <bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="group" value="job_work"/> <property name="name" value="job_work_name"/> <!--false表示等上一个任务执行完后再开启新的任务--> <property name="concurrent" value="false"/> <property name="targetObject"> <ref bean="taskJob"/> </property> <property name="targetMethod"> <value>run</value> </property> </bean> <!-- 调度触发器 --> <bean id="myTrigger" lazy-init="false" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"> <property name="name" value="work_default_name"/> <property name="group" value="work_default"/> <property name="jobDetail"> <ref bean="jobDetail" /> </property> <property name="cronExpression"> <value>0 0 10 * * ?</value> </property> </bean> <!-- 调度工厂 --> <bean id="scheduler" lazy-init="false" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="myTrigger"/> </list> </property> </bean> <bean id="springContextUtil" class="com.example.demo.utils.MyApplicationContextUtil"/>
</beans>
|
TestTask类则是一个普通的Java类,没有继承任何类和实现任何接口(当然可以用注解方式来声明bean):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| package com.example.demo.utils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Configurable; import org.springframework.scheduling.annotation.EnableScheduling;
@Configurable @EnableScheduling public class TestTask { @Autowired ScheduleJobService scheduleJobService;
public void run() { System.out.println("测试任务线程开始执行"); } }
|
读取配置类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| package com.example.demo.utils;
import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component;
@Component public class MyApplicationContextUtil implements ApplicationContextAware { private static ApplicationContext applicationContext;
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { MyApplicationContextUtil.applicationContext=applicationContext; } public static ApplicationContext getContext(){ return applicationContext; } @SuppressWarnings("unchecked") public static <T> T getBean(String name) throws BeansException { return (T) applicationContext.getBean(name); }
}
|
在Application添加配置
1 2 3 4 5
| @Configuration @ImportResource("classpath:/spring/applicationContext.xml") static class XmlImportingConfiguration { }
|
项目启动自运行类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| package com.example.demo;
import com.example.demo.utils.ScheduleJobService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component;
@Component public class MyStartupRunner1 implements CommandLineRunner { @Autowired ScheduleJobService scheduleJobService; @Override public void run(String... args) throws Exception { System.out.println(">>>>>>>>>>>>>>>服务启动执行,执行加载数据等操作<<<<<<<<<<<<<"); init(); }
public void init() throws Exception { scheduleJobService.getAllSchedules(); } }
|
任务操作类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
| package com.example.demo.utils;
import org.quartz.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.quartz.SchedulerFactoryBean; import org.springframework.stereotype.Service;
import java.util.ArrayList; import java.util.List;
@Service public class ScheduleJobService { @Autowired SchedulerFactoryBean schedulerFactoryBean; private static String JOB_GROUP_NAME = "JOBGROUP_NAME"; private static String TRIGGER_GROUP_NAME = "EXTJWEB_TRIGGERGROUP_NAME";
public void getAllSchedules() throws Exception { List<ScheduleJob> jobList = new ArrayList<>(); ScheduleJob scheduleJob = new ScheduleJob(); String cron = String.format("0 0/%s * * * ? *",1); scheduleJob.setJobDesc(String.format("task(id:%s) is running","taskId")); scheduleJob.setJobName(String.valueOf(11)); scheduleJob.setJobGroup("test_group"); scheduleJob.setCronExpression(cron); jobList.add(scheduleJob); for (ScheduleJob job : jobList) { addScheduleJob(job); } }
public void addScheduleJob(ScheduleJob job) throws SchedulerException { Scheduler scheduler = schedulerFactoryBean.getScheduler(); TriggerKey triggerKey = TriggerKey.triggerKey(job.getJobName(), job.getJobGroup()); CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey); if (null == trigger) { JobDetail jobDetail = JobBuilder.newJob(QuartzJobFactory.class) .withIdentity(job.getJobName(), job.getJobGroup()).build(); jobDetail.getJobDataMap().put("scheduleJob", job); CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job .getCronExpression()).withMisfireHandlingInstructionFireAndProceed(); trigger = TriggerBuilder.newTrigger().startNow().withIdentity(job.getJobName(), job.getJobGroup()).withSchedule(scheduleBuilder).build(); scheduler.scheduleJob(jobDetail, trigger); } else { CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job .getCronExpression()).withMisfireHandlingInstructionFireAndProceed(); trigger = trigger.getTriggerBuilder().startNow().withIdentity(triggerKey) .withSchedule(scheduleBuilder).build(); scheduler.rescheduleJob(triggerKey, trigger); } System.out.println("触发器执行完毕!"); if (!scheduler.isShutdown()) { scheduler.start(); } }
public void removeJob(ScheduleJob job) throws SchedulerException { Scheduler sched = schedulerFactoryBean.getScheduler(); TriggerKey triggerKey = TriggerKey.triggerKey(job.getJobName(), job.getJobGroup()); sched.pauseTrigger(triggerKey); sched.unscheduleJob(triggerKey); JobKey jobKey = new JobKey(job.getJobName(),job.getJobGroup()); sched.deleteJob(jobKey ); } }
|
作业调度执行类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| package com.example.demo.utils;
import com.example.demo.service.TaskService; import org.quartz.*; import org.springframework.stereotype.Component;
@Component @DisallowConcurrentExecution public class QuartzJobFactory implements Job { @Override public void execute(JobExecutionContext context) throws JobExecutionException { System.out.println("任务成功运行"); ScheduleJob scheduleJob = (ScheduleJob)context.getMergedJobDataMap().get("scheduleJob"); System.out.println("任务名称 = [" + scheduleJob.getJobName() + "]"); TaskService taskService = MyApplicationContextUtil.getBean("taskService"); try { taskService.run(Long.parseLong(scheduleJob.getJobName())); } catch (Exception e) {
System.out.println("定时任务运行出错"+e.getMessage()); ScheduleJobService scheduleJobService = MyApplicationContextUtil.getBean("scheduleJobService"); try {
System.out.println("删除定时任务"); scheduleJobService.removeJob(scheduleJob); System.out.println("删除数据库任务记录");
} catch (SchedulerException e1) {
System.out.println("删除定时任务出错!"+e.getMessage()); } } } }
|
实体类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package com.example.demo.utils;
import lombok.Data;
import javax.persistence.Table;
@Data @Table(name = "task_quartz") public class ScheduleJob { private Long id; private String jobId; private String jobName; private String jobGroup; private String jobDesc; private String jobStatus; private String cronExpression; }
|
启动程序,效果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| 2017-09-03 12:58:26.555 INFO 4040 --- [ restartedMain] o.s.c.support.DefaultLifecycleProcessor : Starting beans in phase 2147483647 2017-09-03 12:58:26.556 INFO 4040 --- [ restartedMain] o.s.s.quartz.SchedulerFactoryBean : Starting Quartz Scheduler now 2017-09-03 12:58:26.556 INFO 4040 --- [ restartedMain] org.quartz.core.QuartzScheduler : Scheduler scheduler_$_NON_CLUSTERED started. 2017-09-03 12:58:26.626 INFO 4040 --- [ restartedMain] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http) >>>>>>>>>>>>>>>服务启动执行,执行加载数据等操作<<<<<<<<<<<<< 触发器执行完毕! 2017-09-03 12:58:26.631 INFO 4040 --- [ restartedMain] org.quartz.core.QuartzScheduler : Scheduler scheduler_$_NON_CLUSTERED started. 2017-09-03 12:58:26.632 INFO 4040 --- [ restartedMain] com.example.demo.QuartzApplication : Started QuartzApplication in 4.449 seconds (JVM running for 4.988) 任务成功运行 任务名称 = [11] 进入定时任务--- ------ 本次任务执行完毕--- 任务成功运行 任务名称 = [11] 进入定时任务--- ------
|
源码地址:
https://github.com/RowRainclb/springboot_quartz