Spring與Quartz實現定期任務

jopen 10年前發布 | 46K 次閱讀 Quartz 作業調度框架

日志說明:
1、不對Spring的基礎環境配置做詳細說明;
2、只是記錄一下暫時自己從網上及參考手冊上查找到的經測試有用的資料
3、記錄一下,方便以后自己或需要的朋友使用,后續有新的有用資料會及時更新


4、可查看Spring4.0參考手冊:Part Ⅵ.Integration的27.6Using the Quartz Scheduler
5、測試時用的卻是Spring3.1.3
注意:引用Quartz時最好使用1.8.5(目前最新的是2.2.1,此版本與Spring3.1.1暫不兼容,實測時啟動項目會報錯)

<!-- 
任務調度測試實現一 :
自定義的任務對象com.bocloud.equipment.test.ExampleJob
必須繼承QuartzJobBean類,實現抽象方法executeInternal
每次執行任務時,都會新創建一個任務對象.
-->
<bean id="myJobDetail" class="org.springframework.scheduling.quartz.JobDetailBean">
    <!--
    屬性jobClass不能通過ref來指定為exampleJob對象,該屬性接收的是Class類型的參數
    進行任務調度時,每次都是一個新的jobClass對象去執行executeInternal方法
    -->
    <property name="jobClass" value="com.bocloud.equipment.test.ComputerInfoGatherJob" />
</bean>

<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
    <property name="jobDetail" ref="myJobDetail" />
    <property name="cronExpression" value="0/10 * * * * ?" />
</bean>

<bean id="computerInfoGatherScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <property name="triggers">
        <list>
            <ref bean="cronTrigger" />
        </list>
    </property>
</bean>


我們只需要專注于QuartzJobBean子類中的executeInternal方法的實現,該方法里只需要放置我們需要定期執行的任務代碼即可

<!-- 
任務調試實現測試二 :
屬性targetObject:指定執行任務的對象
屬性targetMethod:指定執行任務的方法,該方法必須是無參方法
-->
<bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
    <property name="targetObject" ref="computerService" />
    <property name="targetMethod" value="list" />
</bean>

<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
    <property name="jobDetail" ref="jobDetail" />
    <property name="cronExpression" value="0/10 * * * * ?" />
</bean>

<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <property name="triggers">
        <list>
        <ref bean="cronTrigger" />
    </list>
    </property>
</bean>

targetObject引用參考的對象,就是Spring框架幫我們生成好的自定義的任務bean對象,不過要注意的是,targetMehthod指定的方法必須是無參的(Spring也支持可以帶有參數的任務方法,具體的沒注意,以后搞明白了再更新上來,不過一般我們執行定期任務時都不需要動態參數)

package com.bocloud.equipment.test;

import java.text.ParseException;
import java.util.Date;

import org.quartz.CronTrigger;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.impl.StdScheduler;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.WebApplicationContext;

import com.bocloud.equipment.service.ComputerServiceImpl;

public class ComputerInfoGatherJob extends QuartzJobBean {

    private static long count = 0L;

    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        System.out.println("*******************************");
        count++;
        System.out.println(new Date() + "\t:任務調度開始第" + count + "次");

        WebApplicationContext webContext = ContextLoaderListener.getCurrentWebApplicationContext();
        ComputerServiceImpl csi = webContext.getBean(ComputerServiceImpl.class);
        /*
         * 更改任務調度的周期時間:
         * 1,不要調用StdScheduler的shutdown()方法,shutdown()以后無法再start()
         * 2,可使用standby()暫停調度任務,再start()
         * 3,設置cron后,要調用rescheduleJob(TriggerKey triggerKey, Trigger newTrigger)
         */

        /*
         * 這里獲取SchedulerFactoryBean時,不要通過getBean(Class<T> requiredType)
         * 或getBean(String name, Class<T> requiredType)
         * 否則會提示轉型錯誤:
         * org.quartz.impl.StdScheduler無法轉型為指定的需要類型:
         * org.springframework.scheduling.quartz.SchedulerFactoryBean
         * 直接使用getBean(String name)再強轉為org.quartz.impl.StdScheduler即可
         */
        StdScheduler scheduler = (StdScheduler)webContext.getBean("computerInfoGatherScheduler");
        if (count == 2) {
            System.out.println("Computer信息采集任務暫停!");
            try {
                //獲取此調度器中名稱為cronTrigger(配置文件中CronTriggerFactoryBean的名稱)的Trigger對象
                CronTrigger cronTrigger = (CronTrigger) scheduler.getTrigger("cronTrigger", Scheduler.DEFAULT_GROUP);
                System.out.println("設置Computer信息采集任務周期為:5秒");
                cronTrigger.setCronExpression("0/5 * * * * ?");
                /*
                 * public Date rescheduleJob(String triggerName, String groupName, Trigger newTrigger) throws SchedulerException
                 * triggerName:要被替換的Trigger的名稱
                 * groupName:要被替換的Trigger的組名
                 * newTrigger:要新保存的Trigger對象
                 * 返回:如果沒找到triggerName則返回空,否則返回第一次觸發任務的時間
                 */
                Date date = scheduler.rescheduleJob("cronTrigger", Scheduler.DEFAULT_GROUP, cronTrigger);
                System.out.println("=========Computer信息采集任務重新開始=========");
                if (date == null) {
                    throw new RuntimeException("更改任務周期后,重新調度任務失敗!!!");
                }
            } catch (SchedulerException e) {
                System.out.println("獲取CronTrigger對象時出現異常");
                e.printStackTrace();
            } catch (ParseException e) {
                System.out.println("解析cron表達式時出現異常");
                e.printStackTrace();
            }
        }

        if (count == 4) {
            System.out.println("暫停任務調度!!10秒后重新開始");
            //暫停調度任務:調度器中的所有Trigger對應的任務都會暫停,要暫停指定Trigger的話,調用pauseTrigger()
            scheduler.standby();
            try {
                Thread.sleep(10000);
                //判斷調度器當前是否在暫停狀態
                if (scheduler.isInStandbyMode()) {
                    scheduler.start();
                }
                System.out.println("任務調度又重新開始");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (SchedulerException e) {
                e.printStackTrace();
            }
        }
        csi.list(0, null, null);
    }

}

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!