参考地址:https://www.cnblogs.com/mengrennwpu/p/7191229.html
1. 概述
Quartz的监听器用于当任务调度中你所关注事件发生时,能够及时获取这一事件的通知。类似于任务执行过程中的邮件、短信类的提醒。Quartz监听器主要有JobListener、TriggerListener、SchedulerListener三种,顾名思义,分别表示任务、触发器、调度器对应的监听器。三者的使用方法类似,在开始介绍三种监听器之前,需要明确两个概念:全局监听器与非全局监听器,二者的区别在于:全局监听器能够接收到所有的Job/Trigger的事件通知,而非全局监听器只能接收到在其上注册的Job或Trigger的事件,不在其上注册的Job或Trigger则不会进行监听。关于全局与非全局的监听器的使用,在本文中会做一介绍。
2、JobListener简介
JobListener 可用于监听定时任务执行的事,并在定时任务执行前后做一些自定义操作,类似于java 切面编程的环绕通知。需要注意的是quartz 2.x系列,监听器已不再进行持久化操作,自然也就没有分布式监听这一说了。在quartz 1.x 时, 数据库表还有监听器相关的表。
任务调度过程中,与任务Job相关的事件包括:job开始要执行的提示;job执行完成的提示等。其接口如下:
public interface JobListener {
// 监听器名称
public String getName();
// 定时任务执行前执行, 相当于切面编程中的前置通知
public void jobToBeExecuted(JobExecutionContext context);
// JobDetail即将被执行,但又被TriggerListerner否决时会调用该方法
public void jobExecutionVetoed(JobExecutionContext context);
// 定时任务执行后执行, 相当于切面编程中的后置通知
public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException);
}
第一种创建JobListener的方法是实现JobListener接口,另一种是继承JobListenerSupport类, 只需实现自己关注的方法即可
package org.quartz.listeners;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public abstract class JobListenerSupport implements JobListener {
private final Logger log = LoggerFactory.getLogger(this.getClass());
public JobListenerSupport() {
}
protected Logger getLog() {
return this.log;
}
public void jobToBeExecuted(JobExecutionContext context) {
}
public void jobExecutionVetoed(JobExecutionContext context) {
}
public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {
}
}
3、自定义JobListener
3.1 新建Job
package com.zdw.zixue.job;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
public class ListenerJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println("---测试JobListener的Job---");
}
}
3.2 自定义JobListener
package com.zdw.zixue.listener;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobListener;
/**
* Create By zdw on 2019/9/26
*/
public class MyJobListener implements JobListener {
@Override
public String getName() {
String simpleName = getClass().getSimpleName();
System.out.println("自定义监听器名称:"+simpleName);
return simpleName;
}
@Override
public void jobToBeExecuted(JobExecutionContext jobExecutionContext) {
String name = jobExecutionContext.getJobDetail().getKey().getName();
System.out.println(name+"定时任务执行了");
}
@Override
public void jobExecutionVetoed(JobExecutionContext jobExecutionContext) {
String name = jobExecutionContext.getJobDetail().getKey().getName();
System.out.println(name+"定时任务快要执行时,但又TriggerListerner否决");
}
@Override
public void jobWasExecuted(JobExecutionContext jobExecutionContext, JobExecutionException e) {
String name = jobExecutionContext.getJobDetail().getKey().getName();
System.out.println(name+"定时任务执行完成了");
}
}
3.3 调度器的创建
package com.zdw.zixue.quartz;
import com.zdw.zixue.job.ListenerJob;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import static org.quartz.DateBuilder.futureDate;
/**
* 该类是Quartz的服务类,用来创建程序调度器,JobDetail,Trigger等
*/
public class QuartzServerForJobListener {
//创建调度容器Scheduler
public static Scheduler createScheduler() throws SchedulerException {
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
return scheduler;
}
//创建JobDetail
public static JobDetail createJobDetail(String jobName, String jobGroup){
JobDetail jobDetail = JobBuilder.newJob(ListenerJob.class)//设置执行任务的类
.withIdentity(jobName, jobGroup)//job名称与job组名称组成Scheduler中任务的唯一标识
.build();//构建
return jobDetail;
}
//创建trigger
public static Trigger createTrigger(String triggerName, String triggerGroup){
SimpleTrigger simpleTrigger = TriggerBuilder.newTrigger()
.withIdentity(triggerName, triggerGroup)trigger名称与trigger组名称组成Scheduler中任务的唯一标识
.startAt(futureDate(2, DateBuilder.IntervalUnit.SECOND))//2秒后执行,并且只执行一次
.withSchedule(SimpleScheduleBuilder.simpleSchedule())
.build();//构建
return simpleTrigger;
}
}
3.4 调度器的执行及绑定监听器
package com.zdw.zixue.test;
import com.zdw.zixue.listener.MyJobListener;
import com.zdw.zixue.quartz.QuartzServer;
import com.zdw.zixue.quartz.QuartzServerForJobListener;
import org.quartz.*;
import org.quartz.impl.matchers.EverythingMatcher;
import org.quartz.impl.matchers.GroupMatcher;
import org.quartz.impl.matchers.KeyMatcher;
public class ListenerJobTest {
public static void main(String[] args) throws SchedulerException, InterruptedException {
Scheduler scheduler = QuartzServerForJobListener.createScheduler();//创建调度器
//创建两个JobDetail
JobDetail jobDetail = QuartzServerForJobListener.createJobDetail("listenerJob1","listenerGroup1");//创建任务
JobDetail jobDetail2 = QuartzServerForJobListener.createJobDetail("listenerJob2","listenerGroup2");//创建任务
//创建两个Trigger
Trigger trigger = QuartzServerForJobListener.createTrigger("listenerTrigger1","listenerTriggerGroup1");//创建触发器
Trigger trigger2 = QuartzServerForJobListener.createTrigger("listenerTrigger2","listenerTriggerGroup2");//创建触发器
//构建调度任务
scheduler.scheduleJob(jobDetail,trigger);
scheduler.scheduleJob(jobDetail2,trigger2);
//创建并注册一个全局的Job Listener,监听所有的Job,注册监听器到调度器
scheduler.getListenerManager().addJobListener(new MyJobListener(), EverythingMatcher.allJobs());
//创建一个只监听listenerJob1的监听器
//scheduler.getListenerManager().addJobListener(new MyJobListener(),KeyMatcher.keyEquals(JobKey.jobKey("listenerJob1","listenerGroup1")));
//开启任务
scheduler.start();
//5s后关闭调度器
Thread.sleep(50000);
scheduler.shutdown();
}
}
第一次是创建的全局监听器,执行结果:
listenerJob1定时任务执行了
listenerJob2定时任务执行了
---测试JobListener的Job---
---测试JobListener的Job---
listenerJob1定时任务执行完成了
listenerJob2定时任务执行完成了
注释掉上面的创建监听器的代码,放开注释掉的代码,那就是创建的只监听listenerJob1的监听器,结果:
listenerJob1定时任务执行了
---测试JobListener的Job---
---测试JobListener的Job---
listenerJob1定时任务执行完成了
备注:除了代码中将对应的job注册到监听器中的两种方法,也有如下几种其他方法:
1) 将同一任务组的任务注册到监听器中
scheduler.getListenerManager().addJobListener(new MyJobListener(), GroupMatcher.jobGroupEquals("listenerGroup1"));
2) 将两个任务组的任务注册到监听器中
scheduler.getListenerManager().addJobListener(new MyJobListener(), OrMatcher.or(GroupMatcher.jobGroupEquals("listenerGroup1"), GroupMatcher.jobGroupEquals("listenerGroup2")));
4.TriggerListener
TriggerListner 用于监听触发器的相关创建,用于在触发器触发前后做一些自定义操作。quartz 中TriggerListener的设计思想和JobListener 的设计思想如出一辙,和JobListener 类似,quartz 2.x 也不再进行持久化操作。
quartz 提供了两种方式自定义自己的TriggerListener,一种是实现TriggerListener接口,需要实现所有Listener 自定义的方法;另一种是继承TriggerListenerSupport类,只需实现自己关注的方法即可。
任务调度过程中,与触发器Trigger相关的事件包括:触发器触发、触发器未正常触发、触发器完成等。TriggerListener的接口如下:
public interface TriggerListener {
// 返回trigger名称
String getName();
// 当与监听器相关联的Trigger被触发,Job上的execute()方法将被执行时,Scheduler就调用该方法。
void triggerFired(Trigger trigger, JobExecutionContext context);
//在 Trigger 触发后,Job 将要被执行时由 Scheduler 调用这个方法。TriggerListener 给了一个选择去否决 Job 的执行。假如这个方法返回 true,这个 Job 将不会为此次 Trigger 触发而得到执行。
boolean vetoJobExecution(Trigger trigger, JobExecutionContext context);
// Scheduler 调用这个方法是在 Trigger 错过触发时。你应该关注此方法中持续时间长的逻辑:在出现许多错过触发的 Trigger 时,长逻辑会导致骨牌效应。你应当保持这上方法尽量的小。
void triggerMisfired(Trigger trigger);
// 触发器关联定时任务完成后调用此方法
void triggerComplete(Trigger trigger, JobExecutionContext context, CompletedExecutionInstruction triggerInstructionCode);
}
4.1 创建Job
package com.zdw.zixue.job;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
public class ListenerTrigger implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println("---测试TriggerListener的Job---");
}
}
4.2 创建自定义的TriggerListener
package com.zdw.zixue.listener;
import org.quartz.*;
public class MyTriggerListener implements TriggerListener {
@Override
public String getName() {
return "myTriggerListener";//这里不能返回空
}
@Override
public void triggerFired(Trigger trigger, JobExecutionContext jobExecutionContext) {
String triggerName = trigger.getKey().getName();
System.out.println(triggerName+"触发器被触发了");
}
@Override
public boolean vetoJobExecution(Trigger trigger, JobExecutionContext jobExecutionContext) {
return false;
}
@Override
public void triggerMisfired(Trigger trigger) {
}
@Override
public void triggerComplete(Trigger trigger, JobExecutionContext jobExecutionContext, Trigger.CompletedExecutionInstruction completedExecutionInstruction) {
String triggerName = trigger.getKey().getName();
System.out.println(triggerName+"触发器完成了------------");
}
}
4.3 调度器
package com.zdw.zixue.quartz;
import com.zdw.zixue.job.ListenerJob;
import com.zdw.zixue.job.ListenerTrigger;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import static org.quartz.DateBuilder.futureDate;
/**
* 该类是Quartz的服务类,用来创建程序调度器,JobDetail,Trigger等
*/
public class QuartzServerForTriggerListener {
//创建调度容器Scheduler
public static Scheduler createScheduler() throws SchedulerException {
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
return scheduler;
}
//创建JobDetail
public static JobDetail createJobDetail(String jobName, String jobGroup){
JobDetail jobDetail = JobBuilder.newJob(ListenerTrigger.class)//设置执行任务的类
.withIdentity(jobName, jobGroup)//job名称与job组名称组成Scheduler中任务的唯一标识
.build();//构建
return jobDetail;
}
//创建trigger
public static Trigger createTrigger(String triggerName, String triggerGroup){
SimpleTrigger simpleTrigger = TriggerBuilder.newTrigger()
.withIdentity(triggerName, triggerGroup)trigger名称与trigger组名称组成Scheduler中任务的唯一标识
.startAt(futureDate(2, DateBuilder.IntervalUnit.SECOND))//2秒后执行,并且只执行一次
.withSchedule(SimpleScheduleBuilder.simpleSchedule())
.build();//构建
return simpleTrigger;
}
}
4.4 调度器的执行及绑定监听器
package com.zdw.zixue.test;
import com.zdw.zixue.listener.MyJobListener;
import com.zdw.zixue.listener.MyTriggerListener;
import com.zdw.zixue.quartz.QuartzServerForJobListener;
import com.zdw.zixue.quartz.QuartzServerForTriggerListener;
import org.quartz.*;
import org.quartz.impl.matchers.EverythingMatcher;
import org.quartz.impl.matchers.KeyMatcher;
public class ListenerTriggerTest {
public static void main(String[] args) throws SchedulerException, InterruptedException {
Scheduler scheduler = QuartzServerForTriggerListener.createScheduler();//创建调度器
//创建两个JobDetail
JobDetail jobDetail = QuartzServerForTriggerListener.createJobDetail("listenerJob1","listenerGroup1");//创建任务
JobDetail jobDetail2 = QuartzServerForTriggerListener.createJobDetail("listenerJob2","listenerGroup2");//创建任务
//创建两个Trigger
Trigger trigger = QuartzServerForTriggerListener.createTrigger("listenerTrigger1","listenerTriggerGroup1");//创建触发器
Trigger trigger2 = QuartzServerForTriggerListener.createTrigger("listenerTrigger2","listenerTriggerGroup2");//创建触发器
//构建调度任务
scheduler.scheduleJob(jobDetail,trigger);
scheduler.scheduleJob(jobDetail2,trigger2);
//创建并注册一个全局的Trigger Listener,监听所有的Trigger,注册监听器到调度器
scheduler.getListenerManager().addTriggerListener(new MyTriggerListener(), EverythingMatcher.allTriggers());
// 创建并注册一个局部的Trigger Listener
//scheduler.getListenerManager().addTriggerListener(new MyTriggerListener(), KeyMatcher.keyEquals(TriggerKey.triggerKey("listenerTrigger1", "listenerTriggerGroup1")));
//开启任务
scheduler.start();
//5s后关闭调度器
Thread.sleep(5000);
scheduler.shutdown();
}
}
上面代码种,是全局的监听器,执行结果:
listenerTrigger1触发器被触发了
listenerTrigger2触发器被触发了
---测试TriggerListener的Job---
---测试TriggerListener的Job---
listenerTrigger2触发器完成了------------
listenerTrigger1触发器完成了------------
放开上面的注释,并注释掉上面那个全局监听的代码,执行结果:
listenerTrigger1触发器被触发了
---测试TriggerListener的Job---
---测试TriggerListener的Job---
listenerTrigger1触发器完成了------------
5. SchedulerListener
SchedulerListener 是用于监控调度器scheduler 中添加,删除定时任务或触发器等操作。和JobListener,TriggerListener类似,但又有不同。SchedulerListener 全局唯一,也就是说一个Scheduler 只能配置一个SchedulerListener 监听器。
SchedulerListener会在Scheduler的生命周期中关键事件发生时被调用。与Scheduler有关的事件包括:增加一个job/trigger,删除一个job/trigger,scheduler发生严重错误,关闭scheduler等。
和JobListener/TriggerListener类似,自定义SchedulerListener 需要实现SchedulerListener接口或继承SchedulerListenerSupport,并重写关注的方法。这里推荐使用第二种方式,因为第一种方式需要实现方法太多。
SchedulerListener 定义的接口方法,每一个方法都是监听对应的Scheduler中定义的方法。
SchedulerListener 也不会持久化到数据库,更不支持分布式,需要每次启动应用时注册。
SchedulerListener的接口如下:
public interface SchedulerListener {
//用于部署JobDetail时调用
public void jobScheduled(Trigger trigger);
//用于卸载JobDetail时调用
public void jobUnscheduled(String triggerName, String triggerGroup);
//当一个 Trigger 来到了再也不会触发的状态时调用这个方法。除非这个 Job 已设置成了持久性,否则它就会从 Scheduler 中移除。
public void triggerFinalized(Trigger trigger);
//Scheduler 调用这个方法是发生在一个 Trigger 或 Trigger 组被暂停时。假如是 Trigger 组的话,triggerName 参数将为 null。
public void triggersPaused(String triggerName, String triggerGroup);
//Scheduler 调用这个方法是发生成一个 Trigger 或 Trigger 组从暂停中恢复时。假如是 Trigger 组的话,假如是 Trigger 组的话,triggerName 参数将为 null
public void triggersResumed(String triggerName, String triggerGroup);
//当一个或一组 JobDetail 暂停时调用这个方法
public void jobsPaused(String jobName, String jobGroup);
//当一个或一组 Job 从暂停上恢复时调用这个方法。假如是一个 Job 组,jobName 参数将为 null
public void jobsResumed(String jobName, String jobGroup);
//在 Scheduler 的正常运行期间产生一个严重错误时调用这个方法
public void schedulerError(String msg, SchedulerException cause);
//当Scheduler 开启时,调用该方法
public void schedulerStarted();
//当Scheduler处于StandBy模式时,调用该方法
public void schedulerInStandbyMode();
//当Scheduler停止时,调用该方法
public void schedulerShutdown();
//当Scheduler中的数据被清除时,调用该方法
public void schedulingDataCleared();
}
5.1 创建Job
package com.zdw.zixue.job;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
public class SchedulerListenerJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println("---测试SchedulerListener的Job---");
}
}
5.2 创建自定义的SchedulerListener
package com.zdw.zixue.listener;
import org.quartz.*;
/**
* Create By zdw on 2019/9/26
*/
public class MyShcedulerListener implements SchedulerListener {
@Override
public void jobScheduled(Trigger trigger) {
String jobName = trigger.getJobKey().getName();
System.out.println(jobName+"创建了一个JobDetail");
}
@Override
public void jobUnscheduled(TriggerKey triggerKey) {
}
@Override
public void triggerFinalized(Trigger trigger) {
}
@Override
public void triggerPaused(TriggerKey triggerKey) {
}
@Override
public void triggersPaused(String s) {
}
@Override
public void triggerResumed(TriggerKey triggerKey) {
}
@Override
public void triggersResumed(String s) {
}
@Override
public void jobAdded(JobDetail jobDetail) {
}
@Override
public void jobDeleted(JobKey jobKey) {
}
@Override
public void jobPaused(JobKey jobKey) {
}
@Override
public void jobsPaused(String s) {
}
@Override
public void jobResumed(JobKey jobKey) {
}
@Override
public void jobsResumed(String s) {
}
@Override
public void schedulerError(String s, SchedulerException e) {
}
@Override
public void schedulerInStandbyMode() {
}
@Override
public void schedulerStarted() {
System.out.println("---调度器开启了---");
}
@Override
public void schedulerStarting() {
System.out.println("---调度器开启ing---");
}
@Override
public void schedulerShutdown() {
System.out.println("---调度器关闭了---");
}
@Override
public void schedulerShuttingdown() {
System.out.println("---调度器关闭ing---");
}
@Override
public void schedulingDataCleared() {
}
}
5.3 创建调度器
package com.zdw.zixue.quartz;
import com.zdw.zixue.job.ListenerTrigger;
import com.zdw.zixue.job.SchedulerListenerJob;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import static org.quartz.DateBuilder.futureDate;
/**
* 该类是Quartz的服务类,用来创建程序调度器,JobDetail,Trigger等
*/
public class QuartzServerForSchedulerListener {
//创建调度容器Scheduler
public static Scheduler createScheduler() throws SchedulerException {
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
return scheduler;
}
//创建JobDetail
public static JobDetail createJobDetail(String jobName, String jobGroup){
JobDetail jobDetail = JobBuilder.newJob(SchedulerListenerJob.class)//设置执行任务的类
.withIdentity(jobName, jobGroup)//job名称与job组名称组成Scheduler中任务的唯一标识
.build();//构建
return jobDetail;
}
//创建trigger
public static Trigger createTrigger(String triggerName, String triggerGroup){
SimpleTrigger simpleTrigger = TriggerBuilder.newTrigger()
.withIdentity(triggerName, triggerGroup)trigger名称与trigger组名称组成Scheduler中任务的唯一标识
.startAt(futureDate(2, DateBuilder.IntervalUnit.SECOND))//2秒后执行,并且只执行一次
.withSchedule(SimpleScheduleBuilder.simpleSchedule())
.build();//构建
return simpleTrigger;
}
}
5.4 调度器执行及绑定监听器
package com.zdw.zixue.test;
import com.zdw.zixue.listener.MyShcedulerListener;
import com.zdw.zixue.listener.MyTriggerListener;
import com.zdw.zixue.quartz.QuartzServerForJobListener;
import org.quartz.*;
import org.quartz.impl.matchers.KeyMatcher;
public class SchedulerTriggerTest {
public static void main(String[] args) throws SchedulerException, InterruptedException {
Scheduler scheduler = QuartzServerForJobListener.createScheduler();//创建调度器
//创建JobDetail
JobDetail jobDetail = QuartzServerForJobListener.createJobDetail("listenerJob1","listenerGroup1");//创建任务
//创建Trigger
Trigger trigger = QuartzServerForJobListener.createTrigger("listenerTrigger1","listenerTriggerGroup1");//创建触发器
//构建调度任务
scheduler.scheduleJob(jobDetail,trigger);
//创建SchedulerListener,监听所有的Trigger,注册监听器到调度器
scheduler.getListenerManager().addSchedulerListener(new MyShcedulerListener());
//移除对应的SchedulerListener
//scheduler.getListenerManager().removeSchedulerListener(new MyShcedulerListener());
//开启任务
scheduler.start();
//5s后关闭调度器
Thread.sleep(5000);
scheduler.shutdown();
}
}
执行结果:
---调度器开启ing---
---调度器开启了---
---测试JobListener的Job---
---调度器关闭ing---
---调度器关闭了---