Quartz-JobListener解读
来源:互联网 发布:火锅店库存软件 编辑:程序博客网 时间:2024/06/06 20:44
- 概述
- 步骤简述
- 全局非全局监听器
- JobListener 任务监听器 示例
- JobListener源码
- 完整示例
- 示例源码
概述
在某个所关注事件发生时,监听器提供了一种方便且非侵入性的机制来获得这一通知。Quartz 提供了三种类型的监听器:监听 Job 的,监听 Trigger 的,和监听 Scheduler 自已的。
本博文阐述如何应用每一种类型来更好的管理你的 Quartz 应用,并获悉到什么事件正在发生。
参考官方Demo:
http://www.quartz-scheduler.org/documentation/quartz-2.2.x/tutorials/tutorial-lesson-07.html
步骤简述
要创建一个Listener, 只需要创建一个实现了org.quartz.TriggerListener或org.quartz.JobListener接口的对象即可。
在运行的时候,将Listeners注册进scheduler, 而且必须给一个name(可以通过他们的getName()方法获取Listener的name)。
除了继承接口,类也可以继承JobListenerSupport或TriggerListenerSupport,重写你感兴趣的event。
Listener通过scheduler的ListenerManager来注册,其中的Matcher 里描述哪个Jobs、Triggers需要被监听。
注意:
LListeners在运行的时候被注册进scheduler, 而不是保存在JobStore。Listener是和你的应用集成在一起的,这样每次你的应用运行的时候,都会在scheduler中重新注册listeners。
全局/非全局监听器
JobListener 和 TriggerListener 可被注册为全局或非全局监听器。
全局监听器能接收到所有的 Job/Trigger 的事件通知。
非全局监听器(或者说是一个标准的监听器) 只能接收到那些在其上已注册了监听器的 Job 或 Triiger 的事件。
你要注册你的监听器为全局或非全局的需依据你特定的应用需要。
全局监听器是主动意识的,它们为了执行它们的任务而热切的去寻找每一个可能的事件。通常全局监听器要做的工作不用指定到特定的 Job 或 Trigger。非全局监听器一般是被动意识的,它们在所关注的 Trigger 激发之前或是 Job 执行之前什么事也不做。因此,非全局的监听器比起全局监听器而言更适合于修改或增加 Job 执行的工作。这有点像知名的装饰设计模式的装饰器。
全局 监听器
scheduler.addGlobalTriggerListener(new SimpleMyTriggerListener());
非全局监听器
scheduler.addTriggerListener( triggerListener );trigger.addTriggerListener( triggerListener.getName() );
JobListener 任务监听器 示例
JobListener源码
我们先来看下JobListener的源码:
getName() :返回一个字符串用以说明 JobListener 的名称。对于注册为全局的监听器,getName()主要用于记录日志,对于由特定 Job 引用的JobListener,注册在 JobDetail 上的监听器名称必须匹配从监听器getName() 方法的返回值。
jobToBeExecuted() :Scheduler 在 JobDetail 将要被执行时调用这个方法。
jobExecutionVetoed() :Scheduler 在 JobDetail 即将被执行,但又被 TriggerListener否决了时调用这个方法。
jobWasExecuted() :Scheduler 在 JobDetail 被执行之后调用这个方法。
自定义监听器
import org.quartz.*;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(); // 添加一个特定的jobscheduler.getListenerManager().addJobListener(myJobListener, KeyMatcher.jobKeyEquals(new JobKey("myJobName", "myJobGroup")));
上面的代码就可以变成:
scheduler.getListenerManager().addJobListener(myJobListener, jobKeyEquals(jobKey("myJobName", "myJobGroup")));// 添加特定组的所有jobsscheduler.getListenerManager().addJobListener(myJobListener, jobGroupEquals("myJobGroup"));// 添加多个特定组的所有jobsscheduler.getListenerManager().addJobListener(myJobListener, or(jobGroupEquals("myJobGroup"), jobGroupEquals("yourGroup")));// 添加所有jobsscheduler.getListenerManager().addJobListener(myJobListener, allJobs());
有了Listeners以后,当应用需要在某些事件发生以后去通知你的应用,这时就不需要Job去明确地去告知你的应用了。
完整示例
添加一个jobListener,监听到job1执行后,再触发一个job2任务
Job1.java
package com.xgj.quartz.quartzItself.listener.jobListener;import java.text.SimpleDateFormat;import java.util.Date;import org.quartz.Job;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;import org.quartz.JobKey;public class Job1 implements Job { public void execute(JobExecutionContext context) throws JobExecutionException { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); JobKey jobKey = context.getJobDetail().getKey(); System.out.println("\nJob1 - 任务key " + jobKey + "执行时间:" + sdf.format(new Date())); }}
Job2.java
package com.xgj.quartz.quartzItself.listener.jobListener;import java.text.SimpleDateFormat;import java.util.Date;import org.quartz.Job;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;import org.quartz.JobKey;public class Job2 implements Job { public void execute(JobExecutionContext context) throws JobExecutionException { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); JobKey jobKey = context.getJobDetail().getKey(); System.err.println("\nJob2 - 任务key " + jobKey + "执行时间:" + sdf.format(new Date())); }}
自定义JobListener
package com.xgj.quartz.quartzItself.listener.jobListener;import org.quartz.JobBuilder;import org.quartz.JobDetail;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;import org.quartz.JobListener;import org.quartz.SchedulerException;import org.quartz.Trigger;import org.quartz.TriggerBuilder;/** * * * @ClassName: MyJobListener * * @Description: 自定义Job监听器 * * getName() :返回一个字符串用以说明 JobListener 的名称。对于注册为全局的监听器,getName() * 主要用于记录日志,对于由特定 Job 引用的 JobListener,注册在 JobDetail * 上的监听器名称必须匹配从监听器上 getName() 方法的返回值. * * jobToBeExecuted() :Scheduler 在 JobDetail 将要被执行时调用这个方法。 * * jobExecutionVetoed() :Scheduler 在 JobDetail 即将被执行,但又被 * TriggerListener 否决了时调用这个方法。 * * jobWasExecuted() :Scheduler 在 JobDetail 被执行之后调用这个方法。 * * @author: Mr.Yang * * @date: 2017年11月16日 下午3:57:35 */public class MyJobListener implements JobListener { @Override public String getName() { return "MyJobListerner"; } @Override public void jobToBeExecuted(JobExecutionContext context) { System.out.println("Job监听器:MyJobListener.jobToBeExecuted()"); } @Override public void jobExecutionVetoed(JobExecutionContext context) { System.out.println("Job监听器:MyJobListener.jobExecutionVetoed()"); } @Override public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) { System.out.println("Job监听器:MyJobListener.jobWasExecuted()"); // 设置另外一个job执行 JobDetail job2 = JobBuilder.newJob(Job2.class).withIdentity("job2") .build(); Trigger trigger = TriggerBuilder.newTrigger().withIdentity("job2Trigger").startNow().build(); try { context.getScheduler().scheduleJob(job2, trigger); } catch (SchedulerException e) { System.err.println("无法安排job2!"); e.printStackTrace(); } }}
调度类
package com.xgj.quartz.quartzItself.listener.jobListener;import static org.quartz.JobBuilder.newJob;import static org.quartz.TriggerBuilder.newTrigger;import org.quartz.JobDetail;import org.quartz.JobKey;import org.quartz.JobListener;import org.quartz.Matcher;import org.quartz.Scheduler;import org.quartz.SchedulerFactory;import org.quartz.SchedulerMetaData;import org.quartz.Trigger;import org.quartz.impl.StdSchedulerFactory;import org.quartz.impl.matchers.KeyMatcher;public class JobListenerDemo { public static void main(String[] args) throws Exception { System.out.println("------- 初始化 ----------------------"); // Scheduler SchedulerFactory schedulerFactory = new StdSchedulerFactory(); Scheduler scheduler = schedulerFactory.getScheduler(); // Job JobDetail job = newJob(Job1.class).withIdentity("job1", "group1") .build(); // Tirgger Trigger trigger = newTrigger().withIdentity("trigger1", "group1") .startNow() .build(); // 设置监听器 JobListener jobListener = new MyJobListener(); Matcher<JobKey> matcher = KeyMatcher.keyEquals(job.getKey()); scheduler.getListenerManager().addJobListener(jobListener, matcher); // 将job任务加入到调度器 scheduler.scheduleJob(job, trigger); // 开始任务 System.out.println("------- 开始执行调度器 Scheduler ----------------"); scheduler.start(); try { System.out.println("------- 等待 30 秒... --------------"); Thread.sleep(30L * 1000L); } catch (Exception e) { e.printStackTrace(); } scheduler.shutdown(true); System.out.println("------- 关闭调度器 -----------------"); SchedulerMetaData metaData = scheduler.getMetaData(); System.out.println("~~~~~~~~~~ 执行了 " + metaData.getNumberOfJobsExecuted() + " 个 jobs."); }}
运行结果
------- 初始化 ----------------------INFO StdSchedulerFactory - Using default implementation for ThreadExecutorINFO SimpleThreadPool - Job execution threads will use class loader of thread: mainINFO SchedulerSignalerImpl - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImplINFO QuartzScheduler - Quartz Scheduler v.2.2.3 created.INFO RAMJobStore - RAMJobStore initialized.INFO QuartzScheduler - Scheduler meta-data: Quartz Scheduler (v2.2.3) 'DefaultQuartzScheduler' with instanceId 'NON_CLUSTERED' Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally. NOT STARTED. Currently in standby mode. Number of jobs executed: 0 Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads. Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.INFO StdSchedulerFactory - Quartz scheduler 'DefaultQuartzScheduler' initialized from default resource file in Quartz package: 'quartz.properties'INFO StdSchedulerFactory - Quartz scheduler version: 2.2.3------- 开始执行调度器 Scheduler ----------------INFO QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED started.------- 等待 30 秒... --------------Job监听器:MyJobListener.jobToBeExecuted()Job1 - 任务key group1.job1执行时间:2017-11-16 17:58:54Job监听器:MyJobListener.jobWasExecuted()Job2 - 任务key DEFAULT.job2执行时间:2017-11-16 17:58:54INFO QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED shutting down.INFO QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED paused.INFO QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED shutdown complete.------- 关闭调度器 -----------------~~~~~~~~~~ 执行了 2 个 jobs.
示例源码
代码已托管到Github—> https://github.com/yangshangwei/SpringMaster
- Quartz-JobListener解读
- Quartz实现自己的JobListener和TriggerListener
- 【Quartz】 JobListener、Triggerlistener、SchedulerListener介绍与使用
- 【Quartz】 JobListener、Triggerlistener、SchedulerListener介绍与使用
- Quartz教程七--TriggerListener和JobListener
- Quartz任务调度(4)JobListener分版本超详细解析
- Quartz入门Demo(三)之TriggerListener 和 JobListener
- Quartz任务调度(4)JobListener分版本超详细解析
- Quartz教程 第7课 TriggerListener和JobListener
- Quartz-SimpleTrigger解读
- Quartz-CronTrigger解读
- Quartz-DateBuilder解读
- Quartz-TriggerListener解读
- Quartz-SchedulerListener解读
- quartz--深入解读Quartz的原理
- 深入解读Quartz的原理
- 深入解读Quartz的原理
- 深入解读Quartz的原理
- MXNet ImageNet-11k
- TCP: time wait bucket table overflow的解决方法
- linux CPU Load负载详解,lscpu详解
- Python机器学习库sklearn里利用决策树模型进行回归分析的原理
- Python机器学习库sklearn几种回归算法建模及分析(实验)
- Quartz-JobListener解读
- Vivado HLS 入门实验
- 那些精致的web UI框架
- CentOS下配置sendmail外部邮箱
- Bailian3708 1的个数【进制】
- Bailian2766 最大子矩阵【最大子段和+DP】
- C++函数的返回值(上)
- 对标英伟达,英国AI芯片制造商Graphcore获得红杉资本5000万美元新投资
- Xcode9学习笔记58