Quartz的监听器用于当任务调度中你所关注事件发生时,能够及时获取这一事件的通知。类似于任务执行过程中的邮件、短信类的提醒。
文章目录
目录
一、Quatz是什么?
Quartz框架是一个全功能、开源的任务调度服务,可以集成几乎任何的java应用程序—从小的单片机系统到大型的电子商务系统。Quartz可以执行上千上万的任务调度。
二、Quatz架构
Scheduler
任务调度器Scheduler:
一个任务调度容器中可以注册多个Trigger和JobDetail
当Trigger和JobDetail组合时,就可以被任务调度器Scheduler调度了
一般情况下,一个应用只需要一个Scheduler对象
SchedulerFactory用于创建Scheduler:
包括DirectSchedulerFactory和StdSchedulerFactory
因为DirectSchedulerFactory使用需要做很多详细的手工编码设计,所以一般StdSchedulerFactory使用较多
Scheduler主要有三种:
RemoteMBeanScheduler
RemoteScheduler
StdScheduler
Trigger
触发器Trigger: 任务调度的时间规则
Trigger是Quartz的触发器,会通知任务调度器Scheduler执行指定的任务Job
Quartz中提供四种类型的触发器:
SimpleTrigger: 可以实现在一个指定时间段内执行一次任务或者在一个时间段内执行多次任务
CronTrigger:
基于日历的任务调度,功能非常强大
相比较于SimpleTrigger精准指定间隔 ,CronTrigger是基于Cron表达式的,更加常用
DateIntervalTrigger
NthIncludedDayTrigger
Calendar: 一些日历的特定时间点的集合
一个触发器可以包含多个Calendar, 这样可以用包含或者排除某些时间点
JobDetail
任务调度程序JobDetail:
一个具体的可执行的任务调度程序
Job就是这个可执行任务调度程序所要执行的内容
JobDetail中还包含了任务调度的方案和策略
JobDetail绑定指定的Job, 每次Scheduler调用执行一个Job时,首先会获取对应的Job, 然后创建该Job的实例,再去执行Job中的execute() 的内容,任务执行结束后,关联的Job对象实例会被释放并且会被JVM的GC清除
JobDetail为Job实例提供了许多属性:
name
group
jobClass
jobDataMap
Job
任务Job: 表示要执行的具体工作或者被调度的任务
自定义的任务类需要实现该接口,通过重写execute() 方法来定义任务的执行逻辑
Job的类型有两种:
无状态的stateless job
有状态的stateful job
对于同一个触发器Trigger来说,有状态的Job不能并行执行,只有上一次触发的任务被执行完成之后,才能触发下一次执行
Job的属性有两种:
volatility: 表示任务是否被持久化到数据库存储
durability: 没有trigger关联的时候任务是否保留
两者都是在值为true时表示任务被持久化或者保留
一个Job可以关联多个Trigger, 一个Trigger只能关联一个Job
JobExecutionContext:
JobExecutionContext中包含了Quartz运行时的环境以及Job本身的详细数据信息
当Scheduler调度执行一个Job时,就会将JobExecutionContext传递到当前Job的execute() 中,当前Job就可以通过JobExecutionContext对象获取信息
Quartz设计成JobDetail + Job的原因在于:
JobDetail用于定义任务数据, 真正的执行任务的逻辑在Job中
因为任务有可能是并发执行的,如果Scheduler直接使用Job, 会存在对同一个Job实例并发访问的问题
通过JobDetail绑定Job的方式 ,Scheduler每次执行,都会根据JobDetail创建一个新的Job实例,可以避免并发访问的问题
三、使用步骤
1.引入依赖坐标
代码如下(示例):
<dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.3.0</version> </dependency> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz-jobs</artifactId> <version>2.3.0</version> </dependency>
2.定义Job
代码如下(示例):
public class taskJob implements Job { @Override public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { System.out.println("task run...."); }
}
3.创建调度器 Scheduler
SchedulerFactory factory = new StdSchedulerFactory();
Scheduler scheduler = factory.getScheduler();
4、创建JobDetail实例
JobDetail job = JobBuilder.newJob(taskJob.class)
.withIdentity("job1", "group1")
.build();
5、构建Trigger实例
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "group1")
.startNow()
.withSchedule(SimpleScheduleBuilder
.simpleSchedule()
.withIntervalInSeconds(30)
.repeatForever())
.build();
6、执行,开启调度器
scheduler.scheduleJob(job, trigger);
scheduler.start();
7、暂停任务
scheduler.pauseTrigger(Trigger.triggerKey("name", "group"));
8、恢复任务
scheduler.resumeTrigger(Trigger.triggerKey("name", "group"));
9、删除任务
// 先对任务进行暂停
scheduler.pauseTrigger(Trigger.triggerKey("name", "group"));
// 然后移除任务
scheduler.unscheduleJob(Trigger.triggerKey("name", "group"));
// 根据任务明细中的withIdentity认证信息对任务进行删除
scheduler.deleteJob(JobKey.jobKey("name", "group"));
四、Quartz动态管理
1、定义jobInfo 的bean
public class JobInfo {
private String jobName;
private String jobGroup;
private String triggerName;
private String triggerGroup;
private String jobClass;
private String cronExpression;
private String jobStatus;
public JobInfo(String jobName, String jobGroup, String triggerName, String triggerGroup, String jobClass, String cronExpression, String jobStatus) {
this.jobName = jobName;
this.jobGroup = jobGroup;
this.triggerName = triggerName;
this.triggerGroup = triggerGroup;
this.jobClass = jobClass;
this.cronExpression = cronExpression;
this.jobStatus = jobStatus;
}
public String getJobName() {
return jobName;
}
public void setJobName(String jobName) {
this.jobName = jobName;
}
public String getJobGroup() {
return jobGroup;
}
public void setJobGroup(String jobGroup) {
this.jobGroup = jobGroup;
}
public String getTriggerName() {
return triggerName;
}
public void setTriggerName(String triggerName) {
this.triggerName = triggerName;
}
public String getTriggerGroup() {
return triggerGroup;
}
public void setTriggerGroup(String triggerGroup) {
this.triggerGroup = triggerGroup;
}
public String getJobClass() {
return jobClass;
}
public void setJobClass(String jobClass) {
this.jobClass = jobClass;
}
public String getCronExpression() {
return cronExpression;
}
public void setCronExpression(String cronExpression) {
this.cronExpression = cronExpression;
}
public String getJobStatus() {
return jobStatus;
}
public void setJobStatus(String jobStatus) {
this.jobStatus = jobStatus;
}
}
2、读取任务列表到List,通常我们会配置到数据库中
模拟从数据库读到List<JobInfo>中
List<JobInfo> jobs = new ArrayList<>();
jobs.add(new JobInfo("test1","group1","test1","group1","com.songdian.taskJob","0 0/2 * * * ?","1"));
jobs.add(new JobInfo("test2","group2","test2","group2","com.songdian.taskJob","0 0/5 * * * ?","1"));
3、遍历List 读取jobInfo 设置每个job信息
SchedulerFactory factory = new StdSchedulerFactory();
Scheduler scheduler = factory.getScheduler();
for (JobInfo job : jobs) {
Class jobClass = Class.forName(job.getJobClass());
JobKey jobKey = JobKey.jobKey(job.getJobName(),job.getJobGroup());
TriggerKey triggerKey = TriggerKey.triggerKey(job.getTriggerName(),job.getTriggerGroup());
JobDetail jobDetail = JobBuilder.newJob(jobClass)
.withIdentity(jobKey)
.storeDurably()
.build();
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity(triggerKey)
.withSchedule(CronScheduleBuilder.cronSchedule(job.getCronExpression()))
.build();
int jobStatus = Integer.valueOf(job.getJobStatus());
switch (jobStatus){
case 1:
scheduler.scheduleJob(jobDetail, trigger);
break;
case 0:
scheduler.scheduleJob(jobDetail,trigger);
scheduler.pauseJob(jobKey);
break;
}
}
//设置监听器
scheduler.getListenerManager().addJobListener(new QuartzJobListener(), EverythingMatcher.allJobs());
scheduler.start();
4、定义job的监听器
public class QuartzJobListener implements JobListener {
@Override
public String getName() {
return "QuartzJobListener";
}
@Override
public void jobToBeExecuted(JobExecutionContext jobExecutionContext) {
System.out.println("MyJobListener.jobToBeExecuted()");
}
@Override
public void jobExecutionVetoed(JobExecutionContext jobExecutionContext) {
System.out.println("MyJobListener.jobExecutionVetoed()");
}
@Override
public void jobWasExecuted(JobExecutionContext jobExecutionContext, JobExecutionException e) {
System.out.println("MyJobListener.jobWasExecuted()");
}
}