介绍
cron表达式是一个已经存在了很长时间的UNIX工具,因此它的调度功能非常强大且已经经过验证。CronTrigger类的功能是基于cron的调度功能实现的。
CronTrigger
使用"cron表达式",可以创建诸如“每周一至周五上午8:00”或“每月最后一个星期五上午1:30”的触发调度时间表(调度计划)。
cron表达式很强大,但是它使用起来也有可能相当混乱(这里大概的意思是说cron的用法相对复杂,容易出错)。本教程旨在解决创建cron表达式的一些谜题,为用户提供一个资源,让他们可以在论坛或邮件列表中提问之前访问这个教程(减少在论坛或者邮件中的提问)。
格式
cron表达式是由空格分隔的6或7个字段组成的字符串。字段可以包含任何允许的值,以及该字段允许的特殊字符的各种组合。这些字段如下所示:
字段名称 | 是否必须 | 允许的值 | 允许的特殊字符 |
---|---|---|---|
秒种(Seconds) | 是 | 0-59 | , - * / |
分钟(Minutes) | 是 | 0-59 | , - * / |
小时(Hours) | 是 | 0-23 | , - * / |
日(Day of month) | 是 | 1-31 | , - * ? / L W |
月(Month) | 是 | 1-12 or JAN-DEC | , - * / |
星期(Day of week) | 是 | 1-7 or SUN-SAT | , - * ? / L # |
年(Year) | 否 | empty(也就是不填任何值), 1970-2099 | , - * / |
译者注:这里可以看出一个cron表达式中年(Year)字段是非必须的,如果不填写此字段可以认为它其实就是*
值。
所以cron表达式可以像这样简单:* * * * ? *
,或更复杂,如这个例子所示:0/5 14,18,39,52 * ? JAN,MAR,SEP MON-FRI 2002-2010
。
特殊字符
- *:代表所有值 - 用于选择一个字段中的所有值。例如,分钟字段(Minutes)中的"*"表示 “每分钟”。
- ?:代表没有具体的值 - 当你需要定义两个字段中的其中一个,另一个不需要定义id时候就十分有用(其实主要就是用在Day of month和Day of week的互斥关系中)。例如,例如我想我的触发器每月的某一日(例如第十日)触发,但是我不需要关注当天是星期几,因此我只需要把’10’设置在Day of month字段,把’?'设置在Day of week字段即可。可以参阅下面的例子来进一步了解。
- -:用于指定范围值。例如Hours字段中的"10-12"表示"10,11和12"小时(就是一个范围值)。
- ,:用于指定附加值。例如Day of week字段中的"MON,WED,FRI"表示 “星期一,星期三和星期五”。
- /:用于指定增量(格式是:“初始值/增量”)。例如在Seconds字段中"0/15"表示秒数范围取值"0,15,30和45",Seconds字段中"5/15"表示秒数范围取值"5,20,35和50"。上一个例子说明了,你可以在"/"前取非零值(其实也就是初始值不为0),例如Day of month字段中"1/3"表示从月份的第一天起每三天(触发一次)。
- L:英文单词"last"的缩写,含义和last一致。
- W:英文单词"weekday"的缩写,即工作日(星期一到星期五)。
注意:
代码语言:javascript复制'L'和'W'字符可以Day of month字段合并使用,也就是在Day of month字段中使用'LW',转换为“月份的最后一个工作日”。
例如:"0 0 12 1LW * ?"表示每个月的最后一个工作日中午12点触发。
- #:用于指定月份的"第n个"星期XXX*(格式:n#p,表示月份的第p个星期n,n由1开始,1表示星期日)。例如,Day of week字段的中"6#3"表示该月的第三个星期五(6表示星期五,#3表示第三个星期)。例如:“2#1"表示月份的第一个星期一,“4#5"表示月份的第五个星期三。注意最后这个例子,如果你指定了”#5”,并且月份的星期数不超过5个,那么该月份不会触发任何调度。
注意:
代码语言:javascript复制月份和星期缩写对应的合法字符不区分大小写。例如:MON与mon相同。
例子
这里有一些完整的例子:
表达式 | 含义 |
---|---|
0 0 12 * * ? | 每天中午12点(中午)触发 |
0 15 10 ? * * | 每天上午10点15分触发 |
0 15 10 * * ? | 每天上午10点15分触发 |
0 15 10 * * ? * | 每天上午10点15分触发 |
0 15 10 * * ? 2005 | 2005年每天上午10点15分触发 |
0 * 14 * * ? | 每天下午2点开始,每天下午2点59分结束 |
0 0/5 14 * * ? | 每天下午2点开始,每天下午2点55分结束,每5分钟触发一次 |
0 0/5 14,18 * * ? | 从下午2点开始,每天5分钟触发,结束于下午2点55分,每天5点钟触发,每天晚上6点开始,结束于下午6点55分 |
0 0-5 14 * * ? | 每天下午2点开始,结束于下午2点05分,每分钟触发 |
0 10,44 14 ? 3 WED | 在3月份的每个星期三下午2点10分和下午2点44分触发 |
0 15 10 ? * MON-FRI | 每周一,周二,周三,周四和周五上午10点15分触发 |
0 15 10 15 * ? | 在每个月的第15天上午10点15分触发 |
0 15 10 L * ? | 在每个月的最后一天上午10点15分触发 |
0 15 10 L-2 * ? | 在每个月的倒数第二天的上午10点15分触发 |
0 15 10 ? * 6L | 每个月的最后一个星期五上午10点15分触发 |
0 15 10 ? * 6L 2002-2005 | 2002年,2003年,2004年和2005年每个月的最后一个星期五上午10点15分触发 |
0 15 10 ? * 6#3 | 每个月的第三个星期五上午10点15分触发 |
0 0 12 1/5 * ? | 从每月的第一天开始,每个月每隔5天下午12点(中午)触发 |
0 11 11 11 11 ? | 每11月11日上午11点11分触发 |
注意:
代码语言:javascript复制请注意'?'和'*'在日(Day of month)和星期(Day of week)中的作用。
注意事项
- 目前不完全支持同时定义Day of week和Day of month两个字段(你必须在这两个字段其中之一使用’?’。其实这样做的目的是这两个字段是互斥的)。
- 你需要注意如果触发时间设置在凌晨的几个小时,你的语言环境(locale)有可能会因为“夏令时”(对于美国地区,这通常是凌晨2点之前和之后的一个小时)而发生变化 - 此时,时间迁移有可能会发生跳跃或者重复(这里是指同一个时刻重复两次,因为时间发生了回拨),这取决于时间是向后移动还是向前移动。你可以从维基百科上查找资料确定你所在地区的具体情况,链接是:https://secure.wikimedia.org/wikipedia/en/wiki/Daylight_saving_time_around_the_world