若要明白 Quartz
怎么用,首先要了解 Job
(任务)、JobDetail
(任务信息)、Trigger
(触发器)和Scheduler
(调度器)这 4 个核心的概念。
job
是一个接口,只定义一个方法execute(JobExecutionContext context)
,在实现接口的 execute
方法中编写所需要定时执行的 Job
(任务),JobExecutionContext
类提供了调度应用的一些信息。Job
运行时的信息保存在 JobDataMap
实例中。
package org.quartz;
public interface Job {
void execute(JobExecutionContext var1) throws JobExecutionException;
}
package org.quartz;
import java.util.Date;
public interface JobExecutionContext {
Scheduler getScheduler(); //调度器, 装载着任务和触发器
Trigger getTrigger(); //触发器,触发 Job 执行的时间触发规则
Calendar getCalendar();
boolean isRecovering();
TriggerKey getRecoveringTriggerKey() throws IllegalStateException;
int getRefireCount();
JobDataMap getMergedJobDataMap();
JobDetail getJobDetail(); //Job实现类
Job getJobInstance(); //job
Date getFireTime();
Date getScheduledFireTime();
Date getPreviousFireTime();
Date getNextFireTime();
String getFireInstanceId();
Object getResult();
void setResult(Object var1);
long getJobRunTime();
void put(Object var1, Object var2);
Object get(Object var1);
}
Quartz
每次调度 Job
时,都重新创建一个 Job
实例,所以它不直接接受一个 Job
的实例,相反它接收一个 Job
实现类(JobDetail
,描述 Job
的实现类及其他相关的静态信息,如 Job
名字、描述、关联监听器等信息),以便运行时通过 newInstance()
的反射机制实例化 Job
。
public interface JobDetail extends Serializable, Cloneable {
JobKey getKey();
String getDescription();
Class extends Job> getJobClass();
JobDataMap getJobDataMap();
boolean isDurable();
boolean isPersistJobDataAfterExecution();
boolean isConcurrentExectionDisallowed();
boolean requestsRecovery();
Object clone();
JobBuilder getJobBuilder();
}
描述触发 Job
执行的时间触发规则。主要有 SimpleTrigger
和 CronTrigger
这两个子类。
当且仅当需调度一次或者以固定时间间隔周期执行调度,SimpleTrigger
是最适合的选择;而 CronTrigger
则可以通过 Cron
表达式定义出各种复杂时间规则的调度方案,如工作日周一到周五的 15:00~16:00 执行调度等。
CronTrigger 源码:
package org.quartz;
import java.util.TimeZone;
public interface CronTrigger extends Trigger {
long serialVersionUID = -8644953146451592766L;
int MISFIRE_INSTRUCTION_FIRE_ONCE_NOW = 1;
int MISFIRE_INSTRUCTION_DO_NOTHING = 2;
String getCronExpression();
TimeZone getTimeZone();
String getExpressionSummary();
TriggerBuilder getTriggerBuilder();
}
调度器就相当于一个容器,装载着任务和触发器。 该类是一个接口,代表一个 Quartz
的独立运行容器,Trigger
和 JobDetail
可以注册到 Scheduler
中,两者在 Scheduler
中拥有各自的组及名称,组及名称是 Scheduler
查找定位容器中某一对象的依据,Trigger
的组及名称必须唯一, JobDetail
的组和名称也必须唯一(但可以和 Trigger 的组和名称相同,因为它们是不同类型的)。Scheduler
定义了多个接口方法,允许外部通过组及名称访问和控制容器中 Trigger
和 JobDetail
。
Scheduler 部分源码:
package org.quartz;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.quartz.Trigger.TriggerState;
import org.quartz.impl.matchers.GroupMatcher;
import org.quartz.spi.JobFactory;
public interface Scheduler {
String DEFAULT_GROUP = "DEFAULT";
String DEFAULT_RECOVERY_GROUP = "RECOVERING_JOBS";
String DEFAULT_FAIL_OVER_GROUP = "FAILED_OVER_JOBS";
String FAILED_JOB_ORIGINAL_TRIGGER_NAME = "QRTZ_FAILED_JOB_ORIG_TRIGGER_NAME";
String FAILED_JOB_ORIGINAL_TRIGGER_GROUP = "QRTZ_FAILED_JOB_ORIG_TRIGGER_GROUP";
String FAILED_JOB_ORIGINAL_TRIGGER_FIRETIME_IN_MILLISECONDS = "QRTZ_FAILED_JOB_ORIG_TRIGGER_FIRETIME_IN_MILLISECONDS_AS_STRING";
String FAILED_JOB_ORIGINAL_TRIGGER_SCHEDULED_FIRETIME_IN_MILLISECONDS = "QRTZ_FAILED_JOB_ORIG_TRIGGER_SCHEDULED_FIRETIME_IN_MILLISECONDS_AS_STRING";
//job和trigger结合
Date rescheduleJob(TriggerKey var1, Trigger var2) throws SchedulerException;
//更新job和trigger结合
Date rescheduleJob(TriggerKey var1, Trigger var2) throws SchedulerException;
//立即执行任务
void triggerJob(JobKey var1, JobDataMap var2) throws SchedulerException;
//暂停任务
void pauseJob(JobKey var1) throws SchedulerException;
//恢复任务
void resumeJob(JobKey var1) throws SchedulerException;
//删除定时任务
boolean deleteJob(JobKey var1) throws SchedulerException;
//...
}
如下图:
Job 为作业的接口,为任务调度的对象;JobDetail 用来描述 Job 的实现类及其他相关的静态信息;Trigger 做为作业的定时管理工具,一个 Trigger 只能对应一个作业实例,而一个作业实例可对应多个触发器;Scheduler 做为定时任务容器,是 quartz 最上层的东西,它提携了所有触发器和作业,使它们协调工作,每个 Scheduler 都存有 JobDetail 和 Trigger 的注册,一个 Scheduler 中可以注册多个 JobDetail 和多个 Trigger。
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.0.4.RELEASEversion>
<relativePath/>
parent>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-quartzartifactId>
dependency>
首先定义一个 Job 需要继承QuartzJobBean
,QuartzJobBean
继承了Job接口, 示例中 Job 定义一个变量 Name,用于在定时执行的时候传入。
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;
/**
*job
*/
public class SampleJob extends QuartzJobBean {
private String name;
public void setName(String name) {
this.name = name;
}
@Override
protected void executeInternal(JobExecutionContext context)
throws JobExecutionException {
System.out.println(String.format("Hello %s!", this.name));
}
}
import org.quartz.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SampleScheduler {
@Bean
public JobDetail sampleJobDetail() {
return JobBuilder.newJob(SampleJob.class).withIdentity("sampleJob")
.usingJobData("name", "World").storeDurably().build();
}
@Bean
public Trigger sampleJobTrigger() {
SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(2).repeatForever();
return TriggerBuilder.newTrigger().forJob(sampleJobDetail())
.withIdentity("sampleTrigger").withSchedule(scheduleBuilder).build();
}
}
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class QuartzApplication {
public static void main(String[] args) {
SpringApplication.run(QuartzApplication.class, args);
}
}