Quartz的監聽器用於當任務調度中你所關注事件發生時,可以及時獲取這一事件的通知。Quartz監聽器主要有JobListener、TriggerListener、SchedulerListener三種,顧名思義,分別表示任務、觸發器、調度器對應的監聽器。三者的使用方法相似,在開始介紹三種監聽器以前,須要明確兩個概念:全局監聽器與非全局監聽器,兩者的區別在於:全局監聽器可以接收到全部的Job/Trigger的事件通知,而非全局監聽器只能接收到在其上註冊的Job或Trigger的事件,不在其上註冊的Job或Trigger則不會進行監聽。java
任務調度過程當中,與任務Job相關的事件包括:job開始要執行的提示; job執行完成的提示燈。其接口以下:apache
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的名稱。ide
jobToBeExecuted方法:Scheduler在JobDetail將要被執行時調用這個方法。ui
jobExecutionVetoed方法:Scheduler在JobDetail即將被執行,但又被TriggerListerner否決時會調用該方法this
jobWasExecuted方法:Scheduler在JobDetail被執行以後調用這個方法code
參考以下代碼orm
package com; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.quartz.JobListener; /** * @program: hello * @description: * @author: lee * @create: 2019-01-17 **/ public class JobListenerDemo implements JobListener { @Override public String getName() { String name=getClass().getSimpleName(); return name; } @Override public void jobToBeExecuted(JobExecutionContext jobExecutionContext) { String jobname=jobExecutionContext.getJobDetail().getKey().getName(); System.out.println(jobname+"is going to be executed"); } @Override public void jobExecutionVetoed(JobExecutionContext jobExecutionContext) { String jobname=jobExecutionContext.getJobDetail().getKey().getName(); System.out.println(jobname+"was vetoed and not executed"); } @Override public void jobWasExecuted(JobExecutionContext jobExecutionContext, JobExecutionException e) { String jobname=jobExecutionContext.getJobDetail().getKey().getName(); System.out.println(jobname+"was executed"); } } package com; import com.sun.org.apache.xpath.internal.SourceTree; import org.quartz.*; import java.text.SimpleDateFormat; import java.util.Date; /** * @program: hello * @description: 自定義Job * @author: lee * @create: 2019-01-13 **/ public class PJob implements Job { @Override public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { Date date=new Date(); SimpleDateFormat dateFormat= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String dateString=dateFormat.format(date); System.out.println("正在運行job任務,運行時間是:"+dateString); } } package com; import org.quartz.*; import org.quartz.impl.StdSchedulerFactory; import org.quartz.impl.matchers.EverythingMatcher; import org.quartz.impl.matchers.KeyMatcher; import java.util.Date; /** * @program: hello * @description: 任務調度入口 * @author: lee * @create: 2019-01-13 **/ public class PScheduller { public static void main(String[] args) throws SchedulerException { PScheduller exam = new PScheduller(); Scheduler scheduler = exam.createScheduler(); JobDetail jobDetail = exam.createJobDetail("jobid", "jobgroup"); Trigger trigger = exam.createTrigger("tiggername", "triggergroup"); JobDetail jobDetail2 = exam.createJobDetail("jobid2", "jobgroup2"); Trigger trigger2 = exam.createTrigger("tiggername2", "triggergroup2"); scheduler.scheduleJob(jobDetail, trigger); scheduler.scheduleJob(jobDetail2, trigger2); // 建立並註冊一個全局的Job Listener //scheduler.getListenerManager().addJobListener(new JobListenerDemo(), EverythingMatcher.allJobs()); // 建立並註冊一個指定任務的Job Listener scheduler.getListenerManager().addJobListener(new JobListenerDemo(), KeyMatcher.keyEquals(JobKey.jobKey("jobid","jobgroup"))); scheduler.start(); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } scheduler.shutdown(); } protected Scheduler createScheduler() throws SchedulerException { return StdSchedulerFactory.getDefaultScheduler(); } protected Trigger createTrigger(String triggerName, String triggerGroup) { return TriggerBuilder.newTrigger().withIdentity(triggerName, triggerGroup) .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(4).repeatForever()) .build(); } protected JobDetail createJobDetail(String jobName, String jobGroup) { return JobBuilder.newJob(PJob.class) .withIdentity(jobName, jobGroup) .build(); } }
輸出結果 第一種狀況接口
jobidis going to be executed jobid2is going to be executed 正在運行job任務,運行時間是:2019-01-21 20:29:31 正在運行job任務,運行時間是:2019-01-21 20:29:31 jobidwas executed jobid2was executed
第二種狀況生命週期
jobidis going to be executed 正在運行job任務,運行時間是:2019-01-21 20:28:31 jobidwas executed 正在運行job任務,運行時間是:2019-01-21 20:28:31
將同一任務組的任務註冊到監聽器中事件
scheduler.getListenerManager().addJobListener(new JobListenerDemo(), GroupMatcher.jobGroupEquals("jobgroup2"));
將兩個任務組的任務註冊到監聽器中
scheduler.getListenerManager().addJobListener(new JobListenerDemo(), OrMatcher.or(GroupMatcher.jobGroupEquals("jobgroup"), GroupMatcher.jobGroupEquals("jobgroup2")));
任務調度過程當中,與觸發器Trigger相關的事件包括:觸發器觸發、觸發器未正常觸發、觸發器完成等。TriggerListener的接口以下:
public interface TriggerListener { public String getName(); public void triggerFired(Trigger trigger, JobExecutionContext context); public boolean vetoJobExecution(Trigger trigger, JobExecutionContext context); public void triggerMisfired(Trigger trigger); public void triggerComplete(Trigger trigger, JobExecutionContext context, int triggerInstructionCode); }
getName方法:用於獲取觸發器的名稱
triggerFired方法:當與監聽器相關聯的Trigger被觸發,Job上的execute()方法將被執行時,Scheduler就調用該方法。
vetoJobExecution方法:在 Trigger 觸發後,Job 將要被執行時由 Scheduler 調用這個方法。TriggerListener 給了一個選擇去否決 Job 的執行。假如這個方法返回 true,這個 Job 將不會爲這次 Trigger 觸發而獲得執行。
triggerMisfired方法:Scheduler 調用這個方法是在 Trigger 錯過觸發時。你應該關注此方法中持續時間長的邏輯:在出現許多錯過觸發的 Trigger 時,長邏輯會致使骨牌效應。你應當保持這上方法儘可能的小。
triggerComplete方法:Trigger 被觸發而且完成了 Job 的執行時,Scheduler 調用這個方法。
代碼以下
package com; import org.quartz.JobExecutionContext; import org.quartz.Trigger; import org.quartz.TriggerListener; /** * @program: hello * @description: * @author: lee * @create: 2019-01-21 **/ public class TriggerListenerDemo implements TriggerListener { private String name; public TriggerListenerDemo(String name) { this.name = name; } @Override public String getName() { return name; } @Override public void triggerFired(Trigger trigger, JobExecutionContext jobExecutionContext) { String name=trigger.getKey().getName(); System.out.println("trigger name is "+name); } @Override public boolean vetoJobExecution(Trigger trigger, JobExecutionContext jobExecutionContext) { return false; } @Override public void triggerMisfired(Trigger trigger) { String name=trigger.getKey().getName(); System.out.println("triggerMisfired is running "+name); } @Override public void triggerComplete(Trigger trigger, JobExecutionContext jobExecutionContext, Trigger.CompletedExecutionInstruction completedExecutionInstruction) { String name=trigger.getKey().getName(); System.out.println("triggerComplete is running "+name); } }
調度程序中須要加入
scheduler.getListenerManager().addTriggerListener(new TriggerListenerDemo("TriggerListenerDemo"), GroupMatcher.groupEquals("triggergroup"));
SchedulerListener會在Scheduler的生命週期中關鍵事件發生時被調用。與Scheduler有關的事件包括:增長一個job/trigger,刪除一個job/trigger,scheduler發生嚴重錯誤,關閉scheduler等。
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中的數據被清除時,調用該方法。
示例:
package com; import org.quartz.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @program: hello * @description: * @author: lee * @create: 2019-01-21 **/ public class SchedullerListener implements SchedulerListener { private static Logger logger = LoggerFactory.getLogger(SchedullerListener.class); @Override public void jobScheduled(Trigger trigger) { String jobName = trigger.getJobKey().getName(); System.out.println(jobName + " has been scheduled"); } @Override public void jobUnscheduled(TriggerKey triggerKey) { System.out.println(triggerKey + " is being unscheduled"); } @Override public void triggerFinalized(Trigger trigger) { System.out.println("Trigger is finished for " + trigger.getJobKey().getName()); } @Override public void triggerPaused(TriggerKey triggerKey) { System.out.println(triggerKey + " is being paused"); } @Override public void triggersPaused(String triggerGroup) { System.out.println("trigger group "+triggerGroup + " is being paused"); } @Override public void triggerResumed(TriggerKey triggerKey) { System.out.println(triggerKey + " is being resumed"); } @Override public void triggersResumed(String triggerGroup) { System.out.println("trigger group "+triggerGroup + " is being resumed"); } @Override public void jobAdded(JobDetail jobDetail) { System.out.println(jobDetail.getKey()+" is added"); } @Override public void jobDeleted(JobKey jobKey) { System.out.println(jobKey+" is deleted"); } @Override public void jobPaused(JobKey jobKey) { System.out.println(jobKey+" is paused"); } @Override public void jobsPaused(String jobGroup) { System.out.println("job group "+jobGroup+" is paused"); } @Override public void jobResumed(JobKey jobKey) { System.out.println(jobKey+" is resumed"); } @Override public void jobsResumed(String jobGroup) { System.out.println("job group "+jobGroup+" is resumed"); } @Override public void schedulerError(String msg, SchedulerException cause) { System.out.println(cause.getUnderlyingException()); } @Override public void schedulerInStandbyMode() { logger.info("scheduler is in standby mode"); } @Override public void schedulerStarted() { logger.info("scheduler has been started"); } @Override public void schedulerStarting() { logger.info("scheduler is being started"); } @Override public void schedulerShutdown() { logger.info("scheduler has been shutdown"); } @Override public void schedulerShuttingdown() { logger.info("scheduler is being shutdown"); } @Override public void schedulingDataCleared() { logger.info("scheduler has cleared all data"); } }
調度器代碼
package com; import org.quartz.*; import org.quartz.impl.StdSchedulerFactory; import org.quartz.impl.matchers.EverythingMatcher; import org.quartz.impl.matchers.GroupMatcher; import org.quartz.impl.matchers.KeyMatcher; import org.quartz.impl.matchers.OrMatcher; import java.util.Date; /** * @program: hello * @description: 任務調度入口 * @author: lee * @create: 2019-01-13 **/ public class PScheduller { public static void main(String[] args) throws SchedulerException, InterruptedException { PScheduller exam = new PScheduller(); Scheduler scheduler = exam.createScheduler(); JobDetail jobDetail = exam.createJobDetail("jobid", "jobgroup"); Trigger trigger = exam.createTrigger("tiggername", "triggergroup"); scheduler.scheduleJob(jobDetail, trigger); // 建立SchedulerListener scheduler.getListenerManager().addSchedulerListener(new SchedullerListener()); scheduler.start(); Thread.sleep(20000); scheduler.shutdown(); } protected Scheduler createScheduler() throws SchedulerException { return StdSchedulerFactory.getDefaultScheduler(); } protected Trigger createTrigger(String triggerName, String triggerGroup) { return TriggerBuilder.newTrigger().withIdentity(triggerName, triggerGroup) .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(4).repeatForever()) .build(); } protected JobDetail createJobDetail(String jobName, String jobGroup) { return JobBuilder.newJob(PJob.class) .withIdentity(jobName, jobGroup) .build(); } }