corn 表达式是一个字符串,分为 6 或 7 个域,每一个域都会表明一个含义。java
语法格式
6 个域:second minute hour day month week
7 个域:second minute hour day month week year
由上可见,7 个域与 6 个域的语法只差了 year,通常状况下,咱们使用 6 个域的结构。spring
corn 从左到右(中间用空格隔开):秒 分 小时 月份中的日 月份 星期中的日期 年份express
各个字段的含义springboot
位置 | 时间域名 | 容许值 | 容许的特殊字符 |
---|---|---|---|
1 | 秒 | 0-59 | , - * / |
2 | 分 | 0-59 | , - * / |
3 | 小时 | 0-23 | , - * / |
4 | 日 | 1-31 | , - * ? / L W C |
5 | 月 | 0-12 | , - * / |
6 | 星期 | 1-7 | , - * ? / L C # |
7 | 年(可选) | 1970-2099 | , - * / |
声明:本次的 cron 讲解结合了 springboot 框架。因为只是讲解 cron 表达式,因此就不在介绍 springboot 中如何使用 @Scheduled 注解的相关配置了
秒的位置容许值为 0-59,若是写 60,将会报错框架
/* 如下代码在 springboot 启动时会抛出异常 */ @Scheduled(cron="60 * * * * * ?") public void executeSchedule() { //TODO }
异常信息:Range exceeds maximum (60) |'60' in expression "60 ?"
意思就是说,表达式中的 60 已经超出了最大范围。code
秒字符串
/* 每分钟的第8秒执行 */ @Scheduled(cron="8 * * * * ?") public void executeSchedule() { //TODO }
以上表达式含义为:每分钟的第 8 秒执行 executeSchedule方法。秒后面的时间域是分钟,*(星号)表示每...
,这里表示每分钟
。注意:是每分钟的第 8 秒,不是每隔 8 秒
域名
秒 + 分io
/* 每小时的20分8秒时执行 */ @Scheduled(cron="8 20 * * * ?") public void executeSchedule() { //TODO }
以上表达式含义为:每小时的第 20 分,第 8 秒执行 executeSchedule 方法。分钟后的时间域是小时,因为是 *(星号),因此表明每小时。table
秒 + 分 + 小时
/* 天天中午12点20分8秒执行 */ @Scheduled(cron="8 20 12 * * ?") public void executeSchedule() { //TODO }
以上表达式含义为:天天中午 12 点 20 分 8 秒执行 executeSchedule 方法。小时后的时间域是天,*(星号)表示天天。注意:时间的范围是 0-23,即 24 时制。因此 12 表示中午 12 点,若是表示午夜 12 点,表达式应该为:cron=8 20 0 * * ?
秒 + 分 + 小时 + 日
/* 每个月31号中午12点20分8秒执行 */ @Scheduled(cron="8 20 12 31 * ?") public void executeSchedule() { //TODO }
以上表达式含义为:每月的 31 号中午 12 点 20 分 8 秒执行 executeSchedule 方法。注意:
一、若是某个月份中不包含 31 号,则不执行
二、若是表达式为 cron="8 20 12 31 4 ?",启动项目时将会报错: 4 月份没有 31 号,此表达式永远都不会执行,因此月份与日要配合使用
秒 + 分 + 小时 + 日 + 月
/* 4月30号中午12点20分8秒执行 */ @Scheduled(cron="8 20 12 30 4 ?") public void executeSchedule() { //TODO }
以上表达式含义为:4 月 30 号中午 12 点 20 分 8 秒执行 executeSchedule 方法。
秒 + 分 + 小时 + 日 + 月 + 星期
星期域具备特殊性,它由 1-7 组成,1 表示星期日(一周的开始),7 表示星期六(一周的最后一天);星期的定义与日和月同时表示,有可能会有冲突。
例子:cron="8 20 12 30 4 3"
以上表达式,看着好像是 星期二 4 月 30 号 中午 12 点 20 分 8 秒
这个意思,但实际上并不必定,缘由很简单,你怎么就知道 4 月 30 号正好是星期二呢?因此这样定义表达式是存在问题的,也就是说星期
和日
在某种程度上是有冲突
的。因此通常要在星期
和日
之间做出取舍
。即定义了星期,就不定义日;定义了日,就不定义星期。不须要定义的时候使用
?占位,舍弃谁谁就用
?代替
。
例子:cron="8 20 12 ? 4 2"
以上表达式含义为:4 月份的每一个星期 1 的中午 12 点 20 分 8 秒
表达式 | 含义 |
---|---|
cron="8 20 12 * 4 ?" | 4月份天天中午12点20分8秒 |
cron="8 * 18 * 4 ?" | 4月份天天下午6点的每分钟的第8秒 |
星期域
和日期域
中使用,它一般指定为无心义的值
,至关于占位符小时域
,16-20
表示从下午4点到晚上8点
,即 16,17,18,19,20表达式 | 含义 |
---|---|
cron="8 20 7-9 * 2 ?" | 2月份天天7点,8点,9点的20分8秒 |
星期域
,“1,3,5”,表示星期日,星期二,星期四表达式 | 含义 |
---|---|
cron="2,59 20 3 * 2 ?" | 2月份天天凌晨3点20分的第2秒和第59秒 |
分钟域
中使用0/25
,表示0,25,50秒。也可使用*/y
,同等于0/y
表达式 | 含义 |
---|---|
cron="2,59 0/25 3 * 2 ?" | 2月份天天凌晨3点的第2秒和第59秒,3点25(0+25)分的第2秒和第59秒,3点50(25+25)分的第2秒和第59秒 |
cron="* 15/20 14 * 2 ?" | 2月份天天下午2点15分的每一秒,3点35(15+20)分每一秒,3点55(35+20)分的每一秒 |
日期域
和星期域
中使用,表明Last
的意思,但它在两个域中的意义不一样。域 | 含义 |
---|---|
日期 | 当前月份的最后一天,如1月31日,非闰年2月28日 |
星期 | 表示星期六,同等于7。但若是出如今星期域中,并且在前面还有一个数值X,则表示“这个月的最后X天”,例如:5L表示该月的最后星期四 |
日期域
中,是对前导日期的修饰,表示离该日期最近的工做日。例如12W
表示离该月12号
最近的工做日
,若是该月的12号
是星期六
,则匹配11号星期五
;若是12号
是星期日
,则匹配13号星期一
;若是12号
是星期三
,那结果就是星期三
。但必须注意关联的匹配日期不可以跨月
,如指定1W
,若是1号
是星期六
,那么结果就是3号星期一
,而非上个月的最后的那天。W
只能指定单一日期,而不能指定日期范围。LW
,含义是当月的最后一个工做日
星期域
中使用,表示当月某个工做日
。表达式 | 含义 |
---|---|
6#3 | 当月的第三个星期五(6表示星期五,#3表示当前的第三个) |
4#5 | 当月的第五个星期三。假设当月没有第五个星期三,则忽略不触发 |
日期域
和星期域
中使用,表明Calendar
的意思。意义为计划所关联的日期
。若是日期没有被关联,则至关于日历中的全部日期。如。5C
在日期域
中就至关于日历5日之后的第一天
,1C
在星期域
中至关于星期往后的第一天
。cron表达式对特殊字符的大小写不敏感,对表明星期的缩写英文大小写也不敏感。
表达式 | 含义 |
---|---|
@Scheduled(cron="0 0 1 1 1 ?") | 每一年1月1号的凌晨1点整 |
@Scheduled(cron="0 0 1 1 1,6 ?") | 1月和6月的1号的凌晨1点整 |
@Scheduled(cron="0 0 1 1 1,4,7,10 ?") | 每一个季度的第1个月的1号的凌晨1点 |
@Scheduled(cron="0 0 1 1 * ?") | 每个月1号凌晨1点执行 |
@Scheduled(cron="0 0 1 *") | 天天凌晨1点执行 |