Cron 表達式是一個字符串,由 6 或 7 個域組成,空格分隔:
秒 分 時 日 月 星期 [年]
| 域 | 範圍 | 允許字符 |
|---|---|---|
| 秒 | 0-59 | , - * / |
| 分 | 0-59 | , - * / |
| 時 | 0-23 | , - * / |
| 日 | 1-31 | , - * / ? L W C |
| 月 | 1-12 / JAN-DEC | , - * / |
| 星期 | 1-7 / SUN-SAT | , - * / ? L C # |
| 年(可選) | 1970-2099 | , - * / |
| 字符 | 名稱 | 含義 | 示例 |
|---|---|---|---|
| * | 通配符 | 匹配該域所有值 | * * * * * * 每秒執行 |
| ? | 無具體值 | 僅用於「日」和「星期」,避免衝突 | 每月 20 日觸發:0 0 12 20 * ? |
| - | 範圍 | 包含邊界 | 10-20 表示 10 到 20 |
| / | 增量/步長 | 起始值/每隔多少 | 5/15 表示 5、20、35、50 分 |
| , | 枚舉 | 列出多個值 | MON,WED,FRI 週一三五 |
| L | Last | 「日」=月最後一天,「星期」=最後一個星期六 | 5L = 最後一個星期四 |
| W | Workday | 最近工作日(僅「日」域) | 15W = 15 日若週末則順延 |
| LW | 組合 | 月最後一個工作日(即最後週五) | LW |
| # | 第 N 個 | 「星期」域:第幾個星期幾 | 4#2 = 第 2 個星期三 |
| C | Calendar | 關聯日曆(較少用) | - |
「日」和「星期」不能同時指定具體值,必須有一個用 ?。否則邏輯衝突導致不可預期行為。
| 需求 | Cron 表達式 | 說明 |
|---|---|---|
| 每天中午 12:00 | 0 0 12 * * ? | 標準每日定時 |
| 每天 10:15 | 0 15 10 * * ? | |
| 工作日 10:15 | 0 15 10 ? * MON-FRI | 週一到週五 |
| 每半小時 (9-17點) | 0 0/30 9-17 * * ? | 工作時間輪詢 |
| 每月 1 號 02:00 | 0 0 2 1 * ? | 月度結算 |
| 每月最後一天 10:15 | 0 15 10 L * ? | L 表示最後一天 |
| 每月最後一個週五 10:15 | 0 15 10 ? * 6L | 6=週五,L=最後一個 |
| 每月第 3 個週五 10:15 | 0 15 10 ? * 6#3 | #3 表示第 3 個 |
| 2002-2005 年每月最後週五 | 0 15 10 ? * 6L 2002-2005 | 年份範圍 |
| 每分鐘 (14:00-14:59) | 0 * 14 * * ? | 分鐘域 * |
| 每 5 分鐘 (14:00-14:55) | 0 0/5 14 * * ? | 步長 5 |
| 14:00-14:05 每分鐘 | 0 0-5 14 * * ? | 範圍 0-5 |
| 14:00 和 18:00 每 5 分鐘 | 0 0/5 14,18 * * ? | 多時段 |
| 每年 3 月週三 14:10/14:44 | 0 10,44 14 ? 3 WED | 月+星期組合 |
@Component
public class ScheduledTasks {
// 每天凌晨 2 點執行
@Scheduled(cron = "0 0 2 * * ?")
public void dailyCleanup() { ... }
// 工作日每半小時
@Scheduled(cron = "0 0/30 9-17 ? * MON-FRI")
public void businessHourCheck() { ... }
}
掌握 Cron 表達式,讓定時任務配置從「猜謎遊戲」變為「精確可控」。