學習筆記_spring任務調度

最近看Spring,發現Spring有任務調度管理功能,能很好地解決以上的問題。於是我們決定將定時程序遷移到Spring中。下面就結合我們這次程序的遷移,介紹一下如何使用Spring的任務調度。

在討論Spring的任務調度前,我們先談談Spring。仔細探究Spring,你會發現很多有趣的東西。第一,Spring中並沒有多少新技術,就如AOP這些概念,其實於上個****早已存在了。 MS的操作系統 window2000及以後版本的MTS(Microsoft Transaction Server,事務服務器)就是使用AOP實現的。至於更早的如TUXEDO之類的交易中間件,我想在其中也應該有着AOP理念。第二,Spring並沒有實現很多功能,它只是集成了很多功能。如數據層,它可以集成Hibernate或iBATIS;MVC框架,它可以集成Struts;郵件收發,它集成了JavaMail;包括下面我們將要討論的Spring任務調度,它也是集成了第三方的任務調度類庫:JDK自帶的Timer類庫或第三方的Quartz類庫。Spring只是做了個抽象的接口和集成,方便我們調用。Sping看起來很龐大,可以做很多事情,其實它什麼事都不做!這可能也是它的“輕量級”含義所在的吧。

在Spring中,使用JDK的Timer類庫來做任務調度功能不是很方便,關鍵它不可以象cron服務那樣可以指定具體年、月、日、時和分的時間。你只能將時間通過換算成微秒後傳給它。如任務是每天執行一次,則需要在spring中如下配置:

<bean id="scheduledTask"class= "org.springframework.scheduling.timer.ScheduledTimerTask">

<!--程序啓動後開始執行任務的延遲時間 -->

<property name="delay"value="0" />

<!--每隔一天【一天=24×60×60×1000微秒】執行一次-->

<property name="period"value="86400000" />

<!--業務統計報表bean -->

<property name="timerTask"ref="businessReport" />

</bean>

其中period就是一天的微秒數。如果每月1日運行一次,那就複雜了,不知如何配置。因爲月份有大、小月之分,每月的微秒數都不一樣。

而Quartz類庫不但有着上述JDK的Timer類庫類似的配置,更重要的,它還有着類似於unix的cron服務的配置。因此,在遷移中我們採用了Quartz類庫的接口。

Quartz可以通過兩種方式來調度程序:一是使用Spring提供的MethodInvokingJobDetailFactoryBean代理類,Quartz通過該代理類直接調度任務類的某個函數;二是任務類繼承並實現Quartz接口,Quartz通過該接口進行調度。

如果採用第一種方式,即由Quartz直接調度任務類的某個接口,那麼,業務類是不必進行任何修改的。我們的業務類大概如下

public class BusinessReport {

public void perform(){ //執行報表統計入口函數

//業務邏輯

}

}

第一步,在Spring配置文件中增加本業務類

<bean id=" businessReport "class=" BusinessReport "/>

第二步,定義任務。在Spring配置文件中配置代理類MethodInvokingJobDetailFactoryBean,定義任務的詳細信息。

<bean id=" reportTask " class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">

<property name=" targetObject" ref=" businessReport " />

<property name=" targetMethod" value=" perform " />

<property name=" concurrent "value=" false " />

</bean>

這個配置告訴Spring,我們的任務是執行id爲businessReport的bean中的perform函數。其中參數concurrent告訴Spring,不要併發運行這個任務。

第三步,配置一個觸發器。在Spring配置文件中配置觸發器類CronTriggerBean 。

<bean id="cronTrigger"class="org.springframework.scheduling.quartz.CronTriggerBean">

<property name="jobDetail"ref=" reportTask " />

<property name="cronExpression"value="0 0 1 1 * ?" />

</bean>

觸發器將告訴Quartz兩件事:在何時觸發任務、觸發哪個任務。其中屬性參數cronExpression爲調度時間,格式和unix上的crontab類似,具體見下表1。“0 0 1 1 * ?”表示每月1日凌晨1點運行。其中問號表示忽略該位置(星期)上的值。屬性參數jobDetail指向具體的任務bean:reportTask 。如果你有多個任務,每個任務的觸發時間都不一樣,則你可以在此配置多個不同的觸發器。

表1. cronExpression的時間格式

位置

含義

1

秒(0–59)

2

分(0–59)

3

時(0–23)

4

日(1–31)

5

月(1–12)

6

星期(SUN–SAT or 1–7)

7

年(可選, 1970–2099)

第四步,配置一個調度器。在Spring配置文件中配置調度器類SchedulerFactoryBean。

<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">

<property name="triggers">

<list>

<ref bean="cronTrigger" />

</list>

</property>

</bean>

該調度器用於管理觸發器。只有在調度器中列表出現的觸發器才被Quartz系統調度執行。至此,所有的配置已完成,任務已能正常跑了。

如果採用第二種方式,那業務類是要進行小小的修改。整個過程如下。

第一步,修改上述的業務類,修改如下:

public class BusinessReport implementsorg.quartz.Job {//繼承quartz 的job接口

//實現job接口的execute函數,在其中簡單調用perform()函數就可以了。

public voidexecute(org.quartz.JobExecutionContext context){

//執行報表統計入口函數

perform()

}

//其它的保持不變。

public void perform(){ //執行報表統計入口函數

//業務邏輯

}

}

修改過程比較簡單,只增加了兩三行代碼。

第二步,定義任務。在Spring配置文件中配置如下任務的詳細信息。

<bean name=" reportTask "class= "org.springframework.scheduling.quartz.JobDetailBean">

<property name="jobClass"value=" BusinessReport " />

</bean>

此配置告訴Quartz,我們的任務類的名字爲BusinessReport。在定時觸發時,Quartz會利用該類名來創建任務的實例,並執行該實例的execute方法。

第三、第四步與第一種的調度方式相應的步驟一樣。

按第二種方式,整個Spring的配置文件如下:

<!DOCTYPE beans PUBLIC"-//SPRING//DTD BEAN//EN"

"http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

<!-- 我們的任務 -->

<bean name=" reportTask "class= "org.springframework.scheduling.quartz.JobDetailBean">

<property name="jobClass"value=" BusinessReport " />

</bean>

<!-- 觸發器 -->

<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">

<!-- 指向我們的任務 -->

<property name="jobDetail"ref=" reportTask " />

<!-- 每月1日凌晨1點運行 -->

<propertyname="cronExpression" value="0 0 1 1 * ?" />

</bean>

<!-- 調度器 -->

<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">

<property name="triggers">

<list><!-- 觸發器列表-->

<ref bean="cronTrigger" />

</list>

</property>

</bean>

</beans>

按照上述步驟,整個遷移十分順利,程序也穩定運行。

到Quartz的官方網站溜達了一下,發現Quartz還有不少強大的功能,包括任務的持久化、事務化、容錯、負載均衡等功能。但這些功能暫時在項目中都用不上。

Spring的任務調度管理就介紹到這裏。Spring還有很多其它實用的功能,如果我們能拿過來用在項目中,不但加快開發進度,而且還可以保證項目質量。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章