(翻译)Quartz官方教程——第六课:CronTrigger

如果你需要类似于日历一样触发的任务,而不是精确时间间隔的简单触发,CronTrigger通常要比SimpleTrigger更有用。

通过CronTrigger,你可以指定诸如“每周五中午”或者“每个工作日上午9:30”,甚至是“在一月的每个周一、周三和周五的上午9:00带10:00每五分钟触发一次”这样的时间点。

而且和SimpleTrigger一样,CronTrigger也有一个startTime来指定生效时间,以及一个(可选的)endTime指定结束时间。

Cron表达式

Cron表达式被用来配置CronTrigger实例。Cron表达式是由七个子表达式构成的字符串,他描述了时间表的各个细节。这些子表达式用空格分隔,并表示:

  1. 分钟
  2. 小时
  3. 一月中某一天
  4. 月份
  5. 星期几
  6. 年 (可选字段)

 字符串“0 0 12 ? * WED” 是一个完整的cron表达式实例——它表示“每个周三的下午12:00:00”。

单独的子表达式可以包含范围和列表。比如,在前一个例子中的周几字段(WED字段)就可以了替换成 “MON-FRI”, “MON,WED,FRI”, 甚至“MON-WED,SAT”。

通配符('*'字符)可以用来表示该字段的“每个”可能的值。因此,上例中“月”字段中的字符就表示“每月”。因此,星期几字段中的'*'显然意味着“每周的每一天”。

所有字段都有一组可以指定的有效值。这些值都相当明显——比如0~59表示秒和分钟,0~23表示小时。月的日期可以为1~31的任何值,但是你需要注意所选月份总共有多少天!月份可以指定0~11的数值或者使用JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV 和 DEC这些字符串。周几可以使用1~7的数值(1表示周日)或者使用SUN, MON, TUE, WED, THU, FRI 和 SAT字符串。

'/'字符可用于指定增量值。比如,如果你在“分钟”字段中输入“0/15”,则表示“从第0分钟开始,每15分钟执行一次”。如果你在“分钟”字段使用“3/20”,它表示“从第3分钟开始,每20分钟执行一次”——或者换句话说,它与在分钟字段中指定'3,23,43'相同。请注意,“/ 35”并不意味着“每35分钟” - 而是意味着“从0分钟开始, 每35分钟执行一次” - 换句话说就是指定'0,35'。

'?'字符仅允许用于每月日期和星期几字段。它用于指定“无特定值”。当你需要在这两个字段中的某个指定值的时候,另一个字段就需要使用'? '请参阅下面的示例(和CronTrigger JavaDoc)以进行学习。

' L '字符可以用于月份和星期几字段。这个字符是“last”的简写,但是在两个字段中有着不同的意义。举个栗子,在月份日期中使用"L"字符表示“某一月的最后一天”——比如1月31日,非闰年的2月28日。如果在周几字段中仅使用一个"L",它就表示"7"或者"SAT"。如果在周几字段的其他值后边加上这个字符,那就表示“某月的最后一个周几”——比如"6L"或者"FRIL"都表示“某月的最后一个周五”。你还可以指定从该月的最后一天开始的偏移量,例如“L-3”,这意味着日历月的倒数第三天。当使用“L”选项时,最好不要指定列表或值的范围,因为你会得到令人困惑的结果。

扫描二维码关注公众号,回复: 1303723 查看本文章

'W'用于指定距离指定日最近的星期几(星期一至星期五)。例如,如果您要将“15W”指定为月份日期字段的值,则含义为:“距离本月15日最近的工作日”。

'#'用于指定该月的第n个“XXX”工作日。例如,星期几字段中的“6#3”或“FRI#3”的值表示“该月的第三个星期五”。

下面是一些表达式及其含义的例子 - 你可以在JavaDoc中找到关于org.quartz.CronExpression的更多信息。

Cron表达式例子

CronTrigger示例1——每五分钟触发一次的表达式

“0 0/5 * * * ?”

CronTrigger示例2——每五分钟触发一次,在每分钟的第十秒触发(即上午10:00:10,上午10:05:10等)

“10 0/5 * * * ?”

CronTrigger示例3——每周三和周五的10:30,11:30,12:30和13:30触发

“0 30 10-13 ? * WED,FRI”

CronTrigger示例4——每月5号和20号上午8:00~10:00每半小时触发一次。注意10:00不会触发,仅8:00, 8:30, 9:00 和 9:30有效

“0 0/30 8-9 5,20 * ?”

请注意,某些调度要求过于复杂,无法用单个触发器来表示——如“上午9点到上午10点之间每5分钟一班,下午1点到10点之间每20分钟一班”。这种情况下只需要创建两个触发器,并把它们关联到同一个任务上即可。

构建CronTriggers

CronTrigger实例使用TriggerBuilder(设置触发器的通用属性)和CronScheduleBuilder(设置CronTrigger的特有属性)来构建。要以DSL风格使用这些构建器,请使用静态导入:

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

构建一个每隔两分钟触发一次,时间为每天的8:00~17:00的触发器:

 trigger = newTrigger()
    .withIdentity("trigger3", "group1")
    .withSchedule(cronSchedule("0 0/2 8-17 * * ?"))
    .forJob("myJob", "group1")
    .build();

建立一个触发器,在每天上午10:42触发:

  trigger = newTrigger()
    .withIdentity("trigger3", "group1")
    .withSchedule(dailyAtHourAndMinute(10, 42))
    .forJob(myJobKey)
    .build();

或者

  trigger = newTrigger()
    .withIdentity("trigger3", "group1")
    .withSchedule(cronSchedule("0 42 10 * * ?"))
    .forJob(myJobKey)
    .build();

建立一个触发器,在星期三上午10:42触发,并使用非系统时区:

  trigger = newTrigger()
    .withIdentity("trigger3", "group1")
    .withSchedule(weeklyOnDayAndHourAndMinute(DateBuilder.WEDNESDAY, 10, 42))
    .forJob(myJobKey)
    .inTimeZone(TimeZone.getTimeZone("America/Los_Angeles"))
    .build();

或者

  trigger = newTrigger()
    .withIdentity("trigger3", "group1")
    .withSchedule(cronSchedule("0 42 10 ? * WED"))
    .inTimeZone(TimeZone.getTimeZone("America/Los_Angeles"))
    .forJob(myJobKey)
    .build();

CronTrigger Misfire 策略

当CronTrigger发生misfire的时候有以下策略可用。(关于更多misfire的介绍查看Triggers 部分的教程)。这些策略定义在CronTrigger本身的常量中(包括描述其行为的JavaDoc)。这些策略包括:

MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY
MISFIRE_INSTRUCTION_DO_NOTHING
MISFIRE_INSTRUCTION_FIRE_NOW

所有触发器都有Trigger.MISFIRE_INSTRUCTION_SMART_POLICY策略可供使用,并且此策略也是所有触发器类型的默认值。CronTrigger将'智能策略'指令解释为MISFIRE_INSTRUCTION_FIRE_NOW。CronTrigger.updateAfterMisfire()方法的JavaDoc解释了这种行为的确切细节。

在构建CronTriggers时,可以通过CronSchedulerBuilder指定策略作为调度的一部分:

  trigger = newTrigger()
    .withIdentity("trigger3", "group1")
    .withSchedule(cronSchedule("0 0/2 8-17 * * ?")
        ..withMisfireHandlingInstructionFireAndProceed())
    .forJob("myJob", "group1")
    .build();

猜你喜欢

转载自my.oschina.net/icebergxty/blog/1798375