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

Quartz 與 Spring 整合實戰:定時任務的企業級最佳實踐

     編輯:Java 綜合教學

Quartz 與 Spring 整合實戰:定時任務的企業級最佳實踐

Quartz 是 Java 生態最成熟的定時調度框架,Spring 提供了無縫整合支援,將 Job、Trigger、Scheduler 納入 IOC 容器統一管理。本文系統講解 JobDetail 兩種配置方式、SimpleTrigger/CronTrigger 宣告式配置、SchedulerFactoryBean 統一裝配、集群/持久化/事務/監控 進階主題,並給出生產環境檢查清單。

一、JobDetail 配置:兩種風格任君選擇

1. JobDetailFactoryBean:標準 Quartz Job 風格

適用於複雜邏輯、需存取 JobExecutionContext、JobDataMap 的場景。

// 任務實現類繼承 QuartzJobBean
public class SimpleJob extends QuartzJobBean {
    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        System.out.println("執行時間: " + new Date());
        JobDataMap dataMap = context.getMergedJobDataMap();
        String wish = dataMap.getString("wish");
        System.out.println("參數 wish: " + wish);
    }
}

// Spring XML 配置
<bean id="simpleJob" class="com.example.job.SimpleJob" />

<bean id="jobDetailFactoryBeanExample" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
    <property name="jobClass" value="com.example.job.SimpleJob" />
    <property name="jobDataAsMap">
        <map>
            <entry key="wish" value="hello" />
        </map>
    </property>
    <property name="durability" value="true" /> <!-- 無 Trigger 時也不刪除 -->
</bean>

2. MethodInvokingJobDetailFactoryBean:POJO 方法調用風格(推薦)

任務類無需繼承任何介面,純 POJO,測試極其方便,生產首選。

public class ExampleJob {
    public void execute() {
        System.out.println("現在是 " + new SimpleDateFormat("yyyy年MM月dd日 HH時mm分ss秒").format(new Date()));
    }
}

// Spring XML 配置
<bean id="exampleJob" class="com.example.job.ExampleJob" />

<bean id="methodInvokingJobDetailFactoryBeanExample" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
    <property name="targetObject" ref="exampleJob" />
    <property name="targetMethod" value="execute" />
    <property name="concurrent" value="false" /> <!-- 禁止併發執行 -->
</bean>

關鍵屬性:concurrent=false 確保同一任務不並行(上次未結束不啟動下次),等同實作 StatefulJob 介面。

二、Trigger 配置:Simple vs Cron

SimpleTriggerFactoryBean:固定頻率/延遲

<bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
    <property name="jobDetail" ref="methodInvokingJobDetailFactoryBeanExample" />
    <property name="startDelay" value="5000" /> <!-- 5 秒後首次執行 -->
    <property name="repeatInterval" value="3000" /> <!-- 每 3 秒重複 -->
    <property name="repeatCount" value="10" /> <!-- 重複 10 次(預設 -1 無限) -->
</bean>

CronTriggerFactoryBean:Cron 表達式(推薦生產)

<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
    <property name="jobDetail" ref="jobDetailFactoryBeanExample" />
    <property name="cronExpression" value="0 0/5 * * * ?" /> <!-- 每 5 分鐘 -->
    <property name="timeZone" value="Asia/Shanghai" /> <!-- 關鍵:指定時區 -->
</bean>

常用 Cron 表達式:

表達式含義
0 0 2 * * ?每天凌晨 2 點
0 0/10 * * * ?每 10 分鐘
0 0 0 1 * ?每月 1 號 0 點
0 0 0 ? * MON每週一 0 點
0 15 10 ? * 6L每月最後一個週五 10:15

三、SchedulerFactoryBean:統一裝配入口

<bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" lazy-init="false">
    <property name="triggers">
        <list>
            <ref bean="cronTrigger" />
            <ref bean="simpleTrigger" />
        </list>
    </property>
    <!-- 進階配置 -->
    <property name="overwriteExistingJobs" value="true" /> <!-- 覆蓋同名 Job -->
    <property name="startupDelay" value="30" /> <!-- 延遲 30 秒啟動,等待資料庫就緒 -->
    <property name="autoStartup" value="true" />
    <property name="applicationContextSchedulerContextKey" value="applicationContext" /> <!-- Job 中可獲取 Spring 容器 -->
</bean>

四、進階主題:生產級能力建設

1. 持久化與集群(JDBC JobStore)

<bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="transactionManager" ref="transactionManager" />
    <property name="overwriteExistingJobs" value="true" />
    <property name="quartzProperties">
        <props>
            <prop key="org.quartz.jobStore.class">org.quartz.impl.jdbcjobstore.JobStoreTX</prop>
            <prop key="org.quartz.jobStore.driverDelegateClass">org.quartz.impl.jdbcjobstore.StdJDBCDelegate</prop>
            <prop key="org.quartz.jobStore.tablePrefix">QRTZ_</prop>
            <prop key="org.quartz.jobStore.isClustered">true</prop>
            <prop key="org.quartz.jobStore.clusterCheckinInterval">20000</prop>
            <prop key="org.quartz.scheduler.instanceId">AUTO</prop>
        </props>
    </property>
</bean>

集群關鍵點:共享資料庫、isClustered=true、instanceId=AUTO、時間同步(NTP)、資料庫鎖機制保證唯一執行。

2. 事務邊界管理

任務執行需資料庫事務時,配置 transactionManager,Quartz 會在 executeInternal 外層開啟事務,異常自動回滾。

3. 動態新增/修改/刪除任務

@Autowired private Scheduler scheduler;

// 新增
scheduler.scheduleJob(jobDetail, trigger);

// 修改觸發時間
scheduler.rescheduleJob(triggerKey, newTrigger);

// 暫停/恢復/刪除
scheduler.pauseJob(jobKey);
scheduler.resumeJob(jobKey);
scheduler.deleteJob(jobKey);

4. 監控與指標

  • 啟用 org.quartz.plugin.jobHistory 記錄執行歷史
  • 整合 Micrometer/Prometheus 導出 quartz_job_executed_total、quartz_job_duration_seconds
  • Spring Boot Actuator /actuator/quartz 端點(需依賴 spring-boot-starter-quartz)

五、Spring Boot 2.x+ 簡化配置(註解驅動)

@Configuration
@EnableScheduling
public class QuartzConfig {

    @Bean
    public JobDetailFactoryBean jobDetail() {
        JobDetailFactoryBean factory = new JobDetailFactoryBean();
        factory.setJobClass(MyJob.class);
        factory.setDurability(true);
        return factory;
    }

    @Bean
    public CronTriggerFactoryBean trigger(JobDetail jobDetail) {
        CronTriggerFactoryBean factory = new CronTriggerFactoryBean();
        factory.setJobDetail(jobDetail);
        factory.setCronExpression("0 0/5 * * * ?");
        factory.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
        return factory;
    }

    @Bean
    public SchedulerFactoryBean scheduler(Trigger trigger, DataSource dataSource, PlatformTransactionManager txManager) {
        SchedulerFactoryBean factory = new SchedulerFactoryBean();
        factory.setTriggers(trigger);
        factory.setDataSource(dataSource);
        factory.setTransactionManager(txManager);
        factory.setOverwriteExistingJobs(true);
        factory.setQuartzProperties(quartzProps());
        return factory;
    }

    private Properties quartzProps() {
        Properties props = new Properties();
        props.setProperty("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX");
        props.setProperty("org.quartz.jobStore.isClustered", "true");
        return props;
    }
}

六、生產環境檢查清單

項目建議
時區所有 CronTrigger 顯式設定 timeZone,JVM -Duser.timezone=Asia/Shanghai
併發控制concurrent=false 或 實作 StatefulJob,避免重疊執行導致資料不一致
異常處理Job 內捕獲異常記錄日誌,拋出 JobExecutionException 讓 Quartz 決定重試/暫停
冪等性任務邏輯設計為冪等(唯一鍵、狀態機、分散式鎖),防重複執行
優雅關閉scheduler.shutdown(true) 等待執行中任務完成,配合 Spring @PreDestroy
資料庫索引QRTZ 表建立適當索引(SCHED_NAME, TRIGGER_GROUP, NEXT_FIRE_TIME)
日誌追蹤MDC 注入 jobName、fireInstanceId,關聯業務日誌

總結

Quartz + Spring 整合將調度能力內建於 IOC 容器,MethodInvokingJobDetailFactoryBean + CronTriggerFactoryBean + SchedulerFactoryBean 三劍客覆蓋 95% 場景。進階採用 JDBC JobStore 集群 保證高可用,事務管理 保證資料一致性,動態 API 支援運維靈活性。遵循本文最佳實踐與檢查清單,即可構建穩定、可觀測、可運維的企業級定時調度系統。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved