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

Spring 框架整合 Quartz 定時任務完整配置教程

     編輯:Java 相關知識

Quartz 在 Spring 中的整合架構

Quartz 是功能強大的開源任務調度庫,Spring 通過 spring-context-support 模塊提供無縫整合。核心組件:

  • JobDetail:任務定義 (執行什麼)
  • Trigger:觸發條件 (何時執行)
  • Scheduler:調度器 (綁定 Job 與 Trigger)

Maven 依賴配置

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-support</artifactId>
    <version>5.3.x</version>
</dependency>
<!-- Quartz 已包含在 spring-context-support 中,無需額外引入 -->
<!-- 解決 commons-collections 版本衝突 -->
<dependency>
    <groupId>commons-collections</groupId>
    <artifactId>commons-collections</artifactId>
    <version>3.2.2</version>
</dependency>

web.xml 啟動 Spring 容器

<web-app xmlns="https://xmlns.jcp.org/xml/ns/javaee" version="3.1">
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:application-*.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
</web-app>

Quartz 專用配置文件 application-quartz.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
       xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="https://www.springframework.org/schema/beans
       https://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 1. 任務實現 Bean -->
    <bean id="reportTask" class="com.job.ReportGenerationTask"/>

    <!-- 2. 方法調用封裝 (MethodInvokingJobDetailFactoryBean) -->
    <bean id="reportJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject" ref="reportTask"/>
        <property name="targetMethod" value="generateDailyReport"/>
        <property name="concurrent" value="false"/> <!-- 禁止並發執行 -->
    </bean>

    <!-- 3. Cron 觸發器 -->
    <bean id="reportTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
        <property name="jobDetail" ref="reportJobDetail"/>
        <!-- 每天凌晨 2:30 執行 -->
        <property name="cronExpression" value="0 30 2 * * ?"/>
    </bean>

    <!-- 4. 簡單觸發器 (固定頻率) -->
    <bean id="heartbeatTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
        <property name="jobDetail" ref="heartbeatJobDetail"/>
        <property name="repeatInterval" value="30000"/> <!-- 30 秒 -->
        <property name="startDelay" value="10000"/> <!-- 10 秒後首次執行 -->
    </bean>

    <!-- 5. 調度器工廠 -->
    <bean id="schedulerFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="triggers">
            <list>
                <ref bean="reportTrigger"/>
                <ref bean="heartbeatTrigger"/>
            </list>
        </property>
        <property name="overwriteExistingJobs" value="true"/>
        <property name="startupDelay" value="30"/> <!-- 啟動 30 秒後啟動調度 -->
        <property name="autoStartup" value="true"/>
        <!-- 數據源配置 (集群模式必需) -->
        <!-- <property name="dataSource" ref="dataSource"/> -->
        <!-- <property name="transactionManager" ref="transactionManager"/> -->
    </bean>

</beans>

任務實現類

方式一:繼承 QuartzJobBean (可訪問 JobExecutionContext)

package com.job;

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ReportGenerationTask extends QuartzJobBean {
    private static final Logger log = LoggerFactory.getLogger(ReportGenerationTask.class);
    
    @Override
    protected void executeInternal(JobExecutionContext context) 
            throws JobExecutionException {
        // 可從 context 獲取傳遞參數
        String param = context.getMergedJobDataMap().getString("customParam");
        log.info("執行報表生成任務,參數: {}", param);
        generateDailyReport();
    }
    
    public void generateDailyReport() {
        // 業務邏輯:查詢數據、生成報表、發送郵件、存儲文件
        log.info("每日報表生成完成");
    }
}

方式二:普通 POJO + MethodInvokingJobDetailFactoryBean (推薦)

package com.job;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class OrderCleanupTask {
    private static final Logger log = LoggerFactory.getLogger(OrderCleanupTask.class);
    
    public void cleanupExpiredOrders() {
        log.info("開始清理過期訂單...");
        // 業務邏輯
        log.info("過期訂單清理完成");
    }
}

Cron 表達式詳細解析

格式:秒 分 時 日 月 周 [年]
字段        允許值          特殊字符
秒          0-59            , - * /
分          0-59            , - * /
時          0-23            , - * /
日          1-31            , - * ? / L W C
月          1-12 / JAN-DEC  , - * /
周          1-7 / SUN-SAT   , - * ? / L C #
年(可選)    1970-2099       , - * /

特殊字符含義:
*  : 所有值
?  : 無具體值 (僅日/周字段互斥)
-  : 範圍 (如 10-12 時 表示 10,11,12 點)
,  : 枚舉值 (如 MON,WED,FRI)
/  : 增量 (如 0/15 分 表示每 15 分鐘)
L  : 最後 (日字段=月末,周字段=週六/最後一個周五)
W  : 工作日 (最近的工作日,如 15W 表示該月 15 號最近的工作日)
#  : 第 N 個 (如 6#3 表示該月第三個週五)
C  : 日曆關聯 (需關聯 Calendar)

常用 Cron 表達式示例

表達式含義
0 0 12 * * ?每天中午 12:00
0 15 10 ? * *每天上午 10:15
0 0/5 14 * * ?每天 14:00-14:55 每 5 分鐘
0 0/5 14,18 * * ?每天 14:00-14:55 和 18:00-18:55 每 5 分鐘
0 0-5 14 * * ?每天 14:00-14:05 每分鐘
0 10,44 14 ? 3 WED每年 3 月週三 14:10 和 14:44
0 15 10 ? * MON-FRI週一至週五 10:15
0 15 10 15 * ?每月 15 號 10:15
0 15 10 L * ?每月最後一天 10:15
0 15 10 ? * 6L每月最後一個週五 10:15
0 15 10 ? * 6#3每月第三個週五 10:15

集群模式配置 (生產環境必備)

<!-- quartz.properties 或在 SchedulerFactoryBean 中配置 -->
org.quartz.scheduler.instanceName = MyClusteredScheduler
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 = 20000
org.quartz.jobStore.useProperties = false
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 10
org.quartz.threadPool.threadPriority = 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true

Spring 集群配置

<bean id="schedulerFactory" 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.isClustered">true</prop>
            <prop key="org.quartz.jobStore.clusterCheckinInterval">20000</prop>
        </props>
    </property>
    <property name="configLocation" value="classpath:quartz.properties"/>
</bean>

動態任務管理 (運行時增刪改查)

常見問題與解決

問題原因解決
任務不執行Scheduler 未啟動、Trigger 配置錯誤、Bean 未注入檢查 autoStartup=true、日誌輸出、@Autowired 注入
並發執行導致數據錯亂concurrent=false 未生效、集群節點時間不同步設置 @DisallowConcurrentExecution、NTP 同步時間
任務執行超時/卡死業務邏輯死循環、資源未釋放、線程池耗盡設置執行超時、監控線程堆棧、優化業務邏輯
併發修改異常集群模式下無樂觀鎖、版本衝突確保數據庫表有版本字段、使用 RowVersion
commons-collections 版本衝突Hibernate 依賴舊版本排除舊版,強制使用 3.2.2+

Spring Boot 2.x+ 簡化配置

@Configuration
@EnableScheduling
public class QuartzConfig {
    
    @Bean
    public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource, 
            PlatformTransactionManager txManager) {
        SchedulerFactoryBean factory = new SchedulerFactoryBean();
        factory.setDataSource(dataSource);
        factory.setTransactionManager(txManager);
        factory.setOverwriteExistingJobs(true);
        factory.setAutoStartup(true);
        factory.setStartupDelay(30);
        return factory;
    }
    
    @Bean
    public JobDetailFactoryBean reportJobDetail() {
        JobDetailFactoryBean factory = new JobDetailFactoryBean();
        factory.setJobClass(ReportGenerationTask.class);
        factory.setDurability(true);
        return factory;
    }
    
    @Bean
    public CronTriggerFactoryBean reportTrigger(JobDetail reportJobDetail) {
        CronTriggerFactoryBean factory = new CronTriggerFactoryBean();
        factory.setJobDetail(reportJobDetail);
        factory.setCronExpression("0 30 2 * * ?");
        return factory;
    }
}

Spring 整合 Quartz 提供了企業級任務調度能力,支持集群、持久化、動態管理、事務邊界控制。生產環境建議採用集群模式 + 數據庫持久化 + 監控告警,確保定時任務高可用、可追蹤、可治理。

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