Quartz Tutorial 4 - Simple Trigger

Quartz Tutorial 4 - Simple Trigger

Quartz Tutorial 4 - Simple Trigger

当你的某个任务仅需要在某个特定时间执行一次,或者在某个特定时间之后以固定间隔重复特定的次数,此时就用到了SimpleTrigger了。例如,你需要在某年月日某时分秒触发作业的执行,或者在那个时间后再触发5次,间隔10秒钟。

通过这些,很容易就能想到SimpleTrigger所包含的属性:开始时间,结束时间,重复次数,还有重复间隔。所有这些属性都确实存在,跟你想的确实一样。只是对于结束时间属性,有一些特殊的地方。

重复的次数可以为0、正整数或者是一个常量SimpleTrigger.REPEAT_INDEFINITELY。重复间隔属性必须是0或者一个正的long类型数字,它表示毫秒数。要注意,当重复间隔设为0的时候,触发器将会被同步地触发(或者是调度器所能做到的尽可能靠近的触发)

如果你熟悉Quartz的DateBuilder类,当你想通过你要创建的开始时间startTime(或结束时间endTime)来计算触发的次数,你就知道这个类特别有用。

如果特别声明了结束时间endTime属性,,那么它将覆盖掉重复次数这一属性。比如你可以创建一个每十秒重复一次直到某个特定时间停止的触发器-你不需要计算在起止时间内到底重复了多少次,甚至你可以将重复次数属性赋值为REPEAT_INDEFINITELY(你也可以降之设定为一个足够大的值,保证该值大于它将要实际重复的次数)

SimpleTrigger的实例构造是通过TriggerBuilder类(设置触发器的主要共有属性)和SimpleScheduleBuilder类(设置SimpleTrigger类型触发器特有的属性)。首先静态导入如下类型,就能用DSL风格构造触发器实例了。

1
2
3
import static org.quartz.TriggerBuilder.*;
import static org.quartz.SimpleScheduleBuilder.*;
import static org.quartz.DateBuilder.*;

下面是定义触发器的多个例子,各自存在不同要点:

  • 特定时刻触发,无重复

    1
    2
    3
    4
    5
    
    SimpleTrigger trigger = (SimpleTrigger) newTrigger()
        .withIdentity("trigger1", "group1")
        .startAt(startTime)     // some date
        .forJob("job1", "group1")   // identify job with name, group strings
        .build();
    
  • 特定时刻触发,每10秒触发一次,重复10次

    1
    2
    3
    4
    5
    6
    7
    8
    
    trigger = newTrigger()
        .withIdentity("trigger3","group1")
        .startAt(myTimeToStartFiring)   // if a start time is not given(if this line we omitted), "now" is implied
        .withSchedule(simpleSchedule()
            .withIntervalInSeconds(10)
            .withRepeatCount(10))   // note that 10 repeats will given a total of 11 firings
        .forJob(myJob)  // identify job with handle to its JobDetail itself
        .build();
    
  • 仅五分钟后触发一次

    1
    2
    3
    4
    5
    
    trigger = (SimpleTrigger) newTrigger()
        .withIdentity("trigger5", "group1")
        .startAt(futureDate(5, IntervalUnit.MINUTE))    // use DateBuilder to create a date in the future
        .forJob(myJob)  // identify job with its JobKey
        .build();
    
  • 立即触发,然后每5分钟触发一次,直到22:00

    1
    2
    3
    4
    5
    6
    7
    
    trigger = newTrigger()
        .withIdentity("trigger7", "group1")
        .withSchedule(simpleSchedule()
            .withIntervalInMinutes(5)
            .reportForever())
        .endAt(dateOf(22, 0, 0))
        .build();
    
  • 下一小时一到立即触发,然后每两小时触发一次,永久重复

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    
    trigger = newTrigger()
        .withIdentity("trigger8")   // because group isn't specificated, "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的其他builder)一般会选择一个合理的值赋给你没有显式赋值的属性。例如,你没有调用withIdentity(...)方法,那么TriggerBuilder将会生成一个随机的名字,如果你没有调用startAt(...),它将会假定你要使用当前时间(立即触发)

SimpleTrigger MisFire Instructions

当发生了misfire(“哑火”?),SimpleTrigger提供了一些指令用于告知Quartz该如何处理。这些指令是作为SimpleTrigger自身的常量来定义的(JavaDoc介绍了它们的行为),这些常量包括:

1
2
3
4
5
6
7
8
// Misfire Instruction Constants of Simple Trigger

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指令可用,这也是所有触发器默认的选择。

如果使用了“smart policy”,SimpleTrigger在它多种选项内动态选择,具体取决于该触发器实例的配置和状态。SimpleTrigger.updateAfterMisfire()方法的JavaDoc解释了动态行为的更多细节。

当然,你也可以在构建SimpleTrigger实例的时候设置上这一属性(通过SimpleScheduleBuilder

1
2
3
4
5
6
7
trigger = newTrigger()
    .withIdentity("tigger7", "group1")
    .withSchedule(simpleSchedule()
        .withIntervalInMinutes(5)
        .repeatForever()
        .withMisfireHandlingInstructionNextWithExistingCount())
    .build();