說起 cron 表達式大家一定不陌生,我們常用來作為定時任務執行策略規則。 在 Spring Boot 框架中 cron 表達式主要配合 @Scheduled 註解在應用程序中使用。 在 Spring Boot 2.4 (既 Spring 5.3)以後,引入了 CronExpression
表達式處理器來替代原有的 CronSequenceGenerator。
為什麼要替代原有的 CronSequenceGenerator ? 此處理器是基於 java.util.Calendar
侷限性比較大,無法完成last day of month
語義。
- 例如利用CronExpression 計算表達式下次執行時間
LocalDateTime now = LocalDateTime.now();
System.out.println("當前運行時間: " + now);
// 每小時執行一次
CronExpression expression1 = CronExpression.parse("0 0 0/1 * * *");
LocalDateTime nextTime = expression1.next(now);
System.out.println("每小時執行一次 -> 下次執行時間: " + nextTime);
// 每小時第十分執行一次
CronExpression expression2 = CronExpression.parse("0 10 0/1 * * *");
LocalDateTime nextTime2 = expression2.next(now);
System.out.println("每小時第十分執行 -> 下次執行時間: " + nextTime2);
- 執行結果
當前運行時間: 2020-11-14T23:04:46.302739
每小時執行一次 -> 下次執行時間: 2020-11-15T00:00
每小時第十分執行 -> 下次執行時間: 2020-11-14T23:10
新增常用表達式通用宏
對於非開發人員來說 cron 表達式並不容易理解,所以很難在出現錯誤的時候進行修復。比如筆者會把 cron 表達式 在在線網站 模擬運行一下,確認執行過程方便排查問題。
為了提高可讀性,Spring Boot 現在支持以下代表常用表達式的宏。可以使用這些宏而不是六位的表達式,因此:
@Scheduled(cron = "@hourly")。
相當於
@Scheduled(cron = "0 0 * * * *")
其他常用宏命令
宏 | cron 表達式 | 含義 |
---|---|---|
@yearly | 0 0 0 1 1 * | 每年執行一次 |
@monthly | 0 0 0 1 * * | 每月執行一次 |
@weekly | 0 0 0 * * 0 | 每週執行一次 |
@daily 或@annually | 0 0 0 * * * | 每天執行一次 |
@hourly | 0 0 * * * * | 每小時執行一次 |
增強原有表達式 最後幾天
每週的第幾天
|
∨
* * * * * *
^
|
每月的第幾天
如上其中的 每月的第幾天
、每週的第幾天
支持 最後幾天 (L) 的語義
例如:
0 0 0 L * * 每月最後一天的零時
0 0 0 L-3 * * 每月最後第三天的零時 (L-d 格式)
0 0 0 * * 5L 每月最後的星期五零時 (dL 格式)
0 0 0 * * FRIL 每月最後的星期五零時 ( (星期一星期天的英文縮寫)L 格式)
增強原有表達式 工作日
* * * * * *
^
|
每月的第幾天
如上其中的 每月的第幾天
支持 工作日 (W)的語義
例如:
0 0 0 1W * * 每月的第一個工作日零時
0 0 0 LW * * 每月的最後一個工作日零時
增強原有表達式 幾周的星期幾
每週的第幾天
|
∨
* * * * * *
如上其中的 每週的第幾天
支持 每月第幾周的第幾天語義
例如
0 0 0 ? * 5#2 每月第二週的星期五零時
0 0 0 ? * MON#1 每月週一的星期一零時