前言
因爲自己的畢設項目要用到Quartz,並且在實習工作的時候也是用到了Quartz,所以在這裏進行總結。
Quartz是一個任務調度框架。比如你遇到這樣的問題:
- 想每月25號,信用卡自動還款
- 每天自動生成報表,併發郵箱給某某人。
- 每個小時自動去查詢當前系統的在線人數
這些問題總結起來就是:在某一個有規律的時間點幹某件事。並且時間的觸發的條件可以非常複雜
(比如每月最後一個工作日的17:50),複雜到需要一 個專門的框架來幹這個事。 Quartz就是來
幹這樣的事,你給它一個觸發條件的定義,它負責到了時間點,觸發相應的Job起來幹活。
一、Quartz概述
1.1 Quartz簡介
- 官網上解釋說,quartz是開源且具有豐富特性的”任務調度庫”,能夠集成於任何的java應用,
小到獨立的應用,大至電子商業系統。 - quartz能夠創建亦簡單亦複雜的調度,以執行上十、上百,甚至上萬的任務。任務job被定義
爲標準的java組件,能夠執行任何你想quartz調度框架包含許多企業級的特性,如JTA事務、
集羣的支持。要實現的功能。 - Quartz是一個完全由Java編寫的開源任務調度的框架,通過觸發器設置作業定時運行規則,
控製作業的運行時間。其中quartz集羣通過故障切換和負載平衡的功能,能給調度器帶來高可
用性和伸縮性。主要用來執行定時任務,如:定時發送信息、定時生成報表等等。 - 簡而言之,quartz就是基於java實現的任務調度框架,用於執行你想要執行的任何任務。
其次,quartz也支持.Net平臺。
1.2 Quart特點
- 簡單易用,調度功能強大
支持豐富多樣的調度方法,可以滿足各種常規及 特殊需求 - 靈活性
作爲Spring默認的調度框架,支持任務和調度的多種組合方式,支持調度數據的多種存儲方式 - 分佈式和集羣能力
伸縮性,高可用性,負載均衡
二、Quartz體系結構概述
Quartz的核心主要包括三部分:作業(Job)、觸發器(Trigger)和調度器(Scheduler),
其中Scheduler是整個系統框架的心臟和靈魂。調度器作爲作業的總指揮,觸發器作爲作業的操作者,
作業爲應用的功能模塊。
其關係如下圖所示:
Job爲作業的接口,爲任務調度的對象。
JobDetail用來描述Job的實現類及其它相關的靜態信息。
Trigger做爲作業的定時管理工具,一個Trigger只能對應一個作業實例,
而一個作業實例可對應多個觸發器。Scheduler做爲定時任務容器,是quartz最上層的東西,它提攜了所有觸發
器和作業,使它們協調工作,每個Scheduler都存有JobDetail和Trigger的
註冊,一個Scheduler中可以註冊多個JobDetail和多個Trigger。
2.1 Job(作業或者任務)
- Job是一個接口,只有一個方法void execute(JobExecutionContext context),
JobExecutionContext類提供了調度上下文的各種信息。每次執行該Job均重新創建
一個Job實例。 JobExecutionContext類
JobExecutionContext類提供了調度上下文的各種信息,如獲取執行中的JobDetail實例
和執行完成後的Trigger對象。當Scheduler決定什麼時候執行Job的時候,他會傳
JobExecutionContext給Job;JobExecutionContext包含了Quartz的運行環境和Job本身
的明細數據,相當於ServletContext一樣。舉例:
public class DDNJob implements Job{
public void execute(JobExecutionContext arg0) throws JobExecutionException {
perform();
}
public void perform(){ //執行報表統計入口函數
//業務邏輯
System.out.println("自動DDN預授權開始執行-------------執行時間:"+new Date());
}
}
- 注:DDNJob類爲需要定時執行的類,execute爲定時執行的方法。一個定時任務對應一個Job實現類。
2.2 JobDetail
- Quartz在每次執行Job時,都重新創建一個Job實例,所以它不直接接受一個Job的實例,相反
它接收一個Job實現類,以便運行時通過newInstance()的反射機制實例化Job。因此需要通過一
個類來描述Job的實現類及其它相關的靜態信息,如Job名字、描述、關聯監聽器等信息,
JobDetail承擔了這一角色。JobDetail 用來保存我們作業的詳細信息。一個JobDetail
可以有多個Trigger,但是一個Trigger只能對應一個JobDetail。
JobDetail jobDetail = new JobDetail("myJob","myGroup",DDNJob.class)
說明:
myJob:job 名
myGroup:job 組(爲'null'時,使用缺省的組sched.DEFAULT_GROUP)
DDNJob.class:要被執行的Java類。
- 運用spring集成的MethodInvokingJobDetailFactoryBean時spring能自動生成
符合quartz要去的JobDetail。
Spring中applicationContext.xml配置如下:
<!-- detail任務描述 -->
<bean name="DDNDetail"
class="com.mangocity.mpm.common.autoDDN.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" value="DDNJob" />
<property name="concurrent" value="false"/>(併發執行)
<property name="shouldRecover" value="true"/>
</bean>
2.3 Trigger(觸發器)
1)概述
- Trigger是一個類,描述觸發Job執行的時間觸發規則。主要有SimpleTrigger和
CronTrigger這兩個子類。 - 僅需觸發一次或者以固定時間間隔週期執行,SimpleTrigger是最適合的選擇;
而CronTrigger則 可以通過Cron表達式定義出各種複雜時間規則的調度方案:
如每早晨9:00執行,週一、週三、週五下午5:00執行等。
2)常見的觸發器屬性
使用 TriggerKey 追蹤定位一個觸發器,使用TriggerBuilder創建觸發器時設置各個屬性
- jobKey
- startTime 在起始時間範圍類開始觸發
- endTime 在超過這個時間範圍後,這個觸發器不再有效。
3)SimpleTrigger
- SimpleTrigger特性
start-time 啓動時間
end-time 結束時間
repeat count 重複次數:整型, SimpleTrigger.REPEAT_INDEFINITELY(-1)表示無限循環
repeat interval 重複間隔,如果太短會照成多個實例併發執行
4)SimpleTrigger舉例
- 指定時間執行,沒有重複
SimpleTrigger trigger = (SimpleTrigger) newTrigger()
.withIdentity("trigger1", "group1")
.startAt(new Date()) // some Date
.build();
- 指定時間執行,重複10次,每次間隔10秒
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger3", "group1")
.startAt(new Date()) // 如果開始時間沒有給出,那麼就以當前時間
.withSchedule(simpleSchedule()
.withIntervalInSeconds(10)
.withRepeatCount(10)) // 注意,重複10次將總共11觸發
.forJob(job) // identify job with handle to its JobDetail itself
.build();
- 創建未來指定時間
SimpleTrigger trigger = (SimpleTrigger) newTrigger()
.withIdentity("trigger5", "group1")
.startAt(DateBuilder.futureDate(10, DateBuilder.IntervalUnit.SECOND)) // 開始時間是未來10秒
.forJob(job)
.build();
DateBuilder : 常用的時間生成,如 下一個整點,未來5秒等
- 從當前時間開始,每隔5分鐘執行一次,一直循環,直到22:00:00結束
trigger = newTrigger()
.withIdentity("trigger7", "group1")
.withSchedule(simpleSchedule()
.withIntervalInMinutes(5)
.repeatForever())
.endAt(dateOf(22, 0, 0)) //失效時間,未指定開始時間則按當前時間
.build();
- 開始時間爲下一個整點:00:00,間隔兩小時執行一次,永遠循環
trigger = newTrigger()
.withIdentity("trigger8") // 沒有指定組,將在默認組
.startAt(evenHourDate(null)) // 獲取下一個整點,如現在是0:24,獲取到的時間是: 1:00:00
.withSchedule(simpleSchedule()
.withIntervalInHours(2)
.repeatForever())
.build();
scheduler.scheduleJob(trigger, job);
5)CronTrigger 表達式觸發器
以日曆作爲對象描述執行時間,而不是按 simpleTrigger 那樣簡單的循環間隔或則指定時間,
如 每週五中午,每個工作日等。但是和 simpleTrigger 一樣也能指定開始時間和失效時間。
由7個子表達式來描述日程安排的細節:
- Seconds
- Minutes
- Hours
- Day-of-Month : 自然月中的日期
- Month
- Day-of-Week : 一週中的第幾天,與Day-of-Month互斥
- Year (optional field)
比如:每週三 12:00:00 : 0 0 12 ? * WED
通配符: 一般都能作用於所有字段,除非特殊說明
2.4 Scheduler(調度器)
- Scheduler就是Quartz的大腦,所有任務都是由它來設施。
Schduelr包含一個兩個重要組件: JobStore和ThreadPool。
JobStore
JobStore是會來存儲運行時信息的,包括Trigger,Schduler,JobDetail,業務鎖等。
它有多種實現RAMJob(內存 實現),JobStoreTX(JDBC,事務由Quartz管理),JobStoreCMT
(JDBC,使用容器事 務),ClusteredJobStore(集羣實現)、TerracottaJobStore。- ThreadPool
ThreadPool就是線程池,Quartz有自己的線程池實現。所有任務的都會由線程池執行。