Spring定時任務的實現:Quartz
Java任務排程分類
-
從實現的技術上來分類,目前主要有三種技術:
- Java自帶的java.util.Timer類,這個類允許你排程一個java.util.TimerTask任務。使用這種方式可以讓你的程式按照某一個頻度執行,但不能在指定時間執行。一般用的較少,這篇文章將不做詳細介紹。
- 使用Quartz,這是一個功能比較強大的的排程器,可以讓你的程式在指定時間執行,也可以按照某一個頻度執行,配置起來稍顯複雜,稍後會詳細介紹。
- Spring3.0以後自帶的task,可以將它看成一個輕量級的Quartz,而且使用起來比Quartz簡單許多。
-
從作業類的繼承方式來講,可以分為兩類:
- 作業類需要繼承自特定的作業類基類,如Quartz中需要繼承自org.springframework.scheduling.quartz.QuartzJobBean;java.util.Timer中需要繼承自java.util.TimerTask。
- 作業類即普通的java類,不需要繼承自任何基類。
注:個人推薦使用第二種方式,因為這樣所以的類都是普通類,不需要事先區別對待。
-
從任務排程的觸發時機來分,有以下兩種:
- 每隔指定時間則觸發一次,在Quartz中對應的觸發器為:org.springframework.scheduling.quartz.SimpleTriggerBean
- 每到指定時間則觸發一次,在Quartz中對應的排程器為:org.springframework.scheduling.quartz.CronTriggerBean
注:並非每種任務都可以使用這兩種觸發器,如java.util.TimerTask任務就只能使用第一種。Quartz和spring task都可以支援這兩種觸發條件。
對於spring的整合其中的任務,spring提供了幾個類、介面(這些類都實現了Job介面):
org.springframework.scheduling.quartz.QuartzJobBean
org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean.MethodInvokingJob
org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean.StatefulMethodInvokingJob
QuartzJobBean和MethodInvokingJob是無狀態的,StatefulMethodInvokingJob是有狀態的。
1、Scheduler的配置
說明:Scheduler包含一個Trigger列表,每個Trigger表示一個作業。
2、Trigger的配置
<bean id="testTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail" ref="testJobDetail"/>
<property name="cronExpression" value="*/1 * * * * ?"/><!-- 每隔1秒鐘觸發一次 -->
</bean>
說明:
1)Cron表示式的格式:秒 分 時 日 月 周 年(可選)。
欄位名 允許的值 允許的特殊字元
秒 0-59 , - * /
分 0-59 , - * /
小時 0-23 , - * /
日 1-31 , - * ? / L W C
月 1-12 or JAN-DEC , - * /
周幾 1-7 or SUN-SAT , - * ? / L C #
年 (可選欄位) empty, 1970-2099 , - * /
“?”字元:表示不確定的值
“,”字元:指定數個值
“-”字元:指定一個值的範圍
“/”字元:指定一個值的增加幅度。n/m表示從n開始,每次增加m
“L”字元:用在日表示一個月中的最後一天,用在周表示該月最後一個星期X
“W”字元:指定離給定日期最近的工作日(週一到週五)
“#”字元:表示該月第幾個周X。6#3表示該月第3個週五
2)Cron表示式範例:
每隔5秒執行一次:*/5 * * * * ?
每隔1分鐘執行一次:0 */1 * * * ?
每天23點執行一次:0 0 23 * * ?
每天凌晨1點執行一次:0 0 1 * * ?
每月1號凌晨1點執行一次:0 0 1 1 * ?
每月最後一天23點執行一次:0 0 23 L * ?
每週星期天凌晨1點實行一次:0 0 1 ? * L
在26分、29分、33分執行一次:0 26,29,33 * * * ?
每天的0點、13點、18點、21點都執行一次:0 0 0,13,18,21 * * ?
3、JobDetail的配置
<bean id="testJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="testJob"/>
<property name="targetMethod" value="execute"/>
<property name="concurrent" value="false"/>
<!-- 是否允許任務併發執行。當值為false時,表示必須等到前一個執行緒處理完畢後才再啟一個新的執行緒 -->
</bean>
4、業務類的配置
<bean id="testJob" class="com.cjm.web.service.quartz.TestJob"/>
5、業務類原始碼
public class TestJob {
public void execute(){
try{
//.......
}catch(Exception ex){
ex.printStackTrace();
}
}
}
說明:業務類不需要繼承任何父類,也不需要實現任何介面,只是一個普通的java類。
在Spring配置和Quartz整合內容時,有兩點需要注意
1、在<Beans>中不能夠設定default-lazy-init="true",否則定時任務不觸發,如果不明確指明default-lazy-init的值,預設是false。
2、在<Beans>中不能夠設定default-autowire="byName"的屬性,否則後臺會報org.springframework.beans.factory.BeanCreationException錯誤,這樣就不能通過Bean名稱自動注入,必須通過明確引用注入