Quartz Tutorial 3 - More About Triggers

Quartz Tutorial 3 - More About Triggers

Quartz Tutorial 3 - More About Triggers

类似作业,触发器也是一样易于使用,只是它还包含了一些可自定义的选项。如果想要用Quartz用得飞起,那你需要了解它们。当然首先应该说明,Quartz提供了多种类型的触发器供你使用。

在后面两节,你能了解两个主流使用的触发器SimpleTriggerCronTrigger

Common Trigger Attributes

先不提所有的触发器都会有的用于标识自己的TriggerKey属性,还有很多其它共有的属性,这些共有的属性可以在你构建一个触发器定义的时候使用TriggerBuilder进行设置。

这些属性如下所示:

  • jobKey属性表示该触发器被触发时,应该执行的作业的标识符
  • startTime属性表示该触发器的调度器开始干活的时间。这个值是java.util.Data对象,定义了一个时刻。对于某些类型的触发器,它们确实是在开始时间触发的,而另一些就是简单标记了一个时间,其余的触发都是在这个时间之后的。比如你定义了一个触发器并告知调度器“一月份每隔五天”触发一次,然后你设置开始时间是四月一号,那么要过好几个月,该触发器才会被首次触发。
  • endTime属性表示该触发器的调度器停止干活的时间。

其他属性在接下来几个小节讨论

Priority

有些时候会出现这样的情况,某个时刻有很多个触发器需要被触发,但是Quartz并没有足够的工作线程/资源让这些触发器通通立即触发。那么这个时候,你可能想要给他们指定一个优先级,来告知Quartz应该先触发哪个后触发哪个。这个时候就需要用到priority属性了。如果某个时刻有N个触发器需要被触发,但是只有Z个工作线程可用,那么前Z个优先级最高的触发器将会被首先触发。如果你没有显式指定优先级,那么触发器使用默认值5。任何整数值都可以用来指定优先级,包括负数。

注意:优先级只是在多触发器在同一时刻触发的时候才会用于比较。一个应该在10:59的触发器毕竟早于11:00的触发器。

注意:如果一个触发器的作业被检测到需要恢复,它的恢复调度与它原来的触发优先级相同

Misfire Instructions

触发器的另一个重要属性是它的“哑火指令”。多种情况会导致一个触发错过了它的触发,比如调度器被关闭,比如Quartz的线程池没有可用线程去执行作业等。不同类型的触发器有不同的“哑火指令”。它们默认使用“智能策略”的指令,它对于不同类型的触发器及配置有着不同行为。当调度器启动,它搜索所有出现哑火的持续的触发器,然后按照它们各自的哑火指令更新它们的状态。你开始用Quartz,就应该去熟悉各个触发器的呀或执行,它们在JavaDoc中有着详细的解释。在之后对于某些触发器类型的讲解中,将会详细介绍各自的该属性。

Calendars

Quartz的Calendar对象(不是java.util.Calendar对象)能够在触发器被定义的时候与之关联并存到调度器中。当需要排除某些触发时间的时候,它很有用。举个例子,你可以在周工作日(周一到周五)上午九点半执行某个作业,然后可以添加一个Calendar排除那些法定假日。

Calendar可以是任何实现了Calendar接口的可序列化对象。定义如下

1
2
3
4
5
package org.quartz;
public interface Calender {
    public boolean isTimeIncluded(long timeStamp);
    public long getNextIncludedTime(long timeStamp);
}

注意这些方法的参数都是long类型的。你可能觉得有些不好,因为时间戳都精确到毫秒了,这是因为Quartz想要尽可能精确的去掉某些时间。但有些时候你可能需要去掉全天的,那么你可以使用org.quartz.impl.HolidayCalendar类,它就是做这个的。

Calendar实例化后必须使用调度器的addCalendar()注册给调度器。如果你使用的是HolidayCalendar,实例化完成之后,你要使用addExcludedData(Date date)方法告知调度器你要排除的日子。同一个Calendar实例可以被多个触发器使用。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
HolidayCalendar cal = new HolidayCalendar();
cal.addExcludedDate( someDate );
cal.addExcludedDate( someOtherDate );

sched.addCalendar("myHolidays", cal, false);


Trigger t = newTrigger()
    .withIdentity("myTrigger")
    .forJob("myJob")
    .withSchedule(dailyAtHourAndMinute(9, 30)) // execute job daily at 9:30
    .modifiedByCalendar("myHolidays") // but not on holidays
    .build();

// .. schedule job with trigger

Trigger t2 = newTrigger()
    .withIdentity("myTrigger2")
    .forJob("myJob2")
    .withSchedule(dailyAtHourAndMinute(11, 30)) // execute job daily at 11:30
    .modifiedByCalendar("myHolidays") // but not on holidays
    .build();

// .. schedule job with trigger2

触发器的实例化/构建的细节将会在后面机型讨论。上面的代码只是创建两个触发器,它们都是每日触发的,但都会跳过那些已排除的日期。

如果有更多需要,请查看org.quartz.impl.calendar包,里面有Calendar的多种实现方式。