Quartz Tutorial 5 - Cron Trigger
当你要求作业的调度方式是“日历式”而不是“给定时间间隔式”的时候,CronTrigger
比SimpleTrigger
好用多了。
用CronTrigger
的话,很容易就能声明类似“每周五下午”或者“每周工作日上午9:30”,甚至“一月份的每个周一周三周五的上午九点到十点之间,每五分钟”这种奇奇怪怪的触发时间。
此外,CronTrigger
也有个startTime
属性用于声明何时强制调度,也有一个(可选的)endTime
属性用于声明何时结束调度。
Cron Expressions
Cron表达式是用于配置CronTrigger
实例的。Cron表达式是由六个子表达式组成的字符串,它们互相独立地描述调度的各个细节。这些子表达式是由空格分割,它们表示:
- 秒(Seconds)
- 分钟(Minutes)
- 小时(Hours)
- 月份中的天(Day-of-Month)
- 月份(Month)
- 一周中的天(Day-of-Week)
- 年(可选)(Year)
举个例子,假定有字符串"0 0 12 ? * WED"
,它表示“每周三的中午12点”
这些互相独立的子表达式可以包含范围和/或列表。举个例子,上面例子中的“一周中的天”字段可以替换成MON-FRI
,MON
,WED
,FRI
甚至可以是MON-WED
,SAT
Cron表达式支持使用通配符。上例中,“月份中的天”表达式处的?表示每个“可能”的值,换言之,这个值是不确定的(但不是全部)。而对于*
,就表示了所有值都是。
每个子表达式都有其自己的定义域。这也很显而易见了-对于秒和分钟,肯定是0到59;对于小时也必然是0到23;对于月份中的天,定义域是1到31,但是你自己应当注意这个月实际的天数;月份可以是数字0到11,也可以是字符串“JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC
”;一周中的天可以是数字1到7(1=Sunday),也可以是字符串“SUN MON TUE WED THU FRI SAT
”
/
用于声明值的增量。例如,分钟子表达式是0/15
,它的意思是“在小时内,0分钟之后的每个第15分钟触发一次”;如果是3/20
,意味着“小时内,3分钟之后的每个第20分钟触发一次”,换一个写法,分钟处的表达式就是3 23 43
。要注意到一个细微的区别:/35
不是说“每个35分”,而是说“从0分钟开始后的每个第35分钟”,换个写法就是0 35
。
?
可以用在月份中的天和一周中的天子表达式中。这个符号表示“非确定的值”。当你需要明确声明其中一个值,但是另一个无法明确指定的时候,这很有用。比如你想在每个星期四触发作业的执行,但是周四具体是几号其实是不确定的,那么此时在月份中的天子表达式处就可以写这个通配符了。
L
可以用在月份中的天和一周中的天子表达式处。这是”last”的简写,但它在两个子表达式中具有不同的意义。例如,在月份中的天子表达式处填写L
,意味着“月份中的最后一天”,例如一月份的31号,平年2月的28号等等;如果单独的L
放在一周中的天子表达式处,意味着7
或者SAT
(周六);但是在一周中的天子表达式中,如果L
放在了其他值的后面,例如6L
或FRIL
,那就意味着“该月的最后一个周五”。你也可以声明相对于每月最后一天的偏移,例如L-3
意味着该月的倒数第三天。当你使用L
时,不要再声明列表式、范围式的值了,不然你将得到奇怪的结果
W
用于声明距离给定日子最近的工作日(周一至周五)。例如你在月份中的天子表达式中声明了15W
,那意味着该月“距离15号最近的工作日”
#
用于声明“月份中第X个周X”。例如在一周中的天子表达式处给出6#3
或者FRI#3
,意思是“该月第三个周五”
下面是一些Cron表达式及其含义的具体举例,当然你可以在org.quartz.CronExpression
的JavaDoc中找到更多。
Example Cron Expressions
-
每五分钟触发一次
1
0 0/5 * * * ?
-
每五分钟的第十秒触发,例如“10:00:10, 10:05:10”
1
10 0/5 * * * ?
-
每周三、周五的10:30, 11:30, 12:30, 13:30触发
|
|
-
每月5号和20号的上午8点到10之间,每半小时触发一次。要注意10点并不会触发,只是八点、八点半、九点、九点半
1
0 0/30 8-9 5,20 * ?
有时有些调度的要求特别复杂,如果放在一个表达式中表示会过于复杂,例如“上午九点到十点之间每五分钟,下午一点到十点之间每二十分钟”。这种情况的话,可以创建两个触发器,然后将他俩都关联到同一个作业就好。
Building CronTriggers
CronTrigger
的实例构造是通过TriggerBuilder
类(设置触发器的主要共有属性)和CronScheduleBuilder
类(设置CronTrigger
类型触发器特有的属性)。首先静态导入如下内容,就能用DSL风格构造触发器实例了。
|
|
-
每天上午的八点到下午五点,每两分钟触发一次
1 2 3 4 5
trigger = newTrigger() .withIdentity("trigger3", "group1") .withSchedule(cronSchedule("0 0/2 8-17 * * ?")) .forJob("myJob", "group1") .build();
-
每天上午10点42分触发
1 2 3 4 5 6 7 8 9 10 11
trigger = newTrigger() .withIdentity("trigger3", "group1") .withSchedule(dailyAtHouAndMinute(10, 42)) .forJob(myJobKey) .build() // or trigger = newTrigger() .withIdentity("trigger3", "group1") .withSchedule(cronSchedule("0 42 10 * * ?")) .forJob(myJobKey) .build();
-
在周三上午10点42触发,此外,时区与系统默认时区不同
1 2 3 4 5 6 7 8 9 10 11 12 13
trigger = newTrigger() .withIdentity("trigger3", "group1") .withSchedule(weeklyOnDayAdnHourAdnMinute(DateBuilder.WEDNESDAY, 10, 42)) .forJob(myJobKey) .inTimeZone(TimeZone.getTimeZone("America/Los_Angeles")) .build(); // or trigger = newTrigger() .withIdentity("trigger3", "group1") .withSchedule(cronSchedule("0 42 10 * * WED")) .inTimeZone(TimeZone.getTimeZone("America/Los_Angeles")) .forJob(myJobKey) .build();
CronTrigger Misfire Instruction
当发生了misfire(“哑火”?),CronTrigger
提供了一些指令用于告知Quartz该如何处理。这些指令是作为CronTrigger
自身的常量来定义的(JavaDoc介绍了它们的行为),这些常量包括:
|
|
所有类型的触发器都有Trigger.MISFIRE_INSTRUCTION_SMART_POLICY
指令可用,这也是所有触发器默认的选择。在CronTrigger
中,该“smart policy”会使用MISFIRE_INSTRUCTION_FIRE_NOW
。CronTrigger.updateAfterMisfire()
的JavaDoc介绍了具体的行为细节。
当构造CronTrigger
的实例时,你也可以声明该属性(通过CronScheduleBuilder
)
|
|