首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Quartz 2.2.1 實戰入門:從核心概念到 Web 整合

     編輯:Java 綜合教學

Quartz 2.2.1 极速上手指南:調度框架核心三件套與最佳實踐

Quartz 是 Java 生態中事實標準的任務調度框架。本文提煉官方文檔精華,結合實戰經驗,從「三大核心組件」到「Web 容器整合」、從「參數傳遞」到「監聽器鏈」,為你構建完整的 Quartz 知識體系,助你在半小時內從入門到可用。

核心三件套:JobDetail、Trigger、Scheduler

// 1. 定義任務(業務邏輯載體)
JobDetail job = JobBuilder.newJob(HelloJob.class)
    .withIdentity("job1", "group1").build();

// 2. 定義觸發器(時間規則)
Trigger trigger = TriggerBuilder.newTrigger()
    .withIdentity("trigger1", "group1")
    .startNow()
    .withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?")) // 每 5 秒
    .build();

// 3. 調度器:綁定並啟動
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.scheduleJob(job, trigger);
scheduler.start(); // 必須調用才真正跑起來
// 應用關閉時
scheduler.shutdown();

關鍵概念釐清

  • JobDetail ≠ Job 實現類:JobDetail 是「任務定義」(含名稱/組/參數),HelloJob 才是實際 execute() 邏輯。一個 Job 類可對應多個 JobDetail。
  • Trigger 專職「何時跑」:支援 SimpleTrigger(固定間隔)、CronTrigger(Cron 表達式)、CalendarIntervalTrigger 等。一個 JobDetail 可掛多個 Trigger,實現同一業務不同頻率執行。
  • Scheduler 是總控中樞:start() 前後掛任務均可,內部維護線程池與調度邏輯。

優雅的構建器靜態導入

import static org.quartz.JobBuilder.*;
import static org.quartz.TriggerBuilder.*;
import static org.quartz.CronScheduleBuilder.*;
import static org.quartz.SimpleScheduleBuilder.*;
// 之後直接 newJob()、newTrigger()、cronSchedule() 鏈式調用

強烈建議統一使用 CronTrigger,其表達式能力幾乎覆蓋所有業務場景,減少認知負擔。

參數傳遞最佳實踐:JobDataMap

// JobDetail 級參數(所有 Trigger 共享)
jobDetail.getJobDataMap().put("bizKey", JSON.toJSONString(bizObj));

// Trigger 級參數(覆蓋/補充 JobDetail 參數)
trigger.getJobDataMap().put("runId", UUID.randomUUID().toString());

// 執行時統一獲取(自動合併)
context.getMergedJobDataMap().getString("bizKey");

建議所有值統一序列化為 String,避免類加載器隔離導致反序列化失敗。

監聽器鏈:全鏈路可觀測

// 實現自定義監聽器
public class MetricsJobListener extends JobListenerSupport {
    @Override public void jobToBeExecuted(JobExecutionContext ctx) { /* 記錄開始時間 */ }
    @Override public void jobWasExecuted(JobExecutionContext ctx, JobExecutionException e) {
        // 記錄耗時、成功/失敗、異常堆棧
    }
}

// 註冊(支援針對特定 Job/Group)
scheduler.getListenerManager().addJobListener(listener, allJobs());
scheduler.getListenerManager().addTriggerListener(triggerListener);

執行順序鏈:
TriggerListener.triggerFired → JobListener.jobToBeExecuted → Job.execute → JobListener.jobWasExecuted → TriggerListener.triggerComplete
利用此鏈可實現:執行指標收集、失敗告警、業務狀態流轉等橫切關注點。

Web 容器無縫整合(無 Spring 情況下)

1. web.xml 配置 QuartzInitializerServlet

<servlet>
  <servlet-name>QuartzInitializer</servlet-name>
  <servlet-class>org.quartz.ee.servlet.QuartzInitializerServlet</servlet-class>
  <init-param>
    <param-name>config-file</param-name>
    <param-value>/quartz.properties</param-value>
  </init-param>
  <init-param>
    <param-name>shutdown-on-unload</param-name>
    <param-value>true</param-value>
  </init-param>
  <load-on-startup>2</load-on-startup>
</servlet>

2. quartz.properties 關鍵配置(JDBC JobStore 生產級)

org.quartz.scheduler.instanceName = MainScheduler
org.quartz.scheduler.instanceId = instance_one  # 集群時每節點唯一
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 10
org.quartz.threadPool.threadPriority = 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true

org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.dataSource = qzDS
org.quartz.jobStore.useProperties = true  # 強制 String 參數,避免序列化坑
org.quartz.jobStore.isClustered = false   # 集群改 true

org.quartz.dataSource.qzDS.driver = com.mysql.jdbc.Driver
org.quartz.dataSource.qzDS.URL = jdbc:mysql://localhost:3306/quartz?useUnicode=true&characterEncoding=utf-8
org.quartz.dataSource.qzDS.user = root
org.quartz.dataSource.qzDS.password = 123456
org.quartz.dataSource.qzDS.maxConnections = 30

3. 業務代碼獲取 Scheduler

SchedulerFactory sf = (SchedulerFactory) servletContext
    .getAttribute(QuartzInitializerServlet.QUARTZ_FACTORY_KEY);
Scheduler scheduler = sf.getScheduler(); // 已自動 start()

管理封裝建議

封裝 JobManager 提供:addJob()、pauseJob()、resumeJob()、deleteJob()、triggerJobNow() 等統一入口,內部處理 JobKey/TriggerKey 構建與異常轉換,對上層業務屏蔽 Quartz API 細節。

避坑指南

  • 集群模式必須共享數據庫,且 instanceId 唯一,isClustered=true
  • @DisallowConcurrentExecution 註解防止同一 JobDetail 並發執行(基於鎖機制)
  • Cron 表達式驗證:上線前用在線工具驗證,避免「每分鐘跑」寫成「每小時跑」
  • 事務邊界:Job 內業務異常拋出 JobExecutionException 可配合 refireImmediately 實現重試策略

掌握以上內容,你已具備在生產環境落地 Quartz 的完整能力。更多高級特性(如 Calendar 排除節假日、插件擴展、集群故障轉移)請參考官方文檔深入探索。

  1. 上一篇文章:
  2. 下一篇文章:
Java 代碼塊深度解析:普通、構造、靜態代碼塊執行順序與應用場景 Java 多線程同步機制詳解:鎖、死鎖與同步粒度 微服務架構優勢與挑戰深度解析:從單體到微服務的演進之路 JS 載入時機陷阱:為什麼