| 維度 | JDK Timer | Spring @Scheduled | Quartz |
|---|---|---|---|
| 依賴 | 零 (JDK 內建) | Spring Context | 獨立庫 / Spring 整合 |
| 叢集/高可用 | ❌ 無 | ❌ 單節點 (需配合 ShedLock) | ✅ 內建 JDBC JobStore 叢集 |
| 持久化/重啟不丟失 | ❌ 記憶體內 | ❌ 記憶體內 | ✅ 資料庫持久化 |
| Cron 表達式支援 | ❌ 僅固定延遲/週期 | ✅ @Scheduled(cron="...") | ✅ 原生 CronTrigger |
| 動態新增/移除任務 | 困難 | 困難 (需重啟或反射) | ✅ API 動態管理 |
| 監控/管理介面 | 無 | 無 (需 Actuator) | 豐富 (Quartz Manager, Admin UI) |
| 適用場景 | 簡單單機、臨時任務 | Spring 專案、固定排程、非關鍵 | 生產環境、叢集、需持久化/動態管理 |
@Configuration @EnableScheduling
public class TaskConfig {}
@Component
public class HtmlGenerateTask {
@Autowired HtmlService htmlService;
// 每天凌晨 02:00
@Scheduled(cron = "0 0 2 * * ?")
public void generateDailyHtml() {
List list = htmlService.queryData();
list.forEach(htmlService::generateStaticHtml);
}
}
@Component
public class DataCleanupTask {
@Autowired JdbcTemplate jdbc;
// 每月 1 號、16 號 03:00
@Scheduled(cron = "0 0 3 1,16 * ?")
public void markObsolete() {
jdbc.update("UPDATE biz_data SET status='OBSOLETE' WHERE create_time < DATE_SUB(NOW(), INTERVAL 15 DAY) AND status='ACTIVE'");
}
}
# application.yml
spring:
quartz:
job-store-type: jdbc
jdbc:
initialize-schema: always
properties:
org.quartz.scheduler.instanceName: MyScheduler
org.quartz.scheduler.instanceId: AUTO
org.quartz.jobStore.class: org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.tablePrefix: QRTZ_
org.quartz.jobStore.isClustered: true
org.quartz.jobStore.clusterCheckinInterval: 15000
實作 `Job` 介面,透過 `SchedulerFactoryBean` 註冊 `JobDetail` + `CronTrigger`,即可獲得企業級排程能力。
**Spring Boot 專案 → `@Scheduled` 起步,若未來需叢集/持久化/動態管理 → 平滑遷移至 Quartz** (Spring 整合無縫)。