林炳文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();
-
}
-
-
}
-
}
輸出結果:
或者看大圖!
然後是scheduler關閉後
這就是最後的結果了
林炳文Evankaka原創作品。轉載請註明出處http://blog.csdn.net/evankaka
本文工程免費下載