spring與quartz的整合


使用方法

quartz是一個強大的任務調度框架,利用spring將其整合,添加較少的配置即可快速使用,主要步驟如下:

0. 導入需要的jar包或添加依賴,主要有spring-context-support、spring-tx、quartz;

1. 編寫被調度類和被調度方法,即需要定時執行的類和方法;

2. 在spring容器中注冊被調度類,單個注冊或包掃描均可;

3. 在spring容器中注冊作業類(MethodInvokingjOBdetailFactoryBean),並注入被調度類和被調度方法,一般每個被調度方法需要注冊一個作業類;

4. 在spring容器中注冊觸發器,並注入對應的作業類和觸發條件,一般每個作業類需要注冊一個觸發器;

觸發器是用來指定被調度方法的執行時間的,根據觸發條件的不同,有兩個類可以選擇:

(1) SimpleTriggerFactoryBean,只能指定間隔固定時長執行,例如每隔5秒鍾執行一次;

(2) CronTriggerFactoryBean,既可以指定間隔固定時長執行,也可以指定某個或某幾個時刻執行,例如每周三下午16點;

5. 在spring容器中注冊調度工廠(ScheduerFactoryBean),並注入需要的觸發器,可以注入一個或多個觸發器。

 

示例Demo

被調度類和被調度方法 

/**
 * 使用quartz框架實現定時任務
 * 被調度類
 * created on 2019-04-20
 */
public class QuartzJob {

    /**
     * 定時方法,使用固定時長指定執行時間
     */
    public void doSimpleBusiness() {
        //業務邏輯省略,僅測試能執行方法
        System.out.println("----------quartz + 固定時長----------");
    }

    /**
     * 定時方法,使用cron表達式指定執行時間
     */
    public void doCronBusiness() {
        //業務邏輯省略,僅測試能執行方法
        System.out.println("----------quartz + cron表達式----------");
    }

}

 

spring配置文件

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

    <!--注冊被調度類-->
    <bean id="quartzJob" class="cn.monolog.diana.quartz.QuartzJob" />

    <!--注冊固定時長的作業類,並注入被調度類和被調度方法-->
    <bean id="jobDetail1" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject" ref="quartzJob" />
        <property name="targetMethod" value="doSimpleBusiness" />
    </bean>

    <!--注冊固定時長的觸發器,並注入相應的作業類和間隔時間(單位為毫秒)-->
    <bean id="trigger1" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
        <property name="jobDetail" ref="jobDetail1" />
        <property name="repeatInterval" value="3000" />
    </bean>

    <!--注冊cron表達式的作業類,並注入被調度類和被調度方法-->
    <bean id="jobDetail2" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject" ref="quartzJob" />
        <property name="targetMethod" value="doCronBusiness" />
    </bean>

    <!--注冊cron表達式的觸發器,並注入相應的作業類和cron表達式-->
    <bean id="trigger2" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
        <property name="jobDetail" ref="jobDetail2" />
        <property name="cronExpression" value="0/4 * * * * ?" />
    </bean>

    <!--注冊調度工廠,並注入需要生效的觸發器,注意最后autowire的配置-->
    <bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" autowire="no">
        <property name="triggers">
            <list>
                <ref bean="trigger1" />
                <ref bean="trigger2" />
            </list>
        </property>
    </bean>

</beans>

 

踩過的坑

1. 一開始只是添加了spring-context-support和quartz依賴,結果服務啟動失敗,異常日志如下:

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'schedulerFactory' defined in class path resource [applicationContext.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.scheduling.quartz.SchedulerFactoryBean]: No default constructor found; nested exception is java.lang.NoClassDefFoundError: org/springframework/transaction/TransactionException
乍一看是因為初始化ScheduerFactoryBean失敗,因為沒有默認的構造器,后面又說是沒有關於TransactionException的定義。但是我這個demo並沒有用到事務,跟TransactionException有啥關系?暫時找不到內在聯系,但是既然提示了,就加關於事務的依賴試一下。果然,添加了spring-tx的依賴之后,服務啟動成功。至於為什么初始化ScheduerFactoryBean需要用到事務,待日后找到答案再來更新。

 

2. 一開始在配置文件中注冊調度工廠並沒有加autowire屬性,啟動服務時報錯,無法啟動quartz觸發器,因為表不存在,異常日志如下:

com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'sm4_console.QRTZ_TRIGGERS' doesn't exist

參考了這位大神的博文https://www.cnblogs.com/gmq-sh/p/4328317.html,大概意思是quartz會使用數據庫記錄被調度類的狀態,而數據庫中並不存在這些日志表。解決方法就是在配置文件注冊調度工廠時加autowire屬性配置。

 

其他整合方案

除了上述,spring還提供了另外一種整合quartz的方案,即被調度類需要繼承QuartzJobBean類,其他配置方式類似。

但是這種方案顯然不如第一種靈活,因為被調度類需要繼承固定的類,而Java又是單繼承……


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM