如果你需要一个基于类似日历的概念而不是精确指定的SimpleTrigger时间间隔的工作调度计划,CronTriggers通常比SimpleTrigger更有用。
使用CronTrigger,您可以指定触发时间表,比如每周五的中午、每个工作日和上午9:30,甚至是每周一、三、五的上午9:00到10:00之间每五分钟执行一次。
即使如此,就像SimpleTrigger一样,CronTrigger有一个startTime,它指定了时间表的生效时间,还有一个(可选的)endTime,用于指定应该停止时间表的时间。
Cron Expressions
Cron-Expressions用于配置CronTrigger的实例。Cron-Expressions是由七个子表达式组成的字符串,它们描述了计划的各个细节。这些子表达式用空格分隔,并表示:
- Seconds
- Minutes
- Hours
- Day-of-Month
- Month
- Day-of-Week
- Year (optional field)
一个完整的cron表达式的例子是字符串“0 0 12 ? * WED” - 意思是“每个星期三中午12:00”。
单独的子表达式可以包含范围和/或列表。例如,前一天的星期几字段(以“WED”为例)可以用“MON-FRI”,“MON,WED,FRI”或甚至“MON-WED,SAT”代替。
通配符(’ ‘字符)可以用来表示该字段的“every”可能的值。因此,上例中“Month”字段中的“?”字符仅表示“every month”。Day-Of-Week字段中的’*'显然意味着“每周的每一天”。
所有字段都有一组可以指定的有效值。这些值应该相当明显 - 例如秒和分钟的数字是0到59,小时的值是0到23。Day-of-Month可以是0-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。
'/'字符可用于指定增量值。例如,如果您在“Minutes”字段中输入“0/15”,则表示“每15分钟一次,从零开始”。如果您在“Minutes”字段中使用了“3/20”,则意味着“每隔20分钟,从第三分钟开始” - 换句话说,它与在Minutes字段中指定“3,23,43”相同的效果。
‘?’ 字符允许用于day-of-month和day-of-week字段。它用于指定“无特定值”。当您需要在两个字段中的一个字段中指定某项内容,但在另一个字段中却没有时,此功能非常有用。请参阅下面的示例(和CronTrigger API文档)以进行说明。
“L”字符可以用于day-of-month和day-of-week字段。这个是“Last”的简写,但在两个领域中的每一个中都有不同的含义。例如,月份字段中的值“L”意味着“月份的最后一天” - 一月份的第31天,非闰年的二月份的第28天。如果单独使用在星期几字段中,则仅表示“7”或“SAT”。但如果在星期几字段中使用另一个值,则表示“该月的最后一个xxx日” - 例如“6L”或“FRIL”均表示“该月的最后一个星期五”。使用“L”选项时,不要指定列表或值的范围,因为您会得到令人困惑的结果。
'W’用于指定距离指定日最近的工作日(星期一至星期五)。例如,如果您要将“15W”指定为day-of-month字段的值,则含义为:“距离本月15日最近的工作日”。
'#'用于指定该月的第n个“XXX”工作日。例如,day-of-week字段中的“6#3”或“FRI#3”的值表示“该月的第三个星期五”。
Cron Expressions实例
以下是一些表达式及其含义的更多示例 - 您可以在CronTrigger的API文档中找到更多示例
CronTrigger示例1 - 一个表达式,用于创建每5分钟触发一次的触发器
"0 0/5 * * * ?"
CronTrigger示例2 - 一个表达式,用于创建在该分钟后10秒(即上午10:00:10,上午10:05:10等),每5分钟触发一次的触发器。
"10 0/5 * * * ?"
CronTrigger示例3 - 一个表达式,用于创建在每周三和周五的10:30,11:30,12:30和13:30时触发的触发器。
"0 30 10-13 ? * WED,FRI"
CronTrigger示例4 - 一个表达式,用于创建每个月的第5天和第20天上午8点至上午10点之间每隔半小时触发一次的触发器。请注意,触发器不会在上午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(用于触发器的主属性)和WithCronSchedule扩展方法(用于CronTrigger特定属性)构建。
您还可以使用CronScheduleBuilder的静态方法创建计划。
建立一个触发器,每天早上8点至下午5点,每隔一分钟就会触发一次:
trigger = TriggerBuilder.Create()
.WithIdentity("trigger3", "group1")
.WithCronSchedule("0 0/2 8-17 * * ?")
.ForJob("myJob", "group1")
.Build();
建立一个触发器,每天在上午10:42触发:
// we use CronScheduleBuilder's static helper methods here
trigger = TriggerBuilder.Create()
.WithIdentity("trigger3", "group1")
.WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(10, 42))
.ForJob(myJobKey)
.Build();
或者
trigger = TriggerBuilder.Create()
.WithIdentity("trigger3", "group1")
.WithCronSchedule("0 42 10 * * ?")
.ForJob("myJob", "group1")
.Build();
构建一个触发器,将在星期三上午10:42在除系统默认值之外的TimeZone中触发:
trigger = TriggerBuilder.Create()
.WithIdentity("trigger3", "group1")
.WithSchedule(CronScheduleBuilder
.WeeklyOnDayAndHourAndMinute(DayOfWeek.Wednesday, 10, 42)
.InTimeZone(TimeZoneInfo.FindSystemTimeZoneById("Central America Standard Time")))
.ForJob(myJobKey)
.Build();
或者 -
trigger = TriggerBuilder.Create()
.WithIdentity("trigger3", "group1")
.WithCronSchedule("0 42 10 ? * WED", x => x
.InTimeZone(TimeZoneInfo.FindSystemTimeZoneById("Central America Standard Time")))
.ForJob(myJobKey)
.Build();
CronTrigger Misfire Instructions
以下指令可用于通知Quartz在CronTrigger发生MisFire时应该执行的操作。(有关MisFire的更多介绍查看本教程的 Triggers章节)。这些指令被定义为常量(并且API文档对其行为进行了描述)。说明包括:
- MisfireInstruction.IgnoreMisfirePolicy
- MisfireInstruction.CronTrigger.DoNothing
- MisfireInstruction.CronTrigger.FireOnceNow
所有触发器都有MisfireInstrution.SmartPolicy指令可供使用,并且此指令也是所有触发器类型的默认值。
CronTrigger将“智能策略”指令解释为MisfireInstruction.CronTrigger.FireOnceNow。CronTrigger.UpdateAfterMisfire()方法的API文档解释了此行为的详细细节。
在构建CronTriggers时,可以将misfire指令指定为cron时间表的一部分(通过WithCronSchedule扩展方法):
trigger = TriggerBuilder.Create()
.WithIdentity("trigger3", "group1")
.WithCronSchedule("0 0/2 8-17 * * ?", x => x
.WithMisfireHandlingInstructionFireAndProceed())
.ForJob("myJob", "group1")
.Build();