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點執行 |