Quartz API核心接口有:
1、Scheduler – 与scheduler交互的主要API;
2、Job – 通过scheduler执行任务,你的任务类需要实现的接口;
3、JobDetail – 定义Job的实例;
4、Trigger – 触发Job的执行;
5、JobBuilder – 定义和创建JobDetail实例的接口
6、TriggerBuilder – 定义和创建Trigger实例的接口
maven中需要引入
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.1</version>
</dependency>
import static org.quartz.JobBuilder.newJob;
import static org.quartz.SimpleScheduleBuilder.simpleSchedule;
import static org.quartz.TriggerBuilder.newTrigger;
public void startSchedulerTest() throws SchedulerException{
//Scheduler在使用之前需要实例化。一般通过SchedulerFactory来创建一个实例。
SchedulerFactory schedFact=new StdSchedulerFactory();
Scheduler sched=schedFact.getScheduler();
//要导入静态包文件
JobDetail job=newJob(HelloJob.class)
.withIdentity("myJob","group1")
.build();
Trigger trigger=newTrigger()
.withIdentity("myTrigger","group1")
.startNow()
.withSchedule(simpleSchedule()
.withIntervalInSeconds(40)
.repeatForever())
.build();
sched.scheduleJob(job,trigger);
//scheduler实例化后,可以启动(start)、暂停(stand-by)、停止(shutdown).
//scheduler被停止后,除非重新实例化,否则不能重新启动;只有当scheduler启动后,
// trigger才会被触发(job才会被执行)。即使scheduler处于暂停状态job也不执行,
sched.start();
sched.shutdown();
}
Scheduler的生命期,从SchedulerFactory创建它时开始,到Scheduler调用shutdown()方法时结束;Scheduler被创建后,可以增加、删除和列举Job和Trigger,以及执行其它与调度相关的操作(如暂停Trigger)。但是,Scheduler只有在调用start()方法后,才会真正地触发trigger(即执行job)。
也可以这样获得scheduler实例:
Scheduler scheduler=StdSchedulerFactory.getDefaultScheduler();
Job和Trigger
一个job就是一个实现了Job接口的类,该接口只有一个方法:
public interface Job {
void execute(JobExecutionContext var1) throws JobExecutionException;
}
当job的一个trigger被触发后,execute()方法会被scheduler的一个工作线程调用;每次当scheduler执行job时,在调用其execute(…)方法之前会创建该类的一个新的实例;执行完毕,对该实例的引用就被丢弃了,实例会被垃圾回收;这就会导致:job必须有一个无参的构造函数(当使用默认的JobFactory时);另一个后果是,在job类中,不应该定义有状态的数据属性,因为在job的多次执行中,这些属性的值不会保留。所以要使用JobDataMap跟踪job的状态。
传递给execute()方法的JobExecutionContext对象中保存着该job运行时的一些信息 ,包括执行job的scheduler的引用,触发job的trigger的引用,JobDetail对象引用,以及一些其它信息。
public void execute(JobExecutionContext context) throws JobExecutionException {
context.getScheduler();
context.getJobDetail();
context.getTrigger();
}
JobDetail对象是在将job加入scheduler时,由客户端程序(你的程序)创建的。它包含job的各种属性设置,以及用于存储job实例状态信息的JobDataMap。
JobDataMap中可以包含不限量的(序列化的)数据对象,在job实例执行的时候,可以使用其中的数据;JobDataMap是Java Map接口的一个实现,额外增加了一些便于存取基本类型的数据的方法。
//在创建JobDetail时,将要执行的job的类名传给了JobDetail,所以scheduler就知道了要执行何种类型的job
JobDetail job=newJob(HelloJob.class)
.withIdentity("myJob","group1")
//使用jobDataMap保存job实例状态信息
.usingJobData("jobSays","Hello world")
.usingJobData("myFloatValue",3.14f)
.build();
在job的执行过程中,可以从JobDataMap中取出数据:
public void execute(JobExecutionContext context) throws JobExecutionException {
JobKey key=context.getJobDetail().getKey();
JobDataMap dataMap=context.getJobDetail().getJobDataMap();
String jogSays=dataMap.getString("jobSays");
float myFloat=dataMap.getFloat("myFloatValue");
System.out.println("key="+key+" jobSays="+jogSays+" myFloat="+myFloat);
}
//结果
key=group1.myJob jobSays=Hello world myFloat=3.14
如果你在job类中,为JobDataMap中存储的数据的key增加set方法(如在上面示例中,增加setJobSays(String val)方法),那么Quartz的默认JobFactory实现在job被实例化的时候会自动调用这些set方法,这样你就不需要在execute()方法中显式地从map中取数据了。
public class HelloJob implements Job {
String jobSays;
float myFloatValue;
public HelloJob(){}
public void execute(JobExecutionContext context) throws JobExecutionException {
JobKey key=context.getJobDetail().getKey();
System.out.println("key="+key+" jobSays="+jobSays+" myFloat="+myFloatValue);
}
public void setJobSays(String jobSays){
this.jobSays=jobSays;
}
public void setMyFloatValue(float myFloatValue){
this.myFloatValue=myFloatValue;
}
}
//结果
key=group1.myJob jobSays=Hello world myFloat=3.14
context.getMergedJobDataMap()方法返回的JobDataMap,它是JobDetail中的JobDataMap和Trigger中的JobDataMap的并集,但是如果存在相同的数据,则后者会覆盖前者的值
JobDetail job=newJob(HelloJob.class)
.withIdentity("myJob","group1")
.usingJobData("jobSays","Hello world")
.usingJobData("myFloatValue",3.14f)
.build();
Trigger trigger=newTrigger()
.withIdentity("myTrigger","group1")
.usingJobData("myTrigger","Hello Trigger")
//存在相同的key,会将之前的值覆盖
.usingJobData("jobSays","Hello world trigger")
.startNow()
.withSchedule(simpleSchedule()
.withIntervalInSeconds(40)
.repeatForever())
.build();
//job中
public void execute(JobExecutionContext context) throws JobExecutionException {
JobKey key=context.getJobDetail().getKey();
JobDataMap dataMap=context.getMergedJobDataMap();
String jogSays=dataMap.getString("jobSays");
float myFloat=dataMap.getFloat("myFloatValue");
String myTrigger=dataMap.getString("myTrigger");
System.out.println("key="+key+" jobSays="+jogSays+" myFloat="+myFloat+ " myTrigger="+myTrigger);
//结果
key=group1.myJob jobSays=Hello world trigger myFloat=3.14 myTrigger=Hello Trigger
可以只创建一个job类,然后创建多个与该job关联的JobDetail实例,每一个实例都有自己的属性集和JobDataMap,最后,将所有的实例都加到scheduler中。
JobDetail job=newJob(HelloJob.class)
.withIdentity("myJob","group1")
.usingJobData("jobSays","Hello world")
.usingJobData("myFloatValue",3.14f)
.build();
JobDetail job1=newJob(HelloJob.class)
.withIdentity("myjob1","group2")
.usingJobData("name","my job")
.build();
当一个trigger被触发时,与之关联的JobDetail实例会被加载,JobDetail引用的job类通过配置在Scheduler上的JobFactory进行初始化。默认的JobFactory实现,仅仅是调用job类的newInstance()方法,然后尝试调用JobDataMap中的key的setter方法。你也可以创建自己的JobFactory实现,比如让你的IOC或DI容器可以创建/初始化job实例。
将Job和Trigger注册到Scheduler时,可以为它们设置key,配置其身份属性。Job和Trigger的key(JobKey和TriggerKey)可以用于将Job和Trigger放到不同的分组(group)里,然后基于分组进行操作。同一个分组下的Job或Trigger的名称必须唯一,即一个Job或Trigger的key由名称(name)和分组(group)组成。
参考文章:
http://ifeve.com/quartz-tutorial-job-jobdetail/
https://unmi.cc/quartz-job-scheduling-framework-chinese/