Quartz-JobListener解读
文章目錄
- 概述
- 步驟簡(jiǎn)述
- 全局/非全局監(jiān)聽(tīng)器
- JobListener 任務(wù)監(jiān)聽(tīng)器 示例
- JobListener源碼
- 完整示例
- 示例源碼
概述
在某個(gè)所關(guān)注事件發(fā)生時(shí),監(jiān)聽(tīng)器提供了一種方便且非侵入性的機(jī)制來(lái)獲得這一通知。Quartz 提供了三種類型的監(jiān)聽(tīng)器:監(jiān)聽(tīng) Job 的,監(jiān)聽(tīng) Trigger 的,和監(jiān)聽(tīng) Scheduler 自已的。
本博文闡述如何應(yīng)用每一種類型來(lái)更好的管理你的 Quartz 應(yīng)用,并獲悉到什么事件正在發(fā)生。
參考官方Demo:
http://www.quartz-scheduler.org/documentation/quartz-2.2.x/tutorials/tutorial-lesson-07.html
步驟簡(jiǎn)述
要?jiǎng)?chuàng)建一個(gè)Listener, 只需要?jiǎng)?chuàng)建一個(gè)實(shí)現(xiàn)了org.quartz.TriggerListener或org.quartz.JobListener接口的對(duì)象即可。
在運(yùn)行的時(shí)候,將Listeners注冊(cè)進(jìn)scheduler, 而且必須給一個(gè)name(可以通過(guò)他們的getName()方法獲取Listener的name)。
除了繼承接口,類也可以繼承JobListenerSupport或TriggerListenerSupport,重寫你感興趣的event。
Listener通過(guò)scheduler的ListenerManager來(lái)注冊(cè),其中的Matcher 里描述哪個(gè)Jobs、Triggers需要被監(jiān)聽(tīng)。
注意:
LListeners在運(yùn)行的時(shí)候被注冊(cè)進(jìn)scheduler, 而不是保存在JobStore。Listener是和你的應(yīng)用集成在一起的,這樣每次你的應(yīng)用運(yùn)行的時(shí)候,都會(huì)在scheduler中重新注冊(cè)listeners。
全局/非全局監(jiān)聽(tīng)器
JobListener 和 TriggerListener 可被注冊(cè)為全局或非全局監(jiān)聽(tīng)器。
-
全局監(jiān)聽(tīng)器能接收到所有的 Job/Trigger 的事件通知。
-
非全局監(jiān)聽(tīng)器(或者說(shuō)是一個(gè)標(biāo)準(zhǔn)的監(jiān)聽(tīng)器) 只能接收到那些在其上已注冊(cè)了監(jiān)聽(tīng)器的 Job 或 Triiger 的事件。
你要注冊(cè)你的監(jiān)聽(tīng)器為全局或非全局的需依據(jù)你特定的應(yīng)用需要。
全局監(jiān)聽(tīng)器是主動(dòng)意識(shí)的,它們?yōu)榱藞?zhí)行它們的任務(wù)而熱切的去尋找每一個(gè)可能的事件。通常全局監(jiān)聽(tīng)器要做的工作不用指定到特定的 Job 或 Trigger。非全局監(jiān)聽(tīng)器一般是被動(dòng)意識(shí)的,它們?cè)谒P(guān)注的 Trigger 激發(fā)之前或是 Job 執(zhí)行之前什么事也不做。因此,非全局的監(jiān)聽(tīng)器比起全局監(jiān)聽(tīng)器而言更適合于修改或增加 Job 執(zhí)行的工作。這有點(diǎn)像知名的裝飾設(shè)計(jì)模式的裝飾器。
全局 監(jiān)聽(tīng)器
scheduler.addGlobalTriggerListener(new SimpleMyTriggerListener());非全局監(jiān)聽(tīng)器
scheduler.addTriggerListener( triggerListener ); trigger.addTriggerListener( triggerListener.getName() );JobListener 任務(wù)監(jiān)聽(tīng)器 示例
JobListener源碼
我們先來(lái)看下JobListener的源碼:
-
getName() :返回一個(gè)字符串用以說(shuō)明 JobListener 的名稱。對(duì)于注冊(cè)為全局的監(jiān)聽(tīng)器,getName()主要用于記錄日志,對(duì)于由特定 Job 引用的JobListener,注冊(cè)在 JobDetail 上的監(jiān)聽(tīng)器名稱必須匹配從監(jiān)聽(tīng)器getName() 方法的返回值。
-
jobToBeExecuted() :Scheduler 在 JobDetail 將要被執(zhí)行時(shí)調(diào)用這個(gè)方法。
-
jobExecutionVetoed() :Scheduler 在 JobDetail 即將被執(zhí)行,但又被 TriggerListener否決了時(shí)調(diào)用這個(gè)方法。
-
jobWasExecuted() :Scheduler 在 JobDetail 被執(zhí)行之后調(diào)用這個(gè)方法。
自定義監(jiān)聽(tīng)器
import org.quartz.*;public class MyJobListener implements JobListener {@Overridepublic String getName() {return "MyJobListener";}@Overridepublic void jobExecutionVetoed(JobExecutionContext arg0) {System.out.println("Job監(jiān)聽(tīng)器:MyJobListener.jobExecutionVetoed()");}@Overridepublic void jobToBeExecuted(JobExecutionContext arg0) {System.out.println("Job監(jiān)聽(tīng)器:MyJobListener.jobToBeExecuted()");}@Overridepublic void jobWasExecuted(JobExecutionContext arg0,JobExecutionException arg1) {System.out.println("Job監(jiān)聽(tīng)器:MyJobListener.jobWasExecuted()");}}注冊(cè)監(jiān)聽(tīng)器
MyJobListener myJobListener=new MyJobListener(); // 添加一個(gè)特定的job scheduler.getListenerManager().addJobListener(myJobListener, KeyMatcher.jobKeyEquals(new JobKey("myJobName", "myJobGroup")));上面的代碼就可以變成:
scheduler.getListenerManager().addJobListener(myJobListener, jobKeyEquals(jobKey("myJobName", "myJobGroup")));// 添加特定組的所有jobs scheduler.getListenerManager().addJobListener(myJobListener, jobGroupEquals("myJobGroup"));// 添加多個(gè)特定組的所有jobs scheduler.getListenerManager().addJobListener(myJobListener, or(jobGroupEquals("myJobGroup"), jobGroupEquals("yourGroup")));// 添加所有jobs scheduler.getListenerManager().addJobListener(myJobListener, allJobs());有了Listeners以后,當(dāng)應(yīng)用需要在某些事件發(fā)生以后去通知你的應(yīng)用,這時(shí)就不需要Job去明確地去告知你的應(yīng)用了。
完整示例
添加一個(gè)jobListener,監(jiān)聽(tīng)到j(luò)ob1執(zhí)行后,再觸發(fā)一個(gè)job2任務(wù)
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 - 任務(wù)key "+ jobKey+ "執(zhí)行時(shí)間:"+ 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 - 任務(wù)key "+ jobKey+ "執(zhí)行時(shí)間:"+ 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監(jiān)聽(tīng)器* * getName() :返回一個(gè)字符串用以說(shuō)明 JobListener 的名稱。對(duì)于注冊(cè)為全局的監(jiān)聽(tīng)器,getName()* 主要用于記錄日志,對(duì)于由特定 Job 引用的 JobListener,注冊(cè)在 JobDetail* 上的監(jiān)聽(tīng)器名稱必須匹配從監(jiān)聽(tīng)器上 getName() 方法的返回值.* * jobToBeExecuted() :Scheduler 在 JobDetail 將要被執(zhí)行時(shí)調(diào)用這個(gè)方法。* * jobExecutionVetoed() :Scheduler 在 JobDetail 即將被執(zhí)行,但又被* TriggerListener 否決了時(shí)調(diào)用這個(gè)方法。* * jobWasExecuted() :Scheduler 在 JobDetail 被執(zhí)行之后調(diào)用這個(gè)方法。* * @author: Mr.Yang* * @date: 2017年11月16日 下午3:57:35*/ public class MyJobListener implements JobListener {@Overridepublic String getName() {return "MyJobListerner";}@Overridepublic void jobToBeExecuted(JobExecutionContext context) {System.out.println("Job監(jiān)聽(tīng)器:MyJobListener.jobToBeExecuted()");}@Overridepublic void jobExecutionVetoed(JobExecutionContext context) {System.out.println("Job監(jiān)聽(tīng)器:MyJobListener.jobExecutionVetoed()");}@Overridepublic void jobWasExecuted(JobExecutionContext context,JobExecutionException jobException) {System.out.println("Job監(jiān)聽(tīng)器:MyJobListener.jobWasExecuted()");// 設(shè)置另外一個(gè)job執(zhí)行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("無(wú)法安排job2!");e.printStackTrace();}}}調(diào)度類
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("------- 初始化 ----------------------");// SchedulerSchedulerFactory schedulerFactory = new StdSchedulerFactory();Scheduler scheduler = schedulerFactory.getScheduler();// JobJobDetail job = newJob(Job1.class).withIdentity("job1", "group1").build();// Tirgger Trigger trigger = newTrigger().withIdentity("trigger1", "group1").startNow().build();// 設(shè)置監(jiān)聽(tīng)器JobListener jobListener = new MyJobListener();Matcher<JobKey> matcher = KeyMatcher.keyEquals(job.getKey());scheduler.getListenerManager().addJobListener(jobListener, matcher);// 將job任務(wù)加入到調(diào)度器scheduler.scheduleJob(job, trigger);// 開(kāi)始任務(wù)System.out.println("------- 開(kāi)始執(zhí)行調(diào)度器 Scheduler ----------------");scheduler.start();try {System.out.println("------- 等待 30 秒... --------------");Thread.sleep(30L * 1000L);} catch (Exception e) {e.printStackTrace();}scheduler.shutdown(true);System.out.println("------- 關(guān)閉調(diào)度器 -----------------");SchedulerMetaData metaData = scheduler.getMetaData();System.out.println("~~~~~~~~~~ 執(zhí)行了 "+ metaData.getNumberOfJobsExecuted() + " 個(gè) jobs.");}}運(yùn)行結(jié)果
------- 初始化 ---------------------- INFO StdSchedulerFactory - Using default implementation for ThreadExecutor INFO SimpleThreadPool - Job execution threads will use class loader of thread: main INFO SchedulerSignalerImpl - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl INFO 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: 0Using 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 ------- 開(kāi)始執(zhí)行調(diào)度器 Scheduler ---------------- INFO QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED started. ------- 等待 30 秒... -------------- Job監(jiān)聽(tīng)器:MyJobListener.jobToBeExecuted()Job1 - 任務(wù)key group1.job1執(zhí)行時(shí)間:2017-11-16 17:58:54 Job監(jiān)聽(tīng)器:MyJobListener.jobWasExecuted()Job2 - 任務(wù)key DEFAULT.job2執(zhí)行時(shí)間:2017-11-16 17:58:54 INFO QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED shutting down. INFO QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED paused. INFO QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED shutdown complete. ------- 關(guān)閉調(diào)度器 ----------------- ~~~~~~~~~~ 執(zhí)行了 2 個(gè) jobs.示例源碼
代碼已托管到Github—> https://github.com/yangshangwei/SpringMaster
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的Quartz-JobListener解读的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Quartz-DateBuilder解读
- 下一篇: Quartz-TriggerListen