Quartz 是 Java 生態系中最成熟、功能最豐富的開源任務調度框架。本文系統梳理其核心概念、架構設計,並提供 Spring 整合的實戰配置範例,幫助開發者快速掌握企業級定時任務的構建方法。
在企業級應用中,定時任務無處不在:
相較於簡單的 Timer 或 ScheduledExecutorService,Quartz 提供了持久化、叢集、事務支援、Cron 表達式等企業級特性。
Quartz 將調度領域高度抽象為三個核心介面:
| 組件 | 介面 | 核心職責 |
|---|---|---|
| Scheduler (調度器) | org.quartz.Scheduler | 調度容器,管理觸發器與任務的生命週期,負責執行緒池調度 |
| Job (任務) | org.quartz.Job | 業務邏輯載體,實作 execute(JobExecutionContext) 方法 |
| Trigger (觸發器) | org.quartz.Trigger | 定義觸發規則,主流有 SimpleTrigger (固定間隔) 與 CronTrigger (Cron 表達式) |
關係圖譜:
repeatInterval (間隔毫秒數)、repeatCount (重複次數,-1 表示無限)org.springframework.scheduling.quartz.SimpleTriggerFactoryBean秒 分 時 日 月 週 [年] (7 個欄位)0 0 2 * * ? - 每天凌晨 2 點0 30 9 ? * MON-FRI - 工作日早上 9:300 0 0 1 * ? - 每月 1 號午夜org.springframework.scheduling.quartz.CronTriggerFactoryBean採用 Spring 的 MethodInvokingJobDetailFactoryBean 將任務委派給 Spring Bean 方法,實現鬆耦合:
@Service("payCalculateService")
public class PayCalculateService {
@Resource(name = "daoSupport")
private DaoSupport dao;
/**
* 結息(罰息)定時計算 - 每日執行
*/
public String settlementCalculate() throws Exception {
String settlementDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
PageData pd = new PageData();
pd.put("settlement_date", settlementDate);
// 呼叫 MyBatis Mapper 中定義的存儲過程
dao.findForObject("PayCalculateMapper.settlementCalculate", pd);
return "SUCCESS";
}
}
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX 使用資料庫持久化,設定 org.quartz.jobStore.isClustered = true 實現高可用SmartLifecycle 或註冊 JVM 關閉鉤子,確保 scheduler.shutdown(true) 等待執行中任務完成| 現象 | 可能原因 | 解決方案 |
|---|---|---|
| 任務未在預期時間執行 | Misfire 處理策略不當、系統時間不同步 | 設定合適的 misfireInstruction、啟用 NTP 時間同步 |
| 任務重複執行 | 叢集節點時間漂移、concurrent=false 但鎖失效 | 檢查資料庫鎖表、確保節點時間同步 |
| 執行緒池耗盡 | 任務執行時間過長、並發任務過多 | 調大 threadCount、優化任務邏輯、拆分長任務 |