相較 SimpleTrigger 的固定間隔,CronTrigger 基於日曆邏輯,支持複雜時間調度:
擁有 startTime(生效時間)與可選 endTime(終止時間)邊界控制。
標準 Quartz Cron 表達式由 **7 個子表達式** 組成,以空格分隔:
[秒] [分] [時] [日] [月] [周] [年(可選)]
| 位置 | 字段 | 允許值 | 特殊字符 |
|---|---|---|---|
| 1 | Seconds | 0-59 | , - * / |
| 2 | Minutes | 0-59 | , - * / |
| 3 | Hours | 0-23 | , - * / |
| 4 | Day of Month | 1-31 | , - * / ? L W |
| 5 | Month | 1-12 / JAN-DEC | , - * / |
| 6 | Day of Week | 1-7 / SUN-SAT | , - * / ? L # |
| 7 | Year (可選) | 1970-2099 | , - * / |
*:所有值(每秒、每分...)?:**僅用於 Day of Month / Day of Week**,表示「不指定值」,二者必須有一個用 ?(避免衝突)。-:範圍,如 MON-FRI 表示周一至周五。,:枚舉,如 MON,WED,FRI。/:增量/步長,如 0/15 在分鐘域表示每小時 0、15、30、45 分;5/15 表示 5、20、35、50 分。L:Last,Day of Month 表示月最後一天(31/30/28/29),Day of Week 表示周六(7/SAT),6L 表示本月最後一個周五。W:工作日(最近的工作日),15W 表示離 15 號最近的工作日(若 15 是周六則取 14,周日取 16)。#:第 N 個星期幾,6#3 表示本月第三個周五(6=FRI, 3=第三個)。| 需求 | Cron 表達式 | 說明 |
|---|---|---|
| 每 5 分鐘執行一次 | 0 0/5 * * * ? | 秒=0,分=0/5 |
| 每天凌晨 2:30 | 0 30 2 * * ? | |
| 工作日上午 9:00 | 0 0 9 ? * MON-FRI | 周域用範圍,日域用 ? |
| 每月最後一天 23:59 | 0 59 23 L * ? | 日域用 L |
| 每月第三個周五 10:00 | 0 0 10 ? * 6#3 | 6=FRI, #3=第三個 |
| 2024 年每天 12:00 | 0 0 12 * * ? 2024 | 包含年域 |
| 每季度最後一天 00:00 | 0 0 0 L 3,6,9,12 ? | 月域枚舉季度末月,日域 L |
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
public class CronJobDemo {
public static void main(String[] args) throws SchedulerException {
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
JobDetail job = JobBuilder.newJob(MyJob.class)
.withIdentity("cronJob", "group1").build();
// 每天凌晨 3:15 執行
CronTrigger trigger = TriggerBuilder.newTrigger()
.withIdentity("cronTrigger", "group1")
.withSchedule(CronScheduleBuilder.cronSchedule("0 15 3 * * ?"))
.build();
scheduler.scheduleJob(job, trigger);
scheduler.start();
}
}
class MyJob implements Job {
@Override public void execute(JobExecutionContext context) {
System.out.println("定時任務執行時間: " + new Date());
}
}
@Scheduled(cron="...") 為 6 域(無秒),**切勿混用**。Day of Month 與 Day of Week 不能同時具體指定,必須有一個用 ?。TimeZone 或統一 UTC。L、W、# **不可組合** 使用(如 15LW 無效)。