Quartz的监听器用于当任务调度中你所关注事件发生时,能够及时获取这一事件的通知。类似于任务执行过程中的邮件、短信类的提醒。Quartz监听器主要有JobListener、TriggerListener、SchedulerListener三种,分别表示任务、触发器、调度器对应的监听器。三者的使用方法类似,在开始介绍三种监听器之前,需要明确两个概念:全局监听器与非全局监听器,二者的区别在于:全局监听器能够接收到所有的Job/Trigger的事件通知,而非全局监听器只能接收到在其上注册的Job或Trigger的事件,不在其上注册的Job或Trigger则不会进行监听。
一、TriggerListener
跟触发器有关的事件包括:触发器被触发,触发器触发失败,以及触发器触发完成(触发器完成后作业任务开始运行)。
TriggerListener 接口源码
public interface ITriggerListener
{
string Name { get; }
void TriggerFired(ITrigger trigger, IJobExecutionContext context);
bool VetoJobExecution(ITrigger trigger, IJobExecutionContext context);
void TriggerMisfired(ITrigger trigger);
void TriggerComplete(ITrigger trigger, IJobExecutionContext context, int triggerInstructionCode);
}
含义:
- 1getName方法:用于获取触发器的名称
- triggerFired方法:当与监听器相关联的Trigger被触发,Job上的execute()方法将被执行时,Scheduler就调用该方法。
- vetoJobExecution方法:在 Trigger 触发后,Job 将要被执行时由 Scheduler 调用这个方法。TriggerListener 给了一个选择去否决 Job 的执行。假如这个方法返回 true,这个 Job 将不会为此次 Trigger 触发而得到执行。
- triggerMisfired方法:Scheduler 调用这个方法是在 Trigger 错过触发时。你应该关注此方法中持续时间长的逻辑:在出现许多错过触发的 Trigger 时,长逻辑会导致骨牌效应。你应当保持这上方法尽量的小。
- triggerComplete方法:Trigger 被触发并且完成了 Job 的执行时,Scheduler 调用这个方法。
使用:
- 创建一个监听器,实现org.quartz.TriggerListener或org.quartz.JobListener接口的对象即可。监听器会在运行期间注册到调度器中,并且必须要给定监听器名(更确切地说,监听器会调用getName方法获取自己的名字)。
- 监听器注册到调度器中的监听器管理类时还携带着一个匹配器,这个匹配器描述了作业任务和触发器的监听器想接收的事件。
- 监听器在运行期间注册到调度中,但是不会把作业任务和触发器存储到JobStore中。那是因为监听器在你的应用中通常是一些点的集合。因此,每次应用运行时,监听器都需要重新在调度器中注册。
示例:
TimerJob类:
package com.ghuiqun.timer;
import java.util.Date;
import java.util.List;
import org.apache.log4j.Logger;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import com.gzhuiqun.listener.TimerJobListener;
/*
*
* 定义需要执行的任务。该类是一个接口,只定义一个方法 execute(JobExecutionContext context)
在实现类的 execute 方法中编写所需要定时执行的 Job(任务), JobExecutionContext 类提供了调度应用的一些信息。
Job 运行时的信息保存在 JobDataMap 实例中。
*/
public class TimerJob implements Job {
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
Logger logger = Logger.getLogger(TimerJobListener.class);
logger.info("坚持 坚持 在坚持,永不放弃"+ new Date());
System.out.println("坚持 坚持 在坚持,永不放弃"+ new Date());
}
}
TimerTriggerListerner类:
package com.gzhuiqun.listener;
import org.apache.log4j.Logger;
import org.quartz.JobExecutionContext;
import org.quartz.Trigger;
import org.quartz.Trigger.CompletedExecutionInstruction;
import org.quartz.TriggerListener;
/**
* @author Administrator
* 跟触发器有关的事件包括:触发器被触发,触发器触发失败,以及触发器触发完成(触发器完成后作业任务开始运行)。
*/
public class TimerTriggerListener implements TriggerListener{
Logger logger = Logger.getLogger(TimerTriggerListener.class);
private String timerTriggerName="";
public TimerTriggerListener(String timerTriggerName) {
this.timerTriggerName = timerTriggerName;
}
@Override
public String getName() {
// TODO Auto-generated method stub
logger.info(timerTriggerName);
System.out.println(timerTriggerName);
return timerTriggerName;
}
//触发器触发完成
//(4) 任务完成时触发
@Override
public void triggerComplete(Trigger arg0, JobExecutionContext arg1, CompletedExecutionInstruction arg2) {
// TODO Auto-generated method stub
logger.info("触发器触发完成");
System.out.println("触发器触发完成");
}
//触发器被触发
//(1)Trigger被激发 它关联的job即将被运行
@Override
public void triggerFired(Trigger arg0, JobExecutionContext arg1) {
// TODO Auto-generated method stub
logger.info("Trigger被激发 它关联的job即将被运行");
System.out.println("触发器被触发");
}
//触发器触发失败
//(3) 当Trigger错过被激发时执行,比如当前时间有很多触发器都需要执行,但是线程池中的有效线程都在工作,
//那么有的触发器就有可能超时,错过这一轮的触发。
@Override
public void triggerMisfired(Trigger arg0) {
// TODO Auto-generated method stub
logger.info("触发器触发失败");
System.out.println("触发器触发失败");
}
//(2)Trigger被激发 它关联的job即将被运行,先执行(1),在执行(2) 如果返回TRUE 那么任务job会被终止
@Override
public boolean vetoJobExecution(Trigger arg0, JobExecutionContext arg1) {
// TODO Auto-generated method stub
return false;
}
}
任务调度与运行,及TriggerListener的创建与注册。
package com.ghuiqun.timer;
import org.quartz.CronScheduleBuilder;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.matchers.EverythingMatcher;
import com.gzhuiqun.listener.TimerJobListener;
import com.gzhuiqun.listener.TimerSchedulerListener;
import com.gzhuiqun.listener.TimerTriggerListener;
public class TimerExample {
// 创建 schedulerFactory 工厂
private static SchedulerFactory scheduleFactory= new StdSchedulerFactory();
public static void main(String[] args) {
// TODO Auto-generated method stub
String[] data= {"s","t","r","i","n","g"};
addJob("HelloJob","HelloJobGroup","HelloTrigger","HelloTriggerGroup",TimerJob.class,"0/1 * * * * ?",data);
}
/**添加一个定时任务
* @param jobName 任务名
* @param jobGroupName 任务组名
* @param triggerName 触发器名
* @param triggerGroupName 触发器组名
* @param jobClass 任务类名
* @param cron 时间
*/
public static void addJob(String jobName,String jobGroupName,String triggerName,String triggerGroupName
,Class<? extends Job> jobClass,String cron,String[] data) {
try {
//通过scheduleFactory创建任务调度器
Scheduler scheduler = scheduleFactory.getScheduler();
//创建 jobDetail 实例,绑定 Job 实现类
// 指明 job 的名称,所在组的名称,以及绑定 job 类
JobDetail job = (JobDetail) JobBuilder.newJob(jobClass)
.withIdentity(jobName,jobGroupName)
//.requestRecovery() // 执行中应用发生故障,需要重新执行
.build();
// 初始化参数传递到 job
job.getJobDataMap().put("data",data);
// 定义调度触发规则CronTrigger
//指明 CronTrigger 的名称,所在组的名称,触发时间
Trigger trigger = (Trigger) TriggerBuilder.newTrigger()
.withIdentity(triggerName,triggerGroupName)
.startNow()
.withSchedule(CronScheduleBuilder.cronSchedule(cron))
.build();
// 把作业和触发器注册到任务调度中
scheduler.scheduleJob(job,trigger);
// 创建并注册一个全局的TriggerListener
scheduler.getListenerManager().addTriggerListener(new TimerTriggerListener("TimerTrigger"), EverythingMatcher.allTriggers());
// 创建并注册一个局部的TriggerListener
// scheduler.getListenerManager().addTriggerListener(new TimerTriggerListener("TimerTrigger"), KeyMatcher.keyEquals(TriggerKey.triggerKey(triggerName, triggerGroupName)));
// 创建并注册一个特定组的TriggerListener
// scheduler.getListenerManager().addTriggerListener(new TimerTriggerListener("TimerTrigger"), GroupMatcher.groupEquals(triggerGroupName));
//启动
if(!scheduler.isShutdown()) {
scheduler.start();
System.out.println("开始调度任务");
}
} catch (SchedulerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
结果:
2019-04-03 10:16:53 [ main:592 ] - [ INFO ] TimerTrigger
2019-04-03 10:16:53 [ main:592 ] - [ INFO ] TimerTrigger
2019-04-03 10:16:53 [ main:592 ] - [ INFO ] TimerTrigger
2019-04-03 10:16:53 [ main:592 ] - [ INFO ] TimerTrigger
2019-04-03 10:16:53 [ main:607 ] - [ INFO ] TimerTrigger
2019-04-03 10:16:53 [ main:607 ] - [ INFO ] 触发器触发失败
2019-04-03 10:16:53 [ main:629 ] - [ INFO ] TimerTrigger
2019-04-03 10:16:53 [ main:629 ] - [ INFO ] 触发器触发失败
2019-04-03 10:16:53 [ MyScheduler_Worker-1:708 ] - [ INFO ] TimerTrigger
2019-04-03 10:16:53 [ MyScheduler_Worker-1:709 ] - [ INFO ] Trigger被激发 它关联的job即将被运行
2019-04-03 10:16:53 [ MyScheduler_Worker-1:711 ] - [ INFO ] 坚持 坚持 在坚持,永不放弃Wed Apr 03 10:16:53 CST 2019
2019-04-03 10:16:53 [ MyScheduler_Worker-1:711 ] - [ INFO ] TimerTrigger
2019-04-03 10:16:53 [ MyScheduler_Worker-1:712 ] - [ INFO ] 触发器触发完成
2019-04-03 10:16:53 [ MyScheduler_Worker-2:814 ] - [ INFO ] TimerTrigger
2019-04-03 10:16:53 [ MyScheduler_Worker-2:814 ] - [ INFO ] Trigger被激发 它关联的job即将被运行
2019-04-03 10:16:53 [ MyScheduler_Worker-2:815 ] - [ INFO ] 坚持 坚持 在坚持,永不放弃Wed Apr 03 10:16:53 CST 2019
2019-04-03 10:16:53 [ MyScheduler_Worker-2:815 ] - [ INFO ] TimerTrigger
2019-04-03 10:16:53 [ MyScheduler_Worker-2:815 ] - [ INFO ] 触发器触发完成
2019-04-03 10:16:53 [ MyScheduler_Worker-3:878 ] - [ INFO ] TimerTrigger
2019-04-03 10:16:53 [ MyScheduler_Worker-3:878 ] - [ INFO ] Trigger被激发 它关联的job即将被运行
2019-04-03 10:16:53 [ MyScheduler_Worker-3:878 ] - [ INFO ] 坚持 坚持 在坚持,永不放弃Wed Apr 03 10:16:53 CST 2019
2019-04-03 10:16:53 [ MyScheduler_Worker-3:879 ] - [ INFO ] TimerTrigger
2019-04-03 10:16:53 [ MyScheduler_Worker-3:879 ] - [ INFO ] 触发器触发完成
2019-04-03 10:16:53 [ MyScheduler_Worker-4:905 ] - [ INFO ] TimerTrigger
2019-04-03 10:16:53 [ MyScheduler_Worker-4:905 ] - [ INFO ] Trigger被激发 它关联的job即将被运行
2019-04-03 10:16:53 [ MyScheduler_Worker-4:905 ] - [ INFO ] 坚持 坚持 在坚持,永不放弃Wed Apr 03 10:16:53 CST 2019
2019-04-03 10:16:53 [ MyScheduler_Worker-4:905 ] - [ INFO ] TimerTrigger
2019-04-03 10:16:53 [ MyScheduler_Worker-4:905 ] - [ INFO ] 触发器触发完成
2019-04-03 10:16:54 [ MyScheduler_Worker-5:1470 ] - [ INFO ] TimerTrigger
2019-04-03 10:16:54 [ MyScheduler_Worker-5:1470 ] - [ INFO ] Trigger被激发 它关联的job即将被运行
2019-04-03 10:16:54 [ MyScheduler_Worker-5:1470 ] - [ INFO ] 坚持 坚持 在坚持,永不放弃Wed Apr 03 10:16:54 CST 2019
2019-04-03 10:16:54 [ MyScheduler_Worker-5:1471 ] - [ INFO ] TimerTrigger
2019-04-03 10:16:54 [ MyScheduler_Worker-5:1471 ] - [ INFO ] 触发器触发完成
二、JobListener
跟任务相关的事件包括:job开始要执行的提示; job执行完成的提示灯
JobListener接口源码
public interface JobListener {
public String getName();
public void jobToBeExecuted(JobExecutionContext context);
public void jobExecutionVetoed(JobExecutionContext context);
public void jobWasExecuted(JobExecutionContext context,
JobExecutionException jobException);
}
含义:
- getName方法:用于获取该JobListener的名称。
- jobToBeExecuted方法:Scheduler在JobDetail将要被执行时调用这个方法。
- jobExecutionVetoed方法:Scheduler在JobDetail即将被执行,但又被TriggerListerner否决时会调用该方法
- jobWasExecuted方法:Scheduler在JobDetail被执行之后调用这个方法
示例:
TimerJob类:
package com.ghuiqun.timer;
import java.util.Date;
import java.util.List;
import org.apache.log4j.Logger;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import com.gzhuiqun.listener.TimerJobListener;
/*
*
* 定义需要执行的任务。该类是一个接口,只定义一个方法 execute(JobExecutionContext context)
在实现类的 execute 方法中编写所需要定时执行的 Job(任务), JobExecutionContext 类提供了调度应用的一些信息。
Job 运行时的信息保存在 JobDataMap 实例中。
*/
public class TimerJob implements Job {
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
Logger logger = Logger.getLogger(TimerJobListener.class);
logger.info("坚持 坚持 在坚持,永不放弃"+ new Date());
System.out.println("坚持 坚持 在坚持,永不放弃"+ new Date());
}
}
TimerJobListener类:
package com.gzhuiqun.listener;
import org.apache.log4j.Logger;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobListener;
/**
* @author Administrator
* 跟作业任务相关的事件包括:job即将被执行的通知和job执行完成的通知事件。
*/
public class TimerJobListener implements JobListener {
Logger logger = Logger.getLogger(TimerJobListener.class);
//获取该JobListener的名称
@Override
public String getName() {
// TODO Auto-generated method stub
String name = getClass().getSimpleName();
logger.info(name);
return name;
}
//:Scheduler在JobDetail即将被执行,但又被TriggerListerner否决时会调用该方法
@Override
public void jobExecutionVetoed(JobExecutionContext arg0) {
// TODO Auto-generated method stub
logger.info("Scheduler在JobDetail即将被执行,但又被TriggerListerner否决");
System.out.println("jobExecutionVetoed");
}
//Scheduler在JobDetail将要被执行时调用这个方法。
@Override
public void jobToBeExecuted(JobExecutionContext arg0) {
// TODO Auto-generated method stub
logger.info("Scheduler在JobDetail将要被执行");
System.out.println("jobToBeExecuted");
}
//Scheduler在JobDetail被执行之后调用这个方法
@Override
public void jobWasExecuted(JobExecutionContext arg0, JobExecutionException arg1) {
// TODO Auto-generated method stub
logger.info("Scheduler在JobDetail被执行之后");
System.out.println("jobWasExecuted");
}
}
任务调度与运行,及TimerJobListener的创建与注册。
package com.ghuiqun.timer;
import org.quartz.CronScheduleBuilder;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.matchers.EverythingMatcher;
import com.gzhuiqun.listener.TimerJobListener;
import com.gzhuiqun.listener.TimerSchedulerListener;
import com.gzhuiqun.listener.TimerTriggerListener;
public class TimerExample {
// 创建 schedulerFactory 工厂
private static SchedulerFactory scheduleFactory= new StdSchedulerFactory();
public static void main(String[] args) {
// TODO Auto-generated method stub
String[] data= {"s","t","r","i","n","g"};
addJob("HelloJob1","HelloJobGroup","HelloTrigger1","HelloTriggerGroup",TimerJob.class,"0/1 * * * * ?",data);
}
/**添加一个定时任务
* @param jobName 任务名
* @param jobGroupName 任务组名
* @param triggerName 触发器名
* @param triggerGroupName 触发器组名
* @param jobClass 任务类名
* @param cron 时间
*/
public static void addJob(String jobName,String jobGroupName,String triggerName,String triggerGroupName
,Class<? extends Job> jobClass,String cron,String[] data) {
try {
//通过scheduleFactory创建任务调度器
Scheduler scheduler = scheduleFactory.getScheduler();
//创建 jobDetail 实例,绑定 Job 实现类
// 指明 job 的名称,所在组的名称,以及绑定 job 类
JobDetail job = (JobDetail) JobBuilder.newJob(jobClass)
.withIdentity(jobName,jobGroupName)
//.requestRecovery() // 执行中应用发生故障,需要重新执行
.build();
// 初始化参数传递到 job
job.getJobDataMap().put("data",data);
// 定义调度触发规则CronTrigger
//指明 CronTrigger 的名称,所在组的名称,触发时间
Trigger trigger = (Trigger) TriggerBuilder.newTrigger()
.withIdentity(triggerName,triggerGroupName)
.startNow()
.withSchedule(CronScheduleBuilder.cronSchedule(cron))
.build();
// 把作业和触发器注册到任务调度中
scheduler.scheduleJob(job,trigger);
// 创建并注册一个全局的Job Listener
scheduler.getListenerManager().addJobListener(new TimerJobListener(), EverythingMatcher.allJobs());
// 创建并注册一个指定任务的Job Listener
// scheduler.getListenerManager().addJobListener(new TimerJobListener(), KeyMatcher.keyEquals(JobKey.jobKey(jobName,jobGroupName)));
//启动
if(!scheduler.isShutdown()) {
scheduler.start();
System.out.println("开始调度任务");
}
} catch (SchedulerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
结果:
2019-04-03 10:13:53 [ main:529 ] - [ INFO ] TimerJobListener
2019-04-03 10:13:53 [ main:529 ] - [ INFO ] TimerJobListener
2019-04-03 10:13:53 [ main:529 ] - [ INFO ] TimerJobListener
2019-04-03 10:13:53 [ main:529 ] - [ INFO ] TimerJobListener
2019-04-03 10:13:53 [ MyScheduler_Worker-1:625 ] - [ INFO ] TimerJobListener
2019-04-03 10:13:53 [ MyScheduler_Worker-1:625 ] - [ INFO ] Scheduler在JobDetail将要被执行
2019-04-03 10:13:53 [ MyScheduler_Worker-1:628 ] - [ INFO ] 坚持 坚持 在坚持,永不放弃Wed Apr 03 10:13:53 CST 2019
2019-04-03 10:13:53 [ MyScheduler_Worker-1:628 ] - [ INFO ] TimerJobListener
2019-04-03 10:13:53 [ MyScheduler_Worker-1:628 ] - [ INFO ] Scheduler在JobDetail被执行之后
2019-04-03 10:13:53 [ MyScheduler_Worker-2:647 ] - [ INFO ] TimerJobListener
2019-04-03 10:13:53 [ MyScheduler_Worker-2:647 ] - [ INFO ] Scheduler在JobDetail将要被执行
2019-04-03 10:13:53 [ MyScheduler_Worker-2:648 ] - [ INFO ] 坚持 坚持 在坚持,永不放弃Wed Apr 03 10:13:53 CST 2019
2019-04-03 10:13:53 [ MyScheduler_Worker-2:648 ] - [ INFO ] TimerJobListener
2019-04-03 10:13:53 [ MyScheduler_Worker-2:648 ] - [ INFO ] Scheduler在JobDetail被执行之后
2019-04-03 10:13:54 [ MyScheduler_Worker-3:1094 ] - [ INFO ] TimerJobListener
2019-04-03 10:13:54 [ MyScheduler_Worker-3:1094 ] - [ INFO ] Scheduler在JobDetail将要被执行
2019-04-03 10:13:54 [ MyScheduler_Worker-3:1094 ] - [ INFO ] 坚持 坚持 在坚持,永不放弃Wed Apr 03 10:13:54 CST 2019
2019-04-03 10:13:54 [ MyScheduler_Worker-3:1095 ] - [ INFO ] TimerJobListener
2019-04-03 10:13:54 [ MyScheduler_Worker-3:1095 ] - [ INFO ] Scheduler在JobDetail被执行之后
2019-04-03 10:13:55 [ MyScheduler_Worker-4:2101 ] - [ INFO ] TimerJobListener
2019-04-03 10:13:55 [ MyScheduler_Worker-4:2102 ] - [ INFO ] Scheduler在JobDetail将要被执行
2019-04-03 10:13:55 [ MyScheduler_Worker-4:2102 ] - [ INFO ] 坚持 坚持 在坚持,永不放弃Wed Apr 03 10:13:55 CST 2019
2019-04-03 10:13:55 [ MyScheduler_Worker-4:2103 ] - [ INFO ] TimerJobListener
2019-04-03 10:13:55 [ MyScheduler_Worker-4:2103 ] - [ INFO ] Scheduler在JobDetail被执行之后
备注:
除了代码中将对应的job注册到监听器中的两种方法,也有如下几种其他方法:
1) 将同一任务组的任务注册到监听器中
scheduler.getListenerManager().addJobListener(new TimerJobListener(), GroupMatcher.jobGroupEquals(jobGroupName));
2) 将两个任务组的任务注册到监听器中
scheduler.getListenerManager().addJobListener(new TimerJobListener(), OrMatcher.or(GroupMatcher.jobGroupEquals(jobGroupName), GroupMatcher.jobGroupEquals(jobGroupName)));
三、SchedulerListener
SchedulerListener会在Scheduler的生命周期中关键事件发生时被调用。与Scheduler有关的事件包括:增加一个job/trigger,删除一个job/trigger,scheduler发生严重错误,关闭scheduler等
SchedulerListener接口源码
public interface SchedulerListener {
public void jobScheduled(Trigger trigger);
public void jobUnscheduled(String triggerName, String triggerGroup);
public void triggerFinalized(Trigger trigger);
public void triggersPaused(String triggerName, String triggerGroup);
public void triggersResumed(String triggerName, String triggerGroup);
public void jobsPaused(String jobName, String jobGroup);
public void jobsResumed(String jobName, String jobGroup);
public void schedulerError(String msg, SchedulerException cause);
public void schedulerStarted();
public void schedulerInStandbyMode();
public void schedulerShutdown();
public void schedulingDataCleared();
}
含义:
- jobScheduled方法:用于部署JobDetail时调用
- jobUnscheduled方法:用于卸载JobDetail时调用
- triggerFinalized方法:当一个 Trigger 来到了再也不会触发的状态时调用这个方法。除非这个 Job 已设置成了持久性,否则它就会从 Scheduler 中移除。
- triggersPaused方法:Scheduler 调用这个方法是发生在一个 Trigger 或 Trigger 组被暂停时。假如是 Trigger 组的话,triggerName 参数将为 null。
- triggersResumed方法:Scheduler 调用这个方法是发生成一个 Trigger 或 Trigger 组从暂停中恢复时。假如是 Trigger 组的话,假如是 Trigger 组的话,triggerName 参数将为 null。参数将为 null。
- jobsPaused方法:当一个或一组 JobDetail 暂停时调用这个方法。
- jobsResumed方法:当一个或一组 Job 从暂停上恢复时调用这个方法。假如是一个 Job 组,jobName 参数将为 null。
- schedulerError方法:在 Scheduler 的正常运行期间产生一个严重错误时调用这个方法。
- schedulerStarted方法:当Scheduler 开启时,调用该方法
- schedulerInStandbyMode方法: 当Scheduler处于StandBy模式时,调用该方法
- schedulerShutdown方法:当Scheduler停止时,调用该方法
- schedulingDataCleared方法:当Scheduler中的数据被清除时,调用该方法。
示例:
TimerJob类:
package com.ghuiqun.timer;
import java.util.Date;
import java.util.List;
import org.apache.log4j.Logger;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import com.gzhuiqun.listener.TimerJobListener;
/*
*
* 定义需要执行的任务。该类是一个接口,只定义一个方法 execute(JobExecutionContext context)
在实现类的 execute 方法中编写所需要定时执行的 Job(任务), JobExecutionContext 类提供了调度应用的一些信息。
Job 运行时的信息保存在 JobDataMap 实例中。
*/
public class TimerJob implements Job {
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
Logger logger = Logger.getLogger(TimerJobListener.class);
logger.info("坚持 坚持 在坚持,永不放弃"+ new Date());
System.out.println("坚持 坚持 在坚持,永不放弃"+ new Date());
}
}
TimerSchedulerListener类:
package com.gzhuiqun.listener;
import org.apache.log4j.Logger;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.ScheduleBuilder;
import org.quartz.SchedulerException;
import org.quartz.SchedulerListener;
import org.quartz.Trigger;
import org.quartz.TriggerKey;
/**
* @author Administrator
* SchedulerListener会在Scheduler的生命周期中关键事件发生时被调用。与Scheduler有关的事件包括:增加一个job/trigger,
* 删除一个job/trigger,scheduler发生严重错误,关闭scheduler等。
*/
public class TimerSchedulerListener implements SchedulerListener {
Logger logger = Logger.getLogger(TimerSchedulerListener.class);
@Override
public void jobScheduled(Trigger trigger) {
String jobName = trigger.getJobKey().getName();
logger.info(jobName +"部署");
System.out.println(jobName + "部署s");
}
@Override
public void jobUnscheduled(TriggerKey triggerKey) {
logger.info(triggerKey + "卸载");
System.out.println(triggerKey + "卸载");
}
@Override
public void triggerFinalized(Trigger trigger) {
logger.info("触发完成" + trigger.getJobKey().getName());
System.out.println("触发完成" + trigger.getJobKey().getName());
}
@Override
public void triggerPaused(TriggerKey triggerKey) {
logger.info(triggerKey + "暂停");
System.out.println(triggerKey + "暂停");
}
@Override
public void triggersPaused(String triggerGroup) {
logger.info("trigger group "+triggerGroup + "暂停");
System.out.println("trigger group "+triggerGroup + "暂停");
}
@Override
public void triggerResumed(TriggerKey triggerKey) {
logger.info(triggerKey + "从暂停中恢复");
System.out.println(triggerKey + "从暂停中恢复");
}
@Override
public void triggersResumed(String triggerGroup) {
logger.info("trigger group "+triggerGroup + "从暂停中恢复");
System.out.println("trigger group "+triggerGroup + "从暂停中恢复");
}
@Override
public void jobAdded(JobDetail jobDetail) {
logger.info(jobDetail.getKey()+"增加");
System.out.println(jobDetail.getKey()+"增加");
}
@Override
public void jobDeleted(JobKey jobKey) {
logger.info(jobKey+"删除");
System.out.println(jobKey+"删除");
}
@Override
public void jobPaused(JobKey jobKey) {
logger.info(jobKey+"暂停");
System.out.println(jobKey+"暂停");
}
@Override
public void jobsPaused(String jobGroup) {
logger.info("job group "+jobGroup+"暂停");
System.out.println("job group "+jobGroup+"暂停");
}
@Override
public void jobResumed(JobKey jobKey) {
logger.info(jobKey+"从暂停上恢复");
System.out.println(jobKey+"从暂停上恢复");
}
@Override
public void jobsResumed(String jobGroup) {
logger.info("job group "+jobGroup+"从暂停上恢复");
System.out.println("job group "+jobGroup+"从暂停上恢复");
}
@Override
public void schedulerError(String msg, SchedulerException cause) {
logger.error(msg, cause.getUnderlyingException());
logger.info("正常运行期间产生一个严重错误");
System.out.println("正常运行期间产生一个严重错误");
}
@Override
public void schedulerInStandbyMode() {
logger.info("Scheduler处于StandBy模式");
System.out.println("Scheduler处于StandBy模式");
}
@Override
public void schedulerStarted() {
logger.info("scheduler开启完成");
System.out.println("scheduler开启完成");
}
@Override
public void schedulerStarting() {
logger.info("scheduler正在开启");
System.out.println("scheduler正在开启");
}
@Override
public void schedulerShutdown() {
logger.info("scheduler停止");
System.out.println("scheduler停止");
}
@Override
public void schedulerShuttingdown() {
logger.info("scheduler正在停止");
System.out.println("scheduler正在停止");
}
@Override
public void schedulingDataCleared() {
logger.info("Scheduler中的数据被清除");
System.out.println("Scheduler中的数据被清除");
}
}
任务调度与运行,及TimerSchedulerListener的创建与注册。
package com.ghuiqun.timer;
import org.quartz.CronScheduleBuilder;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.matchers.EverythingMatcher;
import com.gzhuiqun.listener.TimerJobListener;
import com.gzhuiqun.listener.TimerSchedulerListener;
import com.gzhuiqun.listener.TimerTriggerListener;
public class TimerExample {
// 创建 schedulerFactory 工厂
private static SchedulerFactory scheduleFactory= new StdSchedulerFactory();
public static void main(String[] args) {
// TODO Auto-generated method stub
String[] data= {"s","t","r","i","n","g"};
try {
addJob("HelloJob2","HelloJobGroup","HelloTrigger2","HelloTriggerGroup",TimerJob.class,"0/1 * * * * ?",data);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**添加一个定时任务
* @param jobName 任务名
* @param jobGroupName 任务组名
* @param triggerName 触发器名
* @param triggerGroupName 触发器组名
* @param jobClass 任务类名
* @param cron 时间
* @throws InterruptedException
*/
public static void addJob(String jobName,String jobGroupName,String triggerName,String triggerGroupName
,Class<? extends Job> jobClass,String cron,String[] data) throws InterruptedException {
try {
//通过scheduleFactory创建任务调度器
Scheduler scheduler = scheduleFactory.getScheduler();
//创建 jobDetail 实例,绑定 Job 实现类
// 指明 job 的名称,所在组的名称,以及绑定 job 类
JobDetail job = (JobDetail) JobBuilder.newJob(jobClass)
.withIdentity(jobName,jobGroupName)
//.requestRecovery() // 执行中应用发生故障,需要重新执行
.build();
// 初始化参数传递到 job
job.getJobDataMap().put("data",data);
// 定义调度触发规则CronTrigger
//指明 CronTrigger 的名称,所在组的名称,触发时间
Trigger trigger = (Trigger) TriggerBuilder.newTrigger()
.withIdentity(triggerName,triggerGroupName)
.startNow()
.withSchedule(CronScheduleBuilder.cronSchedule(cron))
.build();
// 把作业和触发器注册到任务调度中
scheduler.scheduleJob(job,trigger);
// 创建SchedulerListener
scheduler.getListenerManager().addSchedulerListener(new TimerSchedulerListener());
// 移除对应的SchedulerListener
// scheduler.getListenerManager().removeSchedulerListener(new TimerSchedulerListener());
//启动
if(!scheduler.isShutdown()) {
scheduler.start();
System.out.println("开始调度任务");
}
Thread.sleep(5000);
scheduler.shutdown();
} catch (SchedulerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
结果:
2019-04-03 11:17:41 [ main:546 ] - [ INFO ] scheduler正在开启
2019-04-03 11:17:41 [ main:606 ] - [ INFO ] scheduler开启完成
2019-04-03 11:17:41 [ MyScheduler_Worker-1:641 ] - [ INFO ] 坚持 坚持 在坚持,永不放弃Wed Apr 03 11:17:41 CST 2019
2019-04-03 11:17:41 [ MyScheduler_Worker-2:657 ] - [ INFO ] 坚持 坚持 在坚持,永不放弃Wed Apr 03 11:17:41 CST 2019
2019-04-03 11:17:41 [ MyScheduler_Worker-3:668 ] - [ INFO ] 坚持 坚持 在坚持,永不放弃Wed Apr 03 11:17:41 CST 2019
2019-04-03 11:17:41 [ MyScheduler_Worker-4:680 ] - [ INFO ] 坚持 坚持 在坚持,永不放弃Wed Apr 03 11:17:41 CST 2019
2019-04-03 11:17:41 [ MyScheduler_Worker-5:692 ] - [ INFO ] 坚持 坚持 在坚持,永不放弃Wed Apr 03 11:17:41 CST 2019
2019-04-03 11:17:42 [ MyScheduler_Worker-6:1423 ] - [ INFO ] 坚持 坚持 在坚持,永不放弃Wed Apr 03 11:17:42 CST 2019
2019-04-03 11:17:42 [ MyScheduler_Worker-7:1454 ] - [ INFO ] 坚持 坚持 在坚持,永不放弃Wed Apr 03 11:17:42 CST 2019
2019-04-03 11:17:42 [ MyScheduler_Worker-8:1478 ] - [ INFO ] 坚持 坚持 在坚持,永不放弃Wed Apr 03 11:17:42 CST 2019
2019-04-03 11:17:43 [ MyScheduler_Worker-9:2429 ] - [ INFO ] 坚持 坚持 在坚持,永不放弃Wed Apr 03 11:17:43 CST 2019
2019-04-03 11:17:43 [ MyScheduler_Worker-10:2462 ] - [ INFO ] 坚持 坚持 在坚持,永不放弃Wed Apr 03 11:17:43 CST 2019
2019-04-03 11:17:43 [ MyScheduler_Worker-1:2477 ] - [ INFO ] 坚持 坚持 在坚持,永不放弃Wed Apr 03 11:17:43 CST 2019
2019-04-03 11:17:44 [ MyScheduler_Worker-2:3414 ] - [ INFO ] 坚持 坚持 在坚持,永不放弃Wed Apr 03 11:17:44 CST 2019
2019-04-03 11:17:44 [ MyScheduler_Worker-3:3424 ] - [ INFO ] 坚持 坚持 在坚持,永不放弃Wed Apr 03 11:17:44 CST 2019
2019-04-03 11:17:44 [ MyScheduler_Worker-4:3435 ] - [ INFO ] 坚持 坚持 在坚持,永不放弃Wed Apr 03 11:17:44 CST 2019
2019-04-03 11:17:45 [ MyScheduler_Worker-5:4420 ] - [ INFO ] 坚持 坚持 在坚持,永不放弃Wed Apr 03 11:17:45 CST 2019
2019-04-03 11:17:45 [ MyScheduler_Worker-6:4446 ] - [ INFO ] 坚持 坚持 在坚持,永不放弃Wed Apr 03 11:17:45 CST 2019
2019-04-03 11:17:45 [ MyScheduler_Worker-7:4466 ] - [ INFO ] 坚持 坚持 在坚持,永不放弃Wed Apr 03 11:17:45 CST 2019
2019-04-03 11:17:46 [ MyScheduler_Worker-8:5424 ] - [ INFO ] 坚持 坚持 在坚持,永不放弃Wed Apr 03 11:17:46 CST 2019
2019-04-03 11:17:46 [ MyScheduler_Worker-9:5450 ] - [ INFO ] 坚持 坚持 在坚持,永不放弃Wed Apr 03 11:17:46 CST 2019
2019-04-03 11:17:46 [ MyScheduler_Worker-10:5475 ] - [ INFO ] 坚持 坚持 在坚持,永不放弃Wed Apr 03 11:17:46 CST 2019
2019-04-03 11:17:46 [ main:5607 ] - [ INFO ] Scheduler处于StandBy模式
2019-04-03 11:17:46 [ main:5607 ] - [ INFO ] scheduler正在停止
2019-04-03 11:17:46 [ main:5613 ] - [ INFO ] scheduler停止