林炳文Evankaka原创作品。转载请注明出处http://blog.csdn.net/evankaka
本文工程免费下载
一、Quartz 监听器
在某个所关注事件发生时,监听器提供了一种方便且非侵入性的机制来获得这一通知。Quartz 提供了三种类型的监听器:监听 Job 的,监听 Trigger 的,和监听 Scheduler 自已的。本章解释如何应用每一种类型来更好的管理你的 Quartz 应用,并获悉到什么事件正在发生。
1.1、监听器作为扩展点
术语 "
扩展点
" 在软件开发中用于指示框架或应用的某个位置,在这一位置在创建者期望用户扩展或定制这一框架来适合于他们的需要。(你也将会听到
hook
(钩子) 一词,是一样意思的)
Quartz 监听器是某一类型的扩展点,在这里你,作为一个 Quartz 用户,可以扩展这框架并定制它来做些新的事情。定制化发生成监听类的实现当中,我们会在本章中告诉你如何构建它。
监听器并非框架中仅有的扩展点。还有插件和一些其他的定制选项,不过监听器提供了一个简单的方式来定制框架,使之做你需要它做的事情。因为针对于监听器的扩展点是通过公有化接口来支持,所以你用不着担心创建了你自己的分支代码,到后来又不被支持的情况。
1.2、实现监听
在接下来的讨论中,实现监听器的方法通用于所有的三种类型。可以分成以下步骤:
1.
创建一个 Java 类,实现监听器接口
2.
用你的应用中特定的逻辑实现监听器接口的所有方法
3.
注册监听器
1.3、创建监听器类
监听器是一个 Java 接口,它必须由一个具体类来实现。你也不需要只为这个目的创建一个专门的类;它可以是任何一个你希望能接收到方法回调的类。为符合良好的程序设计,你应当注意保持高内聚和松耦合性。认真的考虑哪个类你决定用于实现监听器类;这从总体设计的视角来看是很重要的。
1.4、全局之于非全局监听器
JobListener 和 TriggerListener 可被注册为全局或非全局监听器。一个全局监听器能接收到所有的 Job/Trigger 的事件通知。而一个非全局监听器(或者说是一个标准的监听器) 只能接收到那些在其上已注册了监听器的 Job 或 Triiger 的事件。
你要注册你的监听器为全局或非全局的需依据你特定的应用需要。我们在以下章节中提供了两种方式的例子。从另一方面来认识全局和非全局的监听器是来自于 Quartz 框架的创建者。James House 在描述全局和非全局监听器时是这样的:
全局监听器是主动意识的,它们为了执行它们的任务而热切的去寻找每一个可能的事件。通常,全局监听器要做的工作不用指定到特定的 Job 或 Trigger。非全局监听器一般是被动意识的,它们在所关注的 Trigger 激发之前或是 Job 执行之前什么事也不做。因此,非全局的监听器比起全局监听器而言更适合于修改或增加 Job 执行的工作。这有点像知名的装饰设计模式的装饰器。
- 全局:
-
- scheduler.addGlobalTriggerListener(new SimpleMyTriggerListener());
-
- 局部:
-
- scheduler.addTriggerListener( triggerListener );
- trigger.addTriggerListener( triggerListener.getName() );
二、 监听 Job 事件
org.quartz.JobListener 接口包含一系列的方法,它们会由 Job 在其生命周期中产生的某些关键事件时被调用。JobListener 可用的方法显示在如下代码
org.quartz.JobListener 接口中的方法
- public interface JobListener {
- public String getName();
- public void jobToBeExecuted(JobExecutionContext context);
- public void jobExecutionVetoed(JobExecutionContext context);
-
- public void jobWasExecuted(JobExecutionContext context,
- JobExecutionException jobException);
- }
- public interface JobListener {
- public String getName();
- public void jobToBeExecuted(JobExecutionContext context);
- public void jobExecutionVetoed(JobExecutionContext context);
-
- public void jobWasExecuted(JobExecutionContext context,
- JobExecutionException jobException);
- }
JobListener 接口中的方法用途是十分明了的。然后,我们还是要对他们加以简单说明。
·getName() 方法
getName() 方法返回一个字符串用以说明 JobListener 的名称。对于注册为全局的监听器,getName() 主要用于记录日志,对于由特定 Job 引用的 JobListener,注册在 JobDetail 上的监听器名称必须匹配从监听器上 getName() 方法的返回值。在你看完一些例子之后就会很清楚了。
·jobToBeExecuted() 方法
Scheduler 在 JobDetail 将要被执行时调用这个方法。
·jobExecutionVetoed() 方法
Scheduler 在 JobDetail 即将被执行,但又被 TriggerListener 否决了时调用这个方法。
·jobWasExecuted() 方法
Scheduler 在 JobDetail 被执行之后调用这个方法。
以下展示了一个很简单的 JobListener 实现。
- package com.mucfc;
-
- import org.quartz.JobExecutionContext;
- import org.quartz.JobExecutionException;
- import org.quartz.JobListener;
-
- public class MyJobListener implements JobListener{
-
- @Override
- public String getName() {
- return "MyJobListener";
- }
-
-
-
- @Override
- public void jobExecutionVetoed(JobExecutionContext arg0) {
- System.out.println("Job监听器:MyJobListener.jobExecutionVetoed()");
- }
-
-
-
- @Override
- public void jobToBeExecuted(JobExecutionContext arg0) {
- System.out.println("Job监听器:MyJobListener.jobToBeExecuted()");
-
- }
-
-
-
- @Override
- public void jobWasExecuted(JobExecutionContext arg0,
- JobExecutionException arg1) {
- System.out.println("Job监听器:MyJobListener.jobWasExecuted()");
-
- }
-
- }
注册监听器:
-
- MyJobListener myJobListener=new MyJobListener();
- scheduler.getListenerManager()
- .addJobListener(myJobListener, allJobs());
-
-
-
-
-
-
三. 监听 Trigger 事件
正如 JobListener, org.quartz.TriggerListener 接口也包含一系列给 Scheduler 调用的方法。然而,与 JobListener 有所不同的是, TriggerListener 接口还有关于 Trigger 实例生命周期的方法。以下代码 列出了 TriggerListener 接口的方法。
org.quartz.TriggerListener 接口的方法
- public interface TriggerListener {
- public String getName();
-
- public void triggerFired(Trigger trigger,
- JobExecutionContext context);
-
- public boolean vetoJobExecution(Trigger trigger,
- JobExecutidonContext context);
-
- public void triggerMisfired(Trigger trigger);
-
- public void triggerComplete(Trigger trigger,
- JobExecutionContext context,
- int triggerInstructionCode);
- }
- public interface TriggerListener {
- public String getName();
-
- public void triggerFired(Trigger trigger,
- JobExecutionContext context);
-
- public boolean vetoJobExecution(Trigger trigger,
- JobExecutidonContext context);
-
- public void triggerMisfired(Trigger trigger);
-
- public void triggerComplete(Trigger trigger,
- JobExecutionContext context,
- int triggerInstructionCod
·getName() 方法
和前面的 JobListener 一样,TriggerListner 接口的 getName() 返回一个字符串用以说明监听器的名称。对于非全局的 TriggerListener,在 addTriggerListener() 方法中给定的名称必须与监听器的 getName() 方法返回值相匹配。
·triggerFired() 方法
当与监听器相关联的 Trigger 被触发,Job 上的 execute() 方法将要被执行时,Scheduler 就调用这个方法。在全局 TriggerListener 情况下,这个方法为所有 Trigger 被调用。
·vetoJobExecution() 方法
在 Trigger 触发后,Job 将要被执行时由 Scheduler 调用这个方法。TriggerListener 给了一个选择去否决 Job 的执行。假如这个方法返回 true,这个 Job 将不会为此次 Trigger 触发而得到执行。
·triggerMisfired() 方法
Scheduler 调用这个方法是在 Trigger 错过触发时。如这个方法的 JavaDoc 所指出的,你应该关注此方法中持续时间长的逻辑:在出现许多错过触发的 Trigger 时,长逻辑会导致骨牌效应。你应当保持这上方法尽量的小。
·triggerComplete() 方法
Trigger 被触发并且完成了 Job 的执行时,Scheduler 调用这个方法。这不是说这个 Trigger 将不再触发了,而仅仅是当前 Trigger 的触发(并且紧接着的 Job 执行) 结束时。这个 Trigger 也许还要在将来触发多次的。
以下代码 展示了一个很简单的 TriggerListener 实现
- package com.mucfc;
-
- import org.quartz.JobExecutionContext;
- import org.quartz.Trigger;
- import org.quartz.Trigger.CompletedExecutionInstruction;
- import org.quartz.TriggerListener;
-
- public class MyTriggerListener implements TriggerListener{
-
- @Override
- public String getName() {
- return "MyTriggerListener";
- }
-
-
-
-
-
-
- @Override
- public void triggerFired(Trigger trigger, JobExecutionContext context) {
- System.out.println("Trigger监听器:MyTriggerListener.triggerFired()");
- }
-
-
-
-
-
-
- @Override
- public boolean vetoJobExecution(Trigger trigger, JobExecutionContext context) {
- System.out.println("Trigger监听器:MyTriggerListener.vetoJobExecution()");
- return false;
- }
-
-
-
-
-
-
- @Override
- public void triggerMisfired(Trigger trigger) {
- System.out.println("Trigger监听器:MyTriggerListener.triggerMisfired()");
- }
-
-
-
-
-
-
- @Override
- public void triggerComplete(Trigger trigger, JobExecutionContext context,
- CompletedExecutionInstruction triggerInstructionCode) {
- System.out.println("Trigger监听器:MyTriggerListener.triggerComplete()");
- }
-
- }
注册监听器事件:
-
- MyTriggerListener myTriggerListener=new MyTriggerListener();
-
-
-
-
-
-
四. 监听 Scheduler 事件
org.quartz.SchedulerListener 接口包含了一系列的回调方法,它们会在 Scheduler 的生命周期中有关键事件发生时被调用。代码 7.9 列出了包括在 SchedulerListener 接口的方法。
org.quartz.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 schedulerShutdown();
- }
SchedulerListener 是在 Scheduler 级别的事件产生时得到通知,不管是增加还是移除 Scheduler 中的 Job,或者是 Scheduler 遭遇到了严重的错误时。那些事件多是关于对 Scheduler 管理的,而不是专注于 Job 或 Trigger 的。
· jobScheduled() 和 jobUnscheduled() 方法
Scheduler 在有新的 JobDetail 部署或卸载时调用这两个中的相应方法。
· triggerFinalized() 方法
当一个 Trigger 来到了再也不会触发的状态时调用这个方法。除非这个 Job 已设置成了持久性,否则它就会从 Scheduler 中移除。
·triggersPaused() 方法
Scheduler 调用这个方法是发生在一个 Trigger 或 Trigger 组被暂停时。假如是 Trigger 组的话,triggerName 参数将为 null。
·triggersResumed() 方法
Scheduler 调用这个方法是发生成一个 Trigger 或 Trigger 组从暂停中恢复时。假如是 Trigger 组的话,triggerName 参数将为 null。
·jobsPaused() 方法
当一个或一组 JobDetail 暂停时调用这个方法。
·jobsResumed() 方法
当一个或一组 Job 从暂停上恢复时调用这个方法。假如是一个 Job 组,jobName 参数将为 null。
·schedulerError() 方法
在 Scheduler 的正常运行期间产生一个严重错误时调用这个方法。错误的类型会各式的,但是下面列举了一些错误例子:
·初始化 Job 类的问题
·试图去找到下一 Trigger 的问题
·JobStore 中重复的问题
·数据存储连接的问题
你可以使用 SchedulerException 的 getErrorCode() 或者 getUnderlyingException() 方法或获取到特定错误的更详尽的信息。
·schedulerShutdown() 方法
Scheduler 调用这个方法用来通知 SchedulerListener Scheduler 将要被关闭。
以下为一个示例代码
添加监听器:
-
- MySchedulerListener schedulerListener = new MySchedulerListener();
- scheduler.getListenerManager().addSchedulerListener(schedulerListener);
五、使用范例:
1、 Job类:
- package com.mucfc;
- import java.text.SimpleDateFormat;
- import java.util.Date;
-
- import org.quartz.Job;
- import org.quartz.JobExecutionContext;
- import org.quartz.JobExecutionException;
- import org.springframework.scheduling.annotation.Scheduled;
- import org.springframework.stereotype.Component;
-
-
-
-
-
-
- public class MyJob implements Job{
- public MyJob(){
- System.out.println("MyJob创建成功");
- }
-
- @Override
- public void execute(JobExecutionContext arg0)
- throws JobExecutionException {
- System.out.println("Hello MyJob "+
- new SimpleDateFormat("yyyy-MM-dd HH:mm:ss ").format(new Date()));
-
- }
-
- }
2、Job监听器类
- package com.mucfc;
-
- import org.quartz.JobExecutionContext;
- import org.quartz.JobExecutionException;
- import org.quartz.JobListener;
-
- public class MyJobListener implements JobListener{
-
- @Override
- public String getName() {
- return "MyJobListener";
- }
-
-
-
- @Override
- public void jobExecutionVetoed(JobExecutionContext arg0) {
- System.out.println("Job监听器:MyJobListener.jobExecutionVetoed()");
- }
-
-
-
- @Override
- public void jobToBeExecuted(JobExecutionContext arg0) {
- System.out.println("Job监听器:MyJobListener.jobToBeExecuted()");
-
- }
-
-
-
- @Override
- public void jobWasExecuted(JobExecutionContext arg0,
- JobExecutionException arg1) {
- System.out.println("Job监听器:MyJobListener.jobWasExecuted()");
-
- }
-
- }
3、Trigger监听器类
- package com.mucfc;
-
- import org.quartz.JobExecutionContext;
- import org.quartz.Trigger;
- import org.quartz.Trigger.CompletedExecutionInstruction;
- import org.quartz.TriggerListener;
-
- public class MyTriggerListener implements TriggerListener{
-
- @Override
- public String getName() {
- return "MyTriggerListener";
- }
-
-
-
-
-
-
- @Override
- public void triggerFired(Trigger trigger, JobExecutionContext context) {
- System.out.println("Trigger监听器:MyTriggerListener.triggerFired()");
- }
-
-
-
-
-
-
- @Override
- public boolean vetoJobExecution(Trigger trigger, JobExecutionContext context) {
- System.out.println("Trigger监听器:MyTriggerListener.vetoJobExecution()");
- return false;
- }
-
-
-
-
-
-
- @Override
- public void triggerMisfired(Trigger trigger) {
- System.out.println("Trigger监听器:MyTriggerListener.triggerMisfired()");
- }
-
-
-
-
-
-
- @Override
- public void triggerComplete(Trigger trigger, JobExecutionContext context,
- CompletedExecutionInstruction triggerInstructionCode) {
- System.out.println("Trigger监听器:MyTriggerListener.triggerComplete()");
- }
-
- }
4、Scheduler监听器类
5、注册使用:
- package com.mucfc;
- import java.util.List;
-
- import org.quartz.JobBuilder;
- import org.quartz.JobDetail;
- import org.quartz.Matcher;
- import org.quartz.Scheduler;
- import org.quartz.SchedulerException;
- import org.quartz.SimpleScheduleBuilder;
- import org.quartz.Trigger;
- import org.quartz.TriggerBuilder;
- import org.quartz.TriggerKey;
- import org.quartz.impl.StdSchedulerFactory;
- import org.quartz.impl.matchers.KeyMatcher;
-
- import static org.quartz.JobKey.*;
- import static org.quartz.impl.matchers.KeyMatcher.*;
- import static org.quartz.impl.matchers.GroupMatcher.*;
- import static org.quartz.impl.matchers.AndMatcher.*;
- import static org.quartz.impl.matchers.OrMatcher.*;
- import static org.quartz.impl.matchers.EverythingMatcher.*;
- public class MyTest {
- public static void main(String[] args) {
-
- try {
-
- JobDetail jobDetail = JobBuilder.newJob(MyJob.class)
-
- .withIdentity("job1_1", "jGroup1")
-
- .build();
-
- SimpleScheduleBuilder builder=SimpleScheduleBuilder.simpleSchedule()
-
- .withIntervalInSeconds(5)
-
- .repeatForever();
- Trigger trigger=TriggerBuilder.newTrigger().withIdentity(
- "trigger1_1","tGroup1").startNow().withSchedule(builder).build();
-
- Scheduler scheduler=StdSchedulerFactory.getDefaultScheduler();
- scheduler.start();
-
-
-
- MyTriggerListener myTriggerListener=new MyTriggerListener();
-
-
-
- scheduler.getListenerManager().addTriggerListener(myTriggerListener, keyEquals(new TriggerKey("trigger1_1","tGroup1")));
-
-
-
-
-
-
- MyJobListener myJobListener=new MyJobListener();
- scheduler.getListenerManager()
- .addJobListener(myJobListener, allJobs());
-
-
-
-
-
-
-
-
- MySchedulerListener schedulerListener = new MySchedulerListener();
- scheduler.getListenerManager().addSchedulerListener(schedulerListener);
-
-
-
-
- scheduler.scheduleJob(jobDetail, trigger);
- try {
- Thread.sleep(60000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
-
- scheduler.shutdown();
-
- } catch (SchedulerException e) {
- e.printStackTrace();
- }
-
- }
- }
输出结果:
![](https://img-blog.csdn.net/20150505095747346)
或者看大图!
![](https://img-blog.csdn.net/20150505095724712)
然后是scheduler关闭后
![](https://img-blog.csdn.net/20150505100615522)
这就是最后的结果了
林炳文Evankaka原创作品。转载请注明出处http://blog.csdn.net/evankaka
本文工程免费下载