Spring與Quartz的整合實現定時任務調度


Quartz集成Spring的2個方法

關於Spring集成Quartz有2種方法:

1. JobDetailBean.

2. MethodInvokeJobDetailFactoryBean.

以下從自身使用和理解以及掌握的知識對其進行闡述。

需要注意的是,在使用Spring集成Quartz的時候,一定不要忘記引入spring-support這個包:

1、使用 MethodInvokeJobDetailFactoryBean

applicationTask.xml 配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-2.5.xsd">
    <!-- 定時任務 下游回調任務-->
    <!-- ======================== 1、定義需要執行的任務類。 ======================== -->
    <bean id="notifyQuartz" class="com.hsmpay.mobile.timerTask.NotifyTimerAction">
    </bean>
    <!-- ======================== 2、將需要執行的定時任務注入JOB中。 ======================== -->
    <bean id="notifyQuartzDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
         <!--引入執行任務的類-->
        <property name="targetObject"><ref bean="notifyQuartz"/></property>
        <!--定義要執行具體類的方法-->
        <property name="targetMethod"><value>remoteNotify</value></property>
    </bean>
    <!-- ======================== 3、調度觸發器 ======================== -->
    <bean id="notifyTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">

        <property name="jobDetail"><ref bean="notifyQuartzDetail"/></property>

        <property name="cronExpression"> <!--每五分鍾執行一次-->
            <!--<value>0 08 10 * * ?</value>-->
            <value>0 0/5 * * * ?</value><!--<value>秒 分 時 天 月 周 年</value> 0 55 17 ? * MON-FRI-->
        </property>
    </bean>
    <!--================================================================================================-->

    <!-- 半分鍾執行定時任務 -->
    <!-- ======================== 1、定義需要執行的任務類。 ======================== -->
    <bean id="messageTask" class="com.hsmpay.mobile.timerTask.MessageTask"></bean>
    <!-- ======================== 2、將需要執行的定時任務注入JOB中。 ======================== -->
    <bean id="oneMessageRollBackTaskJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject"><ref bean="messageTask"/></property>
        <property name="targetMethod"><value>oneTaskJob</value></property>
    </bean>
    <!-- ======================== 3、調度觸發器 ======================== -->
    <bean id="oneMessageStreamRollBackTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
        <property name="jobDetail">
            <ref bean="oneMessageRollBackTaskJobDetail"/>
        </property>
        <property name="cronExpression">
            <value>*/30 * * * * ?</value>
        </property>
    </bean>



    <!-- ======================== 4、調度工廠 ======================== -->
    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="triggers">
            <list>
                <ref bean="notifyTrigger"/>
            </list>
        </property>
    </bean>

    <bean id="threadPoolTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
        <!-- 線程池維護線程的最少數量 -->
        <property name="corePoolSize" value="10" />
        <!-- 線程池維護線程所允許的空閑時間 -->
        <property name="keepAliveSeconds" value="200" />
        <!-- 線程池維護線程的最大數量 -->
        <property name="maxPoolSize" value="50" />
        <!-- 線程池所使用的緩沖隊列 -->
        <property name="queueCapacity" value="100" />
        <property name="rejectedExecutionHandler">
            <!-- AbortPolicy:直接拋出java.util.concurrent.RejectedExecutionException異常 -->
            <!-- CallerRunsPolicy:主線程直接執行該任務,執行完之后嘗試添加下一個任務到線程池中,可以有效降低向線程池內添加任務的速度 -->
            <!-- DiscardOldestPolicy:拋棄舊的任務、暫不支持;會導致被丟棄的任務無法再次被執行 -->
            <!-- DiscardPolicy:拋棄當前任務、暫不支持;會導致被丟棄的任務無法再次被執行 -->
            <bean class="java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy" />
        </property>
    </bean>
</beans>

相關代碼配置

@Controller("notifyTimerAction")
public class NotifyTimerAction {
    private Logger log = LoggerFactory.getLogger(this.getClass());
    @Resource(name="transOrderService")
    TransOrderService transOrderService;//查詢訂單service
    //設置核心池大小
    int corePoolSize = 5;
    //設置線程池最大能接受多少線程
    int maximumPoolSize=20;
    //當前線程數大於corePoolSize、小於maximumPoolSize時,超出corePoolSize的線程數的生命周期
    long keepActiveTime = 200;
    //設置時間單位,秒
    TimeUnit timeUnit = TimeUnit.SECONDS;

    public String url ="http://localhost:8080/mobile/forwardPort/port.action";


    /**
     * 下游回調通知,繼續發送
     */
    public void remoteNotify() throws Exception{
        log.debug("test定時任務啟動了!!!!!!!!");
        System.out.println("test定時任務啟動了!!!!!!!!");
        TransOrder order=new TransOrder();
        order.setStatus(1);//設置成功狀態
        order.setClientType(7);//設置客戶類型 7外放接口類型
        order.setOrderTypeId(1L);//收款類型
        //設置線程池緩存隊列的排隊策略為FIFO,並且指定緩存隊列大小為5
        BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<Runnable>(5);
        //創建ThreadPoolExecutor線程池對象,並初始化該對象的各種參數
        ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepActiveTime, timeUnit,workQueue);
        try {
            List<TransOrder> orderList = transOrderService.searchEntityList(order);
            Map<String,Object> map=new HashMap<String,Object> ();
            //准備給下游發送數據
            for(TransOrder transOrder:orderList){
            Thread thread=new Thread(new Runnable() {
                public void run() {
                map.put("status",transOrder.getStatus());//交易狀態
                map.put("orderNum",transOrder.getOrderNum());//訂單號
                JSONObject jsonObject = JSONObject.fromObject(map);
                HttpClientUtil.submitPost(transOrder.getOtherData(), map.toString(), "UTF-8",60000, 60000);
                }
            });
              executor.execute(thread);
            }
            executor.shutdown();//關閉線程池

        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }

    }

}

==================================================================================================================================================================

二、JobDetailBean

1. 創建一個Job方法,此方法必須繼承QuartzJobBean或者實現Job方法。

public class TestJob extends QuartzJobBean {
    
    @Override
    protected void executeInternal(JobExecutionContext arg0) throws JobExecutionException {
        System.out.println(TimeUtils.getCurrentTime());
    }
}

2. XML配置

<?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="jobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
        <property name="jobClass" value="com.mc.bsframe.job.TestJob"></property>
        <property name="durability" value="true"></property>
    </bean>

    <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
        <property name="jobDetail" ref="jobDetail" />
        <property name="startDelay" value="3000" />
        <property name="repeatInterval" value="2000" />
    </bean>

    <!-- 總管理類 如果將lazy-init='false'那么容器啟動就會執行調度程序 -->
    <bean id="startQuertz" lazy-init="false" autowire="no" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <!-- 管理trigger -->
        <property name="triggers">
            <list>
                <ref bean="simpleTrigger" />
            </list>
        </property>
    </bean>
</beans>

綜上:定時任務的基本配置完成。

三、兩種方法的說明

使用QuartzJobBean,需要繼承。而使用MethodInvokeJobDetailFactoryBean則需要指定targetObject(任務實例)和targetMethod(實例中要執行的方法)

后者優點是無侵入,業務邏輯簡單,一目了然,缺點是無法持久化(目前還不太清楚這點!)

從我使用的經驗來說,我更推薦的第一種,其中一個很重要的原因就是因為定時任務中注入相關Service的時候,后者可以直接注入,而前者還需要進行Schedular的替換修改。

  

 


免責聲明!

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



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