Quartz的监听器用于当任务调度中你所关注事件发生时,能够及时获取这一事件的通知。类似于任务执行过程中的邮件、短信类的提醒。
Quartz监听器主要有JobListener、TriggerListener、SchedulerListener三种,顾名思义,分别表示任务、触发器、调度器对应的监听器。三者的使用方法类似,在开始介绍三种监听器之前,需要明确两个概念:全局监听器与非全局监听器,二者的区别在于:
全局监听器能够接收到所有的Job/Trigger的事件通知,
非全局监听器只能接收到在其上注册的Job或Trigger的事件,不在其上注册的Job或Trigger则不会进行监听。
1、JobListener job监听器
在job执行之前,之后或者执行过程中动态去添加一些额外的动作。
- 任务调度过程中,与任务Job相关的事件包括:job开始要执行的提示; job执行完成的提示。
- JobListener监听器:
public interface JobListener {
// 用于获取该JobListener的名称。
String getName();
// Scheduler在JobDetail将要被执行时调用这个方法.
void jobToBeExecuted(JobExecutionContext var1);
// Scheduler在JobDetail即将被执行,但又被TriggerListerner否决时会调用该方法.
void jobExecutionVetoed(JobExecutionContext var1);
// Scheduler在JobDetail被执行之后调用这个方法.
void jobWasExecuted(JobExecutionContext var1, JobExecutionException var2);
}
3、案例使用JobListener
- 自定义一个Job
public class HelloJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
//输出当前时间的job
Date date = new Date();
SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateString = simpleDateFormat.format(date);
System.out.println("正在进行数据库备份工作,备份数据库的时间是"+dateString);
}
}
- 自定义一个JobListener
public class MyListener implements JobListener {
@Override
public String getName() {
String simpleName = this.getClass().getSimpleName();
System.out.println("监听器的名称是:"+simpleName);
return simpleName;
}
@Override
public void jobToBeExecuted(JobExecutionContext jobExecutionContext) {
String name = jobExecutionContext.getJobDetail().getKey().getName();
System.out.println("Scheduler在jobDetail将要被执行时调用的方法"+name);
}
@Override
public void jobExecutionVetoed(JobExecutionContext jobExecutionContext) {
String name = jobExecutionContext.getJobDetail().getKey().getName();
System.out.println("job将要被执行,但是又被trigger否决时执行的方法:"+name);
}
@Override
public void jobWasExecuted(JobExecutionContext jobExecutionContext, JobExecutionException e) {
String name = jobExecutionContext.getJobDetail().getKey().getName();
System.out.println("job被执行后调用的方法:"+name);
}
}
- 注册监听器到Scheduler
public class HelloSchedulerDemoListener {
public static void main(String[] args) throws SchedulerException {
//1:调度器(Scheduler),从工厂中获取调度实例,默认是实例化了new StdSchedulerFactory
//Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
StdSchedulerFactory stdSchedulerFactory=new StdSchedulerFactory();
Scheduler scheduler=stdSchedulerFactory.getScheduler();
//2:任务实例(JobDetail)
//加载任务类,与HelloJob完成绑定,要求HelloJob实现Job接口
JobDetail jobDetail = JobBuilder.newJob(HelloJob.class)
//参数1:任务的名称,(唯一实例)。参数2:任务组的名称
.withIdentity("job1", "group1")
.usingJobData("message","打印JobDetail日志")
.usingJobData("count",0)
.build();
//3:触发器(Trigger)
Trigger trigger = TriggerBuilder.newTrigger()
//参数1:触发器名称,触发器组的名称
.withIdentity("trigger1", "group1")
.startNow()//马上启动
//使用日历触发器
.withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?"))
// .withSchedule(SimpleScheduleBuilder.simpleSchedule().repeatForever().withIntervalInSeconds(5))
//指定时间启动
.usingJobData("message","打印Trigger日志")
.build();
//4. 使用调度器将触发器和任务jobdetail关联
Date date = scheduler.scheduleJob(jobDetail, trigger);
SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("调度器开始调度时间"+dateFormat.format(date));
// 6. 创建并注册一个全局的Job Listener
//scheduler.getListenerManager().addJobListener(new MyListener(), EverythingMatcher.allJobs());
//7. 创建一个局部的Job Listener 所谓的局部就是指定的job
scheduler.getListenerManager().addJobListener(new MyListener(), KeyMatcher.keyEquals(JobKey.jobKey("job1","group1")));
//5. 启动触发器
scheduler.start();
}
}
2、TriggerListener 触发器监听器
TriggerListener 有一个TriggerListenerSupport的抽象类,即我们也可以继承这个类,只实现其中的部分业务关注的方法。
- 使用方法和JobListener相同,主要是监听触发器的一些情况:任务调度过程中,与触发器Trigger相关的事件包括:触发器触发、触发器未正常触发、触发器完成等。
public interface TriggerListener {
// 用于获取触发器的名称
public String getName();
// 当与监听器相关联的Trigger被触发,Job上的execute()方法将被执行时,Scheduler就调用该方法.
public void triggerFired(Trigger trigger, JobExecutionContext context);
/* 在 Trigger 触发后,Job 将要被执行时由 Scheduler 调用这个方法。TriggerListener 给
了一个选择去否决 Job 的执行。假如这个方法返回 true,这个 Job 将不会为此次 Trigger 触发而得到执行。
*/
public boolean vetoJobExecution(Trigger trigger, JobExecutionContext context);
/*
Scheduler 调用这个方法是在 Trigger 错过触发时。你应该关注此方法中持续时间长的逻辑:
在出现许多错过触发的 Trigger 时,长逻辑会导致骨牌效应。你应当保持这上方法尽量的小。
*/
public void triggerMisfired(Trigger trigger);
// Trigger 被触发并且完成了 Job 的执行时,Scheduler 调用这个方法。
public void triggerComplete(Trigger trigger, JobExecutionContext context,
int triggerInstructionCode);
}
2、案例 TriggerListener
- job
- TriggerListener
public class MyTriggerListener implements TriggerListener {
private String name;
public MyTriggerListener(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
@Override
public void triggerFired(Trigger trigger, JobExecutionContext context) {
String triggerName = trigger.getKey().getName();
System.out.println(triggerName + " 被触发");
}
@Override
public boolean vetoJobExecution(Trigger trigger, JobExecutionContext context) {
String triggerName = trigger.getKey().getName();
System.out.println(triggerName + " 没有被触发");
return true; // true:表示不会执行Job的方法
}
@Override
public void triggerMisfired(Trigger trigger) {
String triggerName = trigger.getKey().getName();
System.out.println(triggerName + " 错过触发");
}
@Override
public void triggerComplete(Trigger trigger, JobExecutionContext context,
Trigger.CompletedExecutionInstruction triggerInstructionCode) {
String triggerName = trigger.getKey().getName();
System.out.println(triggerName + " 完成之后触发");
}
}
- Scheduler调度
public class HelloSchedulerDemoListener {
public static void main(String[] args) throws SchedulerException {
//1:调度器(Scheduler),从工厂中获取调度实例,默认是实例化了new StdSchedulerFactory
//Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
StdSchedulerFactory stdSchedulerFactory=new StdSchedulerFactory();
Scheduler scheduler=stdSchedulerFactory.getScheduler();
//2:任务实例(JobDetail)
//加载任务类,与HelloJob完成绑定,要求HelloJob实现Job接口
JobDetail jobDetail = JobBuilder.newJob(HelloJob.class)
//参数1:任务的名称,(唯一实例)。参数2:任务组的名称
.withIdentity("job1", "group1")
.usingJobData("message","打印JobDetail日志")
.usingJobData("count",0)
.build();
//3:触发器(Trigger)
Trigger trigger = TriggerBuilder.newTrigger()
//参数1:触发器名称,触发器组的名称
.withIdentity("trigger1", "group1")
.startNow()//马上启动
//使用日历触发器
.withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?"))
// .withSchedule(SimpleScheduleBuilder.simpleSchedule().repeatForever().withIntervalInSeconds(5))
//指定时间启动
.usingJobData("message","打印Trigger日志")
.build();
//4. 使用调度器将触发器和任务jobdetail关联
Date date = scheduler.scheduleJob(jobDetail, trigger);
SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("调度器开始调度时间"+dateFormat.format(date));
// 6. 创建并注册一个全局的Job Listener
//scheduler.getListenerManager().addJobListener(new MyListener(), EverythingMatcher.allJobs());
//7. 创建一个局部的Job Listener 所谓的局部就是指定的job
// scheduler.getListenerManager().addJobListener(new MyListener(), KeyMatcher.keyEquals(JobKey.jobKey("job1","group1")));
// 8. 创建并注册一个全局的Trigger Listener
scheduler.getListenerManager().addTriggerListener(new MyTriggerListener("simpleTrigger"), EverythingMatcher.allTriggers());
// 9. 创建并注册一个局部的Trigger Listener
// scheduler.getListenerManager().addTriggerListener(new MyTriggerListener("simpleTrigger"), KeyMatcher.keyEquals(TriggerKey.triggerKey("trigger1", "group1")));
//5. 启动触发器
scheduler.start();
}
}
3、SchedulerListener 调度监听
SchedulerListener会在Scheduler的生命周期中关键事件发生时被调用。与Scheduler有关的事件包括:增加一个job/trigger,删除一个job/trigger,scheduler发生严重错误,关闭scheduler等。
在接口实现上,可以实现SchedulerListener,也可以继承SchedulerListenerSupport抽象类。
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。参数将为 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();
}