Quartz是OpenSymphony开源组织在Job scheduling领域的一个开源项目,是一款清新友好的任务调度框架。
Quartz两大基本功能是job和SimpleTrigger(作业和触发器)。
基本组成
核心的是Scheduler类。

有以下几个相关类:
Scheduler:定时任务调度;
Job:任务类需要实现的接口;
JobDetail:Job的实例,被Scheduler执行的是JobDetail,而不是Job;
Trigger:触发Job的执行;
JobBuilder:定义和创建JobDetail实例的接口;
TriggerBuilder:定义和创建Trigger实例的接口;
作业和触发器,是一对多的关系,每一个Job,都仅对应一个JobDetail。
不使用配置文件
作业
继承Job接口并实现execute方法,或是继承QuartzJobBean并实现executeInternal方法:
public class SimpleQuartzJob implements Job {
public SimpleQuartzJob() {
}
public void execute(JobExecutionContext context) throws JobExecutionException {
System.out.println("In SimpleQuartzJob - executing its JOB at "
+ new Date() + " by " + context.getTrigger().getName());
}
}
execute 方法接受一个 JobExecutionContext 对象作为参数,提供了job实例的上下文
触发器
通过触发器启动任务:
public void task() throws SchedulerException
{
// Initiate a Schedule Factory
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
// Retrieve a scheduler from schedule factory
Scheduler scheduler = schedulerFactory.getScheduler();
long ctime = System.currentTimeMillis();
// Initiate JobDetail with job name, job group, and executable job class
JobDetail jobDetail =
new JobDetail("jobDetail-s1", "jobDetailGroup-s1", SimpleQuartzJob.class);
// Initiate SimpleTrigger with its name and group name
SimpleTrigger simpleTrigger =
new SimpleTrigger("simpleTrigger", "triggerGroup-s1");
// set its start up time
simpleTrigger.setStartTime(new Date(ctime));
// set the interval, how often the job should run (10 seconds here)
simpleTrigger.setRepeatInterval(10000);
// set the number of execution of this job, set to 10 times.
simpleTrigger.setRepeatCount(100);
/** set the ending time of this job.
* We set it for 60 seconds from its startup time here
* Even if we set its repeat count to 10,
* this will stop its process after 6 repeats as it gets it endtime by then.*/
simpleTrigger.setEndTime(new Date(ctime + 60000L));
// set priority of trigger. If not set, the default is 5
simpleTrigger.setPriority(10);
// schedule a job with JobDetail and Trigger
scheduler.scheduleJob(jobDetail, simpleTrigger);
// start the scheduler
scheduler.start();
}
Cron触发器
可使用触发器快捷的调用定时任务(Spring有自身的定时任务cron触发器,类似),Corn包含以下七个字段:
秒 分 时 月内日期 月 周内日期 年(可选)
特殊符号:
/:增量,分位5/15表示5分开始 每15分钟增量
?:忽略,忽略该位,限定月内日、周内日可用
*:通配,所有有效
数字后W:指定工作日,如月1W为第一个工作日
(0/5 * * * * ?)代表每五秒钟执行一次
public void task() throws SchedulerException { // Initiate a Schedule Factory SchedulerFactory schedulerFactory = new StdSchedulerFactory(); // Retrieve a scheduler from schedule factory Scheduler scheduler = schedulerFactory.getScheduler(); long ctime = System.currentTimeMillis(); // Initiate JobDetail with job name, job group, and executable job class JobDetail jobDetail = new JobDetail("jobDetail2", "jobDetailGroup2", SimpleQuartzJob.class); // Initiate CronTrigger with its name and group name CronTrigger cronTrigger = new CronTrigger("cronTrigger", "triggerGroup2"); try { // setup CronExpression CronExpression cexp = new CronExpression("0/5 * * * * ?"); // Assign the CronExpression to CronTrigger cronTrigger.setCronExpression(cexp); } catch (Exception e) { e.printStackTrace(); } // schedule a job with JobDetail and Trigger scheduler.scheduleJob(jobDetail, cronTrigger); // start the scheduler scheduler.start(); }
使用xml配置任务
<bean id="timedtask" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject"> <bean class="com.timetask.TimeTask" /> <!-- 任务 --> </property> <property name="targetMethod" value="run" /> <!-- 作业执行方法(注意:这里不再继承Job类) --> <property name="concurrent" value="false" /><!-- 作业不并发调度 --> </bean> <bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean"> <property name="jobDetail" ref="timedtask" /> <property name="cronExpression" value="0 0 3 * * ?" /> </bean> <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean"> <property name="jobDetail" ref="timedtask" /> <property name="startDelay" value="0" /><!-- 延迟0秒 --> <property name="repeatInterval" value="5000" /><!-- 每5秒调度一次 --> </bean> <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="simpleTrigger" /> <ref bean="cronTrigger" /> </list> </property> </bean>
在Springboot中使用Quartz(注解)
引入依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-quartz</artifactId> </dependency>
写Job:
public class TestQuartz extends QuartzJobBean {
/**
* 执行任务
* @param jobExecutionContext
* @throws JobExecutionException
*/
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println("Test task"+new Date());
}
}
配置调度、触发器,这里提供了三种示范:
@Configuration
public class QuartzConfig {
@Bean(name = "myJob")
public JobDetail testQuartzDetail(){
return JobBuilder.newJob(TestQuartz.class)
.withIdentity("testQuartz","testQuartz_group")
// 执行中应用发生故障,会重新执行
.requestRecovery()
// 即使没有Trigger关联,也不删除该JobDetail,而是将其加入队列,等待一个sched.scheduleJob
.storeDurably()
.build();
}
@Bean(name = "scheduleBuilder")
public SimpleScheduleBuilder scheduleBuilder(){
SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(10) //设置时间周期单位秒
//.repeatSecondlyForTotalCount(5);//指定执行次数
.repeatForever(); //始终执行
return scheduleBuilder;
}
//2.0+ trigger
@Bean(name = "simpleTrigger")
public Trigger testQuartzSimpleTrigger(
@Qualifier("scheduleBuilder")ScheduleBuilder scheduleBuilder,
@Qualifier("myJob")JobDetail job){
return TriggerBuilder.newTrigger().forJob(job)
.withIdentity("testQuartzTrigger","triggerGroup")
.withSchedule(scheduleBuilder)
.build();
}
//Spring2.0之前 CornTrigger
@Bean(name = "cornTrigger")
public CronTriggerFactoryBean CornTrigger(@Qualifier("myJob")JobDetail job) {
CronTriggerFactoryBean trigger = new CronTriggerFactoryBean();
trigger.setJobDetail(job);
trigger.setCronExpression("0/10 * * * * ?");
trigger.setName("cornTrigger");
return trigger;
}
//2.0+ cornTrigger
@Bean(name = "cornTrigger2")
public Trigger SecondCornTrigger(@Qualifier("myJob")JobDetail job) {
Trigger trigger=TriggerBuilder.newTrigger().forJob(job)
.withIdentity("cornTrigger2", "triggerGroup")
.withSchedule(CronScheduleBuilder.cronSchedule("0/10 * * * * ? *"))
.startNow() //其实默认即是startNow()
.build();
return trigger;
}
}
这样配置好的任务会直接被调度触发,一个JobDetail同时注入了三个Trigger,运行结果是每十秒输出三组数据。
配置properties:
# 线程调度器实例名 org.quartz.scheduler.instanceName = quartzScheduler # 线程池的线程数,即最多3个任务同时跑 org.quartz.threadPool.threadCount = 3 # 使用内存存储任务和触发器等信息 org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
配置:
@Configuration
public class QuartzConfigration {
@Autowired
private JobFactory jobFactory;
@Bean
public SchedulerFactoryBean schedulerFactoryBean() {
SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
schedulerFactoryBean.setJobFactory(jobFactory);
// 用于quartz集群,QuartzScheduler 启动时更新己存在的Job
schedulerFactoryBean.setOverwriteExistingJobs(true);
schedulerFactoryBean.setStartupDelay(1);
return schedulerFactoryBean;
}
@Bean
public Scheduler scheduler() {
return schedulerFactoryBean().getScheduler();
}
}
配置jobFactory:
@Component
public class JobFactory extends AdaptableJobFactory {
@Autowired
private AutowireCapableBeanFactory capableBeanFactory;
@Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
// 调用父类的方法
Object jobInstance = super.createJobInstance(bundle);
// 进行注入
capableBeanFactory.autowireBean(jobInstance);
return jobInstance;
}
}
注册组件(这里省略了任务类):
@Configuration
public class QuartzJobConfig {
/**
* MethodInvokingJobDetailFactoryBean
*/
@Bean(name = "myJobBean")
public MethodInvokingJobDetailFactoryBean myJobBean(
MyJob myJob) {
MethodInvokingJobDetailFactoryBean jobDetail = new MethodInvokingJobDetailFactoryBean();
jobDetail.setConcurrent(false);
jobDetail.setName("general-myJob");
jobDetail.setGroup("general");
jobDetail.setTargetObject(myJob);
jobDetail.setTargetMethod("myJobBusinessMethod");
return jobDetail;
}
/**
* CornTriggerFacyoryBean
*/
@Bean(name = "myJobTrigger")
public CronTriggerFactoryBean myJobTrigger(@Qualifier("myJobBean")
MethodInvokingJobDetailFactoryBean myJobDetailFactoryBean) {
CronTriggerFactoryBean trigger = new CronTriggerFactoryBean();
trigger.setJobDetail(myJobDetailFactoryBean.getObject());
trigger.setCronExpression("0/10 * * * * ?");
trigger.setName("general-myJobTrigger");
return trigger;
}
}
把job和触发器注册到调度器:
@Configuration
public class QuartzConfig {
/**
* 调度器工厂Bean
*/
@Bean(name = "schedulerFactory")
public SchedulerFactoryBean schedulerFactory(
@Qualifier("myFirstExerciseJobTrigger") Trigger myFirstExerciseJobTrigger,
@Qualifier("mySecondExerciseJobTrigger") Trigger mySecondExerciseJobTrigger) {
SchedulerFactoryBean bean = new SchedulerFactoryBean();
// 覆盖已存在的任务
bean.setOverwriteExistingJobs(true);
// 延时启动定时任务,避免系统未完全启动却开始执行定时任务的情况
bean.setStartupDelay(15);
// 注册触发器
bean.setTriggers(myFirstExerciseJobTrigger, mySecondExerciseJobTrigger);
return bean;
}
}
Quartz的其他扩展(待更新)
多线程下的Quartz
Job仓库
Job的Param
//TODO


2019-06-18鱼鱼