Quartz.NET - 教程 6: Cron 触发器

译者注:
目录在这 Quartz.NET 3.x 教程
原文在这 Lesson 6: CronTrigger

如果你需要一个类似日历概念而不是像 SimpleTrigger 那样指定间隔来调度作业触发, 那么 CronTrigger 通常比 SimpleTrigger 更有用.

使用 CronTrigger, 你可以指定调度触发时间, 比如 "每周五的中午", "每周日的上午9:30", 甚至是 "每周一, 周三, 周五的上午9:00到10:00之间每5分钟执行一次".

既然如此, 像 SimpleTrigger 一样, CronTrigger 也有一个开始时间来指定调度何时生效, 还有一个 (可选) 结束时间来指定调度应该何时终止.

Cron 表达式

Cron 表达式用于配置 CronTrigger 的实例. Cron 表达式实际上是由七个子表达式组成的字符串, 她们描述了调度的各个细节. 这些子表达式用空格分隔,从左往右依次表示:

  1. 分钟
  2. 星期几
  3. 年 (可选字段)

一个完整的 cron 表达式的例子是字符串 "0 0 12 ? * WED" - 意思是 "每周三下午12:00".

单个子表达式可以包含范围和/或列表. 例如, 上一个示例中的周数字段(读作 "WED")可以替换为 "MON-FRI", "MON,WED,FRI", 甚至可以替换为 "MON-WED,SAT".

通配符 ('' 星号字符)可用于表示此字段的 "每个" 可能的值. 因此, 上例中 "月份" 字段中的 "" 字符仅表示 "每月". "星期几" 字段中的 "*" 显然意味着 "一星期中的每一天".

所有字段都有一组可以指定的有效值. 这些值应该相当明显 - 例如数字0到59代表秒和分钟, 值0到23代表小时. 一个月中的某一天可以是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.

字符 '/' 可用来指定值的增量. 例如, 如果在分钟字段中输入 "0/15", 则表示 "每15分钟, 从0分钟开始". 如果你在 "分钟" 字段中使用 "3/20", 则表示 "一小时内每20分钟, 从第3分钟开始", - 亦或在分钟字段中指定 "3,23,43" 效果一样.

问号字符 '?' 可用于 "日期" 和 "星期几" 字段. 她用于表示 "无特定值". 当你需要在两个字段中的一个字段中指定某些内容, 而不在另一个字段中指定时, 这非常有用. 请参阅下面的示例 (和 CronTrigger API文档) 来获得说明.

字符 'L' 可用于 "日期" 和 "星期几" 字段. 这个字符是 "last" 的简写, 但在两个字段中的有不同的含义. 举个栗子, "日期" 字段中的值 "L" 表示 "月份的最后一天" - 1月31日, 非闰年的2月28日. 如果在 "星期几" 字段中单独使用, 她只表示 "7" 或 "SAT". 但如果在星期几字段中用在另一个值之后, 则表示 "月的最后一个 xxx 天", 例如 "6L" 或 "FRIL" 都表示 "月份的最后一个星期五". 当使用 "L" 选项时, 千万不要指定列表或值的范围, 因为这样会得到让你百撕不得骑姐的结果.

字母 'W' 用来指定离给定日期最近的工作日 (星期一 - 星期五). 举个栗子, 如果你指定 "15W" 作为 "日期" 字段的值, 则其含义是: "最接近月15日的工作日".

井号 '#' 用于指定每月的 "第n个" XXX工作日. 例如, 星期几字段中的值 "6#3" 或 "FRI#3" 表示 "每月的第三个星期五".

Cron 表达式的一些栗子

下面是一些表达式及其含义的更多示例 - 你可以在 CronTrigger 的API文档中找到更多

CronTrigger 举个栗子 1 - 一个用来创建触发器的表达式, 简单的每5分钟触发一次.

"0 0/5 * * * ?"

CronTrigger 举个栗子 2 - 一个用来创建触发器的表达式, 每5分钟10秒触发一次 (如上午 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点到10点之间每半小时触发一次. 注意, 触发器不会在上午 10:00 触发, 只在 8:00, 8:30, 9:00 和 9:30 触发.

"0 0/30 8-9 5,20 * ?"

注意有些调度要求太过复杂是没法用单个触发器来表示的 - 例如 "上午 9:00 到 10:00 之间每5分钟一次, 并且在下午 1:00 到下午 10:00 每20分钟一次". 这种需求场景的解决办法是简单的创建2个触发器, 并注册她们来运行同一个作业.

构建 CronTriggers

CronTrigger 实例是使用 TriggerBuilder (用于触发器的主属性) 和 WithCronSchedule 扩展方法 (用于 CronTrigger 的特定属性) 来构建的.

你还可以使用 CronScheduleBuilder 的静态方法来构建调度.

构建一个触发器其在每天上午8点到下午8点的每一分钟会触发一次:

trigger = TriggerBuilder.Create()
    .WithIdentity("trigger3", "group1")
    .WithCronSchedule("0 0/2 8-17 * * ?")
    .ForJob("myJob", "group1")
    .Build();

构建一个触发器其会在每天上午 10:42 触发一次:

// 这里我们使用 CronScheduleBuilder 的静态助手方法
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 触发:

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 哑火指令

以下指令可用于通知 Quartz 在 CronTrigger 发生哑火时应采取的措施. (本教程的 "更多关于触发器" 部分介绍了哑火指令). 这些指令被定义为常量 (API文档对其行为有描述). 指令包括:

  • MisfireInstruction.IgnoreMisfirePolicy
  • MisfireInstruction.CronTrigger.DoNothing
  • MisfireInstruction.CronTrigger.FireOnceNow

所有触发器都可以使用 Misfireinstruction.SmartPolicy 指令, 并且此指令也是所有触发器类型的默认指令. CronTrigger 将 MisfireInstruction.CronTrigger.FireOnceNow 作为 '智能策略' 指令. CronTrigger.UpdateAfterMisfire() 方法的API文档解释了此行为的确切细节.

当构建 ConTrigger 时, 你可以指定哑火指令作为 cron 调度的一部分 (通过 WithCronSchedule 扩展方法):

trigger = TriggerBuilder.Create()
    .WithIdentity("trigger3", "group1")
    .WithCronSchedule("0 0/2 8-17 * * ?", x => x
        .WithMisfireHandlingInstructionFireAndProceed())
    .ForJob("myJob", "group1")
    .Build();
posted @ 2020-02-26 16:04  taadis  阅读(235)  评论(0编辑  收藏