Quartz任務調度(4)JobListener分版本超詳細解析


JobListener

我們的jobListener實現類必須實現其以下方法:

方法 說明
getName() getName() 方法返回一個字符串用以說明 JobListener 的名稱。對於注冊為全局的監聽器,getName() 主要用於記錄日志,對於由特定 Job 引用的 JobListener,注冊在 JobDetail 上的監聽器名稱必須匹配從監聽器上 getName() 方法的返回值。
jobToBeExecuted() Scheduler 在 JobDetail 將要被執行時調用這個方法。
jobExecutionVetoed() Scheduler 在 JobDetail 即將被執行,但又被 TriggerListener 否決了時調用這個方法。
jobWasExecuted() Scheduler 在 JobDetail 被執行之后調用這個方法。

接下來我們以Quartz任務調度(1)概念例析快速一文中的定時扒取新聞任務和獲得最熱新聞任務為例,分析我們的監聽器方法。

1. 自定義監聽器接口實現類

public class MyJobListener implements JobListener {

    @Override//相當於為我們的監聽器命名
    public String getName() {
        return "myJobListener";
    }

    @Override
    public void jobToBeExecuted(JobExecutionContext context) {
        System.out.println(getName() + "觸發對"+context.getJobDetail().getJobClass()+"的開始執行的監聽工作,這里可以完成任務前的一些資源准備工作或日志記錄");
    }

    @Override//“否決JobDetail”是在Triiger被其相應的監聽器監聽時才具備的能力
    public void jobExecutionVetoed(JobExecutionContext context) {
        System.out.println("被否決執行了,可以做些日志記錄。");
    }

    @Override
    public void jobWasExecuted(JobExecutionContext context,
            JobExecutionException jobException) {
        System.out.println(getName() + "觸發對"+context.getJobDetail().getJobClass()+"結束執行的監聽工作,這里可以進行資源銷毀工作或做一些新聞扒取結果的統計工作");

    }

}

2. 在scheduler中注冊監聽器

這里有兩種方式,一種是注冊為全局監聽器,對所有的JobDetail都有效,另一種是注冊為針對特定JobDetail的局部監聽器。針對不同的版本,有不同的配置方式

1. 准備工作

在測試中我們用到工作實現類為

public class PickNewsJob implements Job {

    @Override
    public void execute(JobExecutionContext jec) throws JobExecutionException {
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
        System.out.println("在" + sdf.format(new Date()) + "扒取新聞");
    }
}

public class GetHottestJob implements Job {

    @Override
    public void execute(JobExecutionContext jec) throws JobExecutionException {
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
        System.out.println("在" + sdf.format(new Date()) +"根據文章的閱讀量和評論量來生成我們的最熱文章列表");
    }

}

2. 1.x版本配置

在1.+版本中,我們可以通過如下代碼監聽job

/**********局部監聽器配置**********/
JobListener myJobListener = new MyJobListener();
pickNewsJob.addJobListener("myJobListener");//這里的名字和myJobListener中getName()方法的名字一樣
scheduler.addJobListener(myJobListener);//向scheduler注冊我們的監聽器
/*********全局監聽器配置************/
JobListener myJobListener = new MyJobListener();
scheduler.addGlobalJobListener(myJobListener);//直接添加為全局監聽器

下面是我們的完整測試代碼:

public static void main(String args[]) throws SchedulerException {
    JobDetail pickNewsJob =new JobDetail("job1", "jgroup1", PickNewsJob.class); 
    JobDetail getHottestJob =new JobDetail("job2", "jgroup2", GetHottestJob.class);
    SimpleTrigger pickNewsTrigger = new SimpleTrigger("trigger1", "group1",1,2000);
    SimpleTrigger getHottestTrigger = new SimpleTrigger("trigger2", "group2",1,3000);

    SchedulerFactory schedulerFactory = new StdSchedulerFactory();
    Scheduler scheduler = schedulerFactory.getScheduler();

    /**********局部監聽器配置**********/
    JobListener myJobListener = new MyJobListener();
    pickNewsJob.addJobListener("myJobListener");//這里的名字和myJobListener中getName()方法的名字一樣
    scheduler.addJobListener(myJobListener);//向scheduler注冊我們的監聽器
    /*********全局監聽器配置************/
//      JobListener myJobListener = new MyJobListener();
//      scheduler.addGlobalJobListener(myJobListener);//直接添加為全局監聽器

    scheduler.scheduleJob(pickNewsJob,pickNewsTrigger);
    scheduler.scheduleJob(getHottestJob,getHottestTrigger);

    scheduler.start();

}

現在是使用局部監聽器的配置,運行程序,控制台打印:

myJobListener觸發對class tool.job.PickNewsJob的開始執行的監聽工作,這里可以完成任務前的一些資源准備工作或日志記錄
在11:18:31扒取新聞
在11:18:31根據文章的閱讀量和評論量來生成我們的最熱文章列表————————從這里我們可以看出兩個工作是異步進行的
myJobListener觸發對class tool.job.PickNewsJob結束執行的監聽工作,這里可以進行資源銷毀工作或做一些新聞扒取結果的統計工作
myJobListener觸發對class tool.job.PickNewsJob的開始執行的監聽工作,這里可以完成任務前的一些資源准備工作或日志記錄
在11:18:33扒取新聞
myJobListener觸發對class tool.job.PickNewsJob結束執行的監聽工作,這里可以進行資源銷毀工作或做一些新聞扒取結果的統計工作
在11:18:34根據文章的閱讀量和評論量來生成我們的最熱文章列表
我們細心觀察還會發現,我們兩個工作都運行了三次,但我們在配置觸發器時,repeatCount都是設為2。這說明我們的任務調度特點是:主執行了1次,重復了2次,於是共執行3(1+repeatCount)次。

如果我們注釋掉局部監聽代碼,啟用全局監聽,會看到控制台打印:

myJobListener觸發對class tool.job.PickNewsJob的開始執行的監聽工作,這里可以完成任務前的一些資源准備工作或日志記錄
myJobListener觸發對class tool.job.GetHottestJob的開始執行的監聽工作,這里可以完成任務前的一些資源准備工作或日志記錄
在11:25:41扒取新聞
在11:25:41根據文章的閱讀量和評論量來生成我們的最熱文章列表
myJobListener觸發對class tool.job.GetHottestJob結束執行的監聽工作,這里可以進行資源銷毀工作或做一些新聞扒取結果的統計工作
myJobListener觸發對class tool.job.PickNewsJob結束執行的監聽工作,這里可以進行資源銷毀工作或做一些新聞扒取結果的統計工作
myJobListener觸發對class tool.job.PickNewsJob的開始執行的監聽工作,這里可以完成任務前的一些資源准備工作或日志記錄
在11:25:43扒取新聞
myJobListener觸發對class tool.job.PickNewsJob結束執行的監聽工作,這里可以進行資源銷毀工作或做一些新聞扒取結果的統計工作
myJobListener觸發對class tool.job.GetHottestJob的開始執行的監聽工作,這里可以完成任務前的一些資源准備工作或日志記錄
在11:25:44根據文章的閱讀量和評論量來生成我們的最熱文章列表
myJobListener觸發對class tool.job.GetHottestJob結束執行的監聽工作,這里可以進行資源銷毀工作或做一些新聞扒取結果的統計工作
即我們的兩個任務都被監聽了

3. 2.x版本配置

在2.+版本中,引入了**org.quartz.ListenerManager和org.quartz.Matcher
**來對我們的監聽器進行更細粒度的管理配置

1. ListenerManager

我們通過ListenerManager向scheduler中添加我們的監聽器。它針對JobDetail的常用方法有:
1. public void addJobListener(JobListener jobListener)
添加全局監聽器,即所有JobDetail都會被此監聽器監聽
2. public void addJobListener(JobListener jobListener, Matcher matcher)
添加帶條件匹配的監聽器,在matcher中聲明我們的匹配條件
3. public void addJobListener(JobListener jobListener, Matcher … matchers)
添加附帶不定參條件陪陪的監聽器
4. public boolean removeJobListener(String name)
根據名字移除JobListener
5. public List getJobListeners()
獲取所有的監聽器
6. public JobListener getJobListener(String name)
根據名字獲取監聽器

2. matcher

我們通過matcher讓不同的監聽器監聽不同的任務。它有很多實現類,先逐一分析如下:

1. KeyMatcher<JobKey>

根據JobKey進行匹配,每個JobDetail都有一個對應的JobKey,里面存儲了JobName和JobGroup來定位唯一的JobDetail。它的常用方法有:

    /************構造Matcher方法************/
    KeyMatcher<JobKey> keyMatcher = KeyMatcher.keyEquals(pickNewsJob.getKey());//構造匹配pickNewsJob中的JobKey的keyMatcher。

    /*********使用方法************/
    scheduler.getListenerManager().addJobListener(myJobListener, keyMatcher);//通過這句完成我們監聽器對pickNewsJob的唯一監聽
2. GroupMatcher

根據組名信息匹配,它的常用方法有:

    GroupMatcher<JobKey> groupMatcher = GroupMatcher.jobGroupContains("group1");//包含特定字符串
            GroupMatcher.groupEndsWith("oup1");//以特定字符串結尾
            GroupMatcher.groupEquals("jgroup1");//以特定字符串完全匹配
            GroupMatcher.groupStartsWith("jgou");//以特定字符串開頭
3. AndMatcher

對兩個匹配器取交集,實例如下:

KeyMatcher<JobKey> keyMatcher = KeyMatcher.keyEquals(pickNewsJob.getKey());
GroupMatcher<JobKey> groupMatcher = GroupMatcher.jobGroupContains("group1");
AndMatcher<JobKey> andMatcher = AndMatcher.and(keyMatcher,groupMatcher);//同時滿足兩個入參匹配
4. OrMatcher

對兩個匹配器取並集,實例如下:

OrMatcher<JobKey> orMatcher = OrMatcher.or(keyMatcher, groupMatcher);//滿足任意一個即可
5. EverythingMatcher

局部全局匹配,它有兩個構造方法:

EverythingMatcher.allJobs();//對全部JobListener匹配
EverythingMatcher.allTriggers();//對全部TriggerListener匹配

下面是我們的完整測試測序:

public static void main(String args[]) throws SchedulerException {
    final JobDetail pickNewsJob = JobBuilder.newJob(PickNewsJob.class)
            .withIdentity("job1", "jgroup1").build();
    JobDetail getHottestJob = JobBuilder.newJob(GetHottestJob.class)
            .withIdentity("job2", "jgroup2").build();
    SimpleTrigger pickNewsTrigger = TriggerBuilder
            .newTrigger()
            .withIdentity("trigger1","tgroup1")
            .withSchedule(SimpleScheduleBuilder.repeatSecondlyForTotalCount(2, 1)).startNow()
            .build();
    SimpleTrigger getHottestTrigger = TriggerBuilder
            .newTrigger()
            .withIdentity("trigger2","tgroup2")
            .withSchedule(SimpleScheduleBuilder.repeatSecondlyForTotalCount(2, 2)).startNow()
            .build();
    Scheduler scheduler = new StdSchedulerFactory().getScheduler();
    JobListener myJobListener = new MyJobListener();
    KeyMatcher<JobKey> keyMatcher = KeyMatcher.keyEquals(pickNewsJob.getKey());
    scheduler.getListenerManager().addJobListener(myJobListener, keyMatcher);
    scheduler.scheduleJob(pickNewsJob, pickNewsTrigger);
    scheduler.scheduleJob(getHottestJob,getHottestTrigger);
    scheduler.start();
}

運行程序,我們得到下列打印信息:

myJobListener觸發對class tool.job.PickNewsJob的開始執行的監聽工作,這里可以完成任務前的一些資源准備工作或日志記錄
根據文章的閱讀量和評論量來生成我們的最熱文章列表
在12:48:58扒取新聞
myJobListener觸發對class tool.job.PickNewsJob結束執行的監聽工作,這里可以進行資源銷毀工作或做一些新聞扒取結果的統計工作
myJobListener觸發對class tool.job.PickNewsJob的開始執行的監聽工作,這里可以完成任務前的一些資源准備工作或日志記錄
在12:48:59扒取新聞
myJobListener觸發對class tool.job.PickNewsJob結束執行的監聽工作,這里可以進行資源銷毀工作或做一些新聞扒取結果的統計工作
根據文章的閱讀量和評論量來生成我們的最熱文章列表
顯然,myJobListener只和我們的PickNewsJob匹配了。
關於測試代碼的其他配置可移步參考本系列前面的文章,里面都有詳細的配置實例講解


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM