1. 程式人生 > >Quartz 框架 教程(中文版)2.2.x 之第五課 SimpleTrigger

Quartz 框架 教程(中文版)2.2.x 之第五課 SimpleTrigger

第五課 SimpleTrigger

        如果你需要在一個指定時間段內執行一次作業任務或是在指定的時間間隔內多次執行作業任務,SimpleTrigger應該能滿足你的排程需求。例如,你希望觸發器在2015113日上午11:23:54準時觸發,或是希望在那個時間點觸發,然後再重複觸發5次,每隔10秒一次。有了這樣的描述,你就不會對SimpleTrigger包含的引數感到奇怪:開始執行時間,結束執行時間,重複次數和重複執行間隔時間。所有的引數都是你期望的那樣,只是關於結束執行時間引數有兩條特別的提示。

        重複次數可以為0,正整數或是SimpleTrigger.REPEAT_INDEFINITELY

常量值。重複執行間隔必須為0或長整數(long型別),它表示毫秒數的值。注意如果重複執行間隔時間為0會導致數量為“重複次數”的觸發器併發執行(或是在排程器控制下接近併發執行)。

        如果你還不熟悉QuartzDateBuilder類,你嘗試建立日期物件時會發現它非常方便地根據startTimeendTime引數計算觸發器的觸發時間。

         endTime引數(如果被指定)會覆蓋重複次數引數的效果。當你希望建立一個觸發器,每隔10秒被觸發一次直到給定的截止時間,而不是必須完成在給定的開始和結束時間段內的觸發次數,使用endTime引數會非常方便,你可以僅僅指定一個end-time

引數,並且將重複次數設定為REPEAT_INDEFINITELY(你甚至可以將重複次數指定為非常大的值,確保比結束執行時間到達前實際要執行的次數大就行)。

       SimpleTrigger例項物件可以使用TriggerBuilder(針對觸發器主要的引數)和SimpleScheduleBuilder(針對SimpleTrigger的指定引數)來建立。為了使用這些建立類時滿足DSL格式,使用靜態匯入:

import static org.quartz.TriggerBuilder.*;
import static org.quartz.SimpleScheduleBuilder.*;
import static org.quartz.DateBuilder.*:

       下面是使用簡易排程器定義觸發器的幾個案例,請通讀一遍,每個例子都至少展示了一個新的、不同的知識點:

    建立觸發器時指定具體的時間,不重複執行:

SimpleTrigger trigger = (SimpleTrigger) newTrigger() 
    .withIdentity("trigger1", "group1")
    .startAt(myStartTime) // some Date 
    .forJob("job1", "group1") // identify job with name, group strings
    .build();


        建立觸發器時指定具體的時間,然後每隔10秒觸發一次,共重複觸發10次:

trigger = newTrigger()
    .withIdentity("trigger3", "group1")
    .startAt(myTimeToStartFiring)  // if a start time is not given (if this line were omitted), "now" is implied
    .withSchedule(simpleSchedule()
        .withIntervalInSeconds(10)
        .withRepeatCount(10)) // note that 10 repeats will give a total of 11 firings
    .forJob(myJob) // identify job with handle to its JobDetail itself                   
    .build();
    建立觸發器,5分鐘後將會觸發一次:
trigger = (SimpleTrigger) newTrigger() 
    .withIdentity("trigger5", "group1")
    .startAt(futureDate(5, IntervalUnit.MINUTE)) // use DateBuilder to create a date in the future
    .forJob(myJobKey) // identify job with its JobKey
    .build();
    建立觸發器時立即觸發,然後每隔5分鐘觸發一次,直到22:00:
trigger = newTrigger()
    .withIdentity("trigger7", "group1")
    .withSchedule(simpleSchedule()
        .withIntervalInMinutes(5)
        .repeatForever())
    .endAt(dateOf(22, 0, 0))
    .build();
    建立觸發器時,在下一個整點小時觸發,然後每隔2小時觸發一次,永不停歇:
trigger = newTrigger()
    .withIdentity("trigger8") // because group is not specified, "trigger8" will be in the default group
    .startAt(evenHourDate(null)) // get the next even-hour (minutes and seconds zero ("00:00"))
    .withSchedule(simpleSchedule()
        .withIntervalInHours(2)
        .repeatForever())
    // note that in this example, 'forJob(..)' is not called 
    //  - which is valid if the trigger is passed to the scheduler along with the job  
    .build();
            
    scheduler.scheduleJob(trigger, job);
   花點時間查閱TriggerBuilderSimpleScheduleBuilder類的所有可用方法,以便你能熟悉在上面演示程式碼中可能沒有展示的有用操作。
    注意TriggerBuilder(或是Quartz別的建立類)在你沒有明確設定引數值時一般會選擇合理的值。例如,如果你沒有呼叫withIdentity方法,TriggerBuilder會為你的觸發器產生一個隨機的名字,如果你沒有呼叫startAt方法,它會假設是立即觸發。

SimpleTrigger的觸發失敗指令

         SimpleTrigger有幾條指令,用來告知Quartz當觸發失敗時該如何操作。(在第四課更多關於觸發器已經介紹過觸發失敗的情況)。這些指令在SimpleTrigger類中設計成常量(包含JavaDoc描述了它們的行為)。指令有:
   SimpleTrigger的觸發失敗指令常量:
MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY
MISFIRE_INSTRUCTION_FIRE_NOW
MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT
MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT
MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT
MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT

回顧前面的課程可以知道:所有的觸發器都可以使用Trigger.MISFIRE_INSTRUCTION_SMART_POLICY指令,並且這條指令也是所有觸發器的預設指令。

如果使用“智慧策略”指令,SimpleTrigger會從多條觸發失敗指令集中根據配置和SimpleTrigger例項的狀態動態地選擇指令。JavaDoc文件中SimpleTriggerupdateAfterMisfire方法解釋了動態選擇行為更詳細的資訊。

當你建立SimpleTrigger時,可以通過SimpleSchedulerBuilder指定觸發失敗指令作為排程器的一部分。
trigger = newTrigger()
    .withIdentity("trigger7", "group1")
    .withSchedule(simpleSchedule()
        .withIntervalInMinutes(5)
        .repeatForever()
        .withMisfireHandlingInstructionNextWithExistingCount())
    .build();