1. 使用quartz
在開始使用scheduler前厂财,首先使用
SchedulerFactory
創(chuàng)建一個
SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory();
Scheduler sched = schedFact.getScheduler();
sched.start();
// define the job and tie it to our HelloJob class
JobDetail job = newJob(HelloJob.class)
.withIdentity("myJob", "group1")
.build();
// Trigger the job to run now, and then every 40 seconds
Trigger trigger = newTrigger()
.withIdentity("myTrigger", "group1")
.startNow()
.withSchedule(simpleSchedule()
.withIntervalInSeconds(40)
.repeatForever())
.build();
// Tell quartz to schedule the job using our trigger
sched.scheduleJob(job, trigger);
2. Quartz Api jobs 和 trigger
2.1 Quartz Api
- [x] Scheduler
- [x] Job
- [x] JobDetail
- [x] Trigger
- [x] JobBuilder
- [x] TiggerBuilder
JobBuilder
TriggerBuilder
SimpleScheduleBulder
import static org.quartz.JobBuilder.*;
import static org.quartz.SimpleScheduleBuilder.*;
import static org.quartz.CronScheduleBuilder.*;
import static org.quartz.CalendarIntervalScheduleBuilder.*;
import static org.quartz.TriggerBuilder.*;
import static org.quartz.DateBuilder.*;
不同的ScheduleBuilder類有自己的方法定義schedules類型
比如DateBuilder類包含各種易于構(gòu)造java.util的方法熊咽。指定時間點的日期實例
2.2 Jobs and triggers
job interface
一個Job需要實現(xiàn)job 接口
package org.quartz;
public interface Job {
public void execute(JobExecutionContext context)
throws JobExecutionException;
}
當job的trigger觸發(fā)時,execute(..)方法被==scheduler’s==的一個工作線程執(zhí)行续誉。JobExecutionContext內(nèi)含有job的運行信息:執(zhí)行它的Scheduler,觸發(fā)它的Trigger,JobDetail 和其他一些items。
JobDetail對象是由Quartz客戶機(您的程序)在將作業(yè)添加到調(diào)度器時創(chuàng)建的织咧。它包含作業(yè)的各種屬性設(shè)置,以及JobDataMap漠秋,可用于存儲作業(yè)類的給定實例的狀態(tài)信息笙蒙。它本質(zhì)上是作業(yè)實例的定義,并將在下一課中進一步詳細討論庆锦。
觸發(fā)器對象用于觸發(fā)作業(yè)的執(zhí)行(或“觸發(fā)”)捅位。當您希望調(diào)度作業(yè)時,您將實例化觸發(fā)器并“優(yōu)化”其屬性,以提供您希望的調(diào)度艇搀。觸發(fā)器也可能與JobDataMap關(guān)聯(lián)——這對于將參數(shù)傳遞給特定于觸發(fā)器觸發(fā)的作業(yè)非常有用尿扯。Quartz附帶了一些不同的觸發(fā)器類型,但是最常用的類型是SimpleTrigger和CronTrigger焰雕。
如果您需要“一次性”執(zhí)行(在給定的時間點只執(zhí)行一個作業(yè))衷笋,或者需要在給定的時間點觸發(fā)一個作業(yè),并讓它重復N次矩屁,兩次執(zhí)行之間的延遲為T辟宗,那么SimpleTrigger非常有用。如果您希望基于類似日歷的時間表進行觸發(fā)吝秕,例如“每個星期五泊脐、中午”或“每個月的第10天10:15”,CronTrigger非常有用烁峭。
為什么是工作和觸發(fā)器?許多作業(yè)調(diào)度程序沒有作業(yè)和觸發(fā)器的獨立概念容客。有些人將“作業(yè)”簡單地定義為執(zhí)行時間(或調(diào)度)和一些小型作業(yè)標識符。其他的類似于Quartz的工作和觸發(fā)器對象的結(jié)合约郁。在開發(fā)Quartz時缩挑,我們認為在計劃和按照計劃執(zhí)行的工作之間創(chuàng)建一個分離是有意義的。這(在我們看來)有許多好處鬓梅。
例如调煎,作業(yè)可以獨立于觸發(fā)器創(chuàng)建和存儲在作業(yè)調(diào)度器中,而且許多觸發(fā)器可以與相同的作業(yè)關(guān)聯(lián)己肮。這種松散耦合的另一個好處是士袄,可以配置在相關(guān)觸發(fā)器過期后仍然保留在調(diào)度器中的作業(yè),以便以后可以重新調(diào)度它們谎僻,而不必重新定義它們娄柳。它還允許您修改或替換觸發(fā)器,而不必重新定義其關(guān)聯(lián)的作業(yè)艘绍。
2.3 Identities
3. more about job and trigger
使用jobbuilder
import static org.quartz.JobBuilder.*;
上一章節(jié)我們簡單的定義了一個job
// define the job and tie it to our HelloJob class
JobDetail job = newJob(HelloJob.class)
.withIdentity("myJob", "group1") // name "myJob", group "group1"
.build();
// Trigger the job to run now, and then every 40 seconds
Trigger trigger = newTrigger()
.withIdentity("myTrigger", "group1")
.startNow()
.withSchedule(simpleSchedule()
.withIntervalInSeconds(40)
.repeatForever())
.build();
// Tell quartz to schedule the job using our trigger
sched.scheduleJob(job, trigger);
來看一下HelloJob的定義
public class HelloJob implements Job {
public HelloJob() {
}
public void execute(JobExecutionContext context)
throws JobExecutionException
{
System.err.println("Hello! HelloJob is executing.");
}
}
3.1 JobDataMap
JobDataMap 可以用來存儲任意大小的數(shù)據(jù)赤拒,(在數(shù)據(jù)庫中存儲為Blob格式的數(shù)據(jù)類型),實現(xiàn)了java map并添加了常用的方法來存儲和檢索原始類型數(shù)據(jù)。
// define the job and tie it to our DumbJob class
JobDetail job = newJob(DumbJob.class)
.withIdentity("myJob", "group1") // name "myJob", group "group1"
.usingJobData("jobSays", "Hello World!")
.usingJobData("myFloatValue", 3.141f)
.build();
在job執(zhí)行期間取出jobDataMap中的數(shù)據(jù)
public class DumbJob implements Job {
public DumbJob() {
}
public void execute(JobExecutionContext context)
throws JobExecutionException
{
JobKey key = context.getJobDetail().getKey();
JobDataMap dataMap = context.getJobDetail().getJobDataMap();
String jobSays = dataMap.getString("jobSays");
float myFloatValue = dataMap.getFloat("myFloatValue");
System.err.println("Instance " + key + " of DumbJob says: " + jobSays + ", and val is: " + myFloatValue);
}
}
從JobExecutionContext’s取出merged后的jobDataMap
public class DumbJob implements Job {
public DumbJob() {
}
public void execute(JobExecutionContext context)
throws JobExecutionException
{
JobKey key = context.getJobDetail().getKey();
JobDataMap dataMap = context.getMergedJobDataMap(); // Note the difference from the previous example
String jobSays = dataMap.getString("jobSays");
float myFloatValue = dataMap.getFloat("myFloatValue");
ArrayList state = (ArrayList)dataMap.get("myStateData");
state.add(new Date());
System.err.println("Instance " + key + " of DumbJob says: " + jobSays + ", and val is: " + myFloatValue);
}
}
3.2 Job State and Concurrency
- [x] @DisallowConcurrentExecution
- [x] @PersistJobDataAfterExecution
3.3 Other Attributes Of Jobs
- [x] Durability
- [x] RequestsRecovery
3.4 JobExecutionException
4. More about Triggers
4.1 Common Trigger Attributes
- [x] jobKey 標示身份
- [x] startTime:表明trigger什么時候開始起作用诱鞠,對于一些類型的trigger來說挎挖,startTime到了就會執(zhí)行;而有一些只是簡單表明了什么時間點開始schedule航夺,比如您可以在1月份存儲一個帶有時間表的觸發(fā)器蕉朵,例如“每個月的第5天”,如果startTime屬性設(shè)置為4月1日阳掐,那么在第一次觸發(fā)之前還有幾個月的時間始衅,明白了吧冷蚂。
- [x] endTime:表明任務(wù)執(zhí)行的截止日期,舉個栗子:一個帶有“每個月的第5天”和7月1日結(jié)束時間的觸發(fā)器將在6月5日最后一次觸發(fā)汛闸。
4.2 Priority
.withPriority(int triggerPriority)
有時蝙茶,項目中可能有許多triggers需要執(zhí)行,而你的Quartz thread pool是有限的诸老,不能保證在同一時間下所有的trigger在執(zhí)行的時候都能獲取到線程資源執(zhí)行任務(wù)隆夯,因此有時候設(shè)置priority是有必要的,優(yōu)先級越高的越先獲取到線程資源别伏。
priority需要設(shè)置為正整數(shù)蹄衷,默認為5
只有在同一時間下,priority參數(shù)才有作用畸肆,10:11的優(yōu)先級永遠比10:20的高
被恢復的任務(wù)的優(yōu)先級高于origin trigger的
4.3 Misfire Instructions
trigger 可能因為Quartz’s thread pool 沒有足夠的線程執(zhí)行trigger或因為scheduler被關(guān)閉而錯過了它的執(zhí)行時間
4.4 Calendars
此calender非java.util.Calendar
calendar對于從觸發(fā)器的觸發(fā)計劃中排除時間塊非常有用宦芦。例如宙址,您可以創(chuàng)建一個觸發(fā)器轴脐,該觸發(fā)器在每個工作日上午9:30觸發(fā)作業(yè),然后添加一個日歷抡砂,這個日歷用來排除了所有業(yè)務(wù)假期時間塊大咱。
package org.quartz;
public interface Calendar {
public boolean isTimeIncluded(long timeStamp);
public long getNextIncludedTime(long timeStamp);
}
注意,方法的參數(shù)都是毫秒格式的時間戳注益,意味著日歷可以“劃分”出一毫秒那么短的時間段碴巾;
Quartz的實現(xiàn)類org.quartz.impl下有豐富多樣的Calendar;
AnnualCalendar 年歷
CronCalendar cron 日歷
DailyCalendar 每日日歷
HolidayCalendar 假日日歷
MonthlyCalendar 月歷
WeeklyCalendar 周歷
日歷必須通過addCalendar(..)方法實例化并注冊到調(diào)度程序丑搔。如果您使用HolidayCalendar厦瓢,在實例化它之后,需要使用它的addExcludedDate(Date Date)方法來剔除指定的時間啤月,舉個栗子:
calendar example
HolidayCalendar cal = new HolidayCalendar();
cal.addExcludedDate( someDate );
cal.addExcludedDate( someOtherDate );
sched.addCalendar("myHolidays", cal, false);
Trigger t = newTrigger()
.withIdentity("myTrigger")
.forJob("myJob")
.withSchedule(dailyAtHourAndMinute(9, 30)) // execute job daily at 9:30
.modifiedByCalendar("myHolidays") // but not on holidays
.build();
// .. schedule job with trigger
Trigger t2 = newTrigger()
.withIdentity("myTrigger2")
.forJob("myJob2")
.withSchedule(dailyAtHourAndMinute(11, 30)) // execute job daily at 11:30
.modifiedByCalendar("myHolidays") // but not on holidays
.build();
// .. schedule job with trigger2
5. SimpleTrigger
如果需要在特定的時間點精確執(zhí)行job一次煮仇,或者在特定的時間點執(zhí)行job,然后在特定的時間間隔內(nèi)重復執(zhí)行job谎仲,==使用simpleTrigger==比如浙垫,你想讓trigger在2015年1月13日上午11:23:54準時fire,或者你想讓它在那個時間fire郑诺,然后每十秒鐘再fire五次夹姥。
然后你會發(fā)現(xiàn)==simpleTrigger==主要有==startTime==,==endTime==,==repeat count==,==repeat interval==這幾個屬性
repeat count 可為0,或正整數(shù)辙诞,或==SimpleTrigger.REPEAT_INDEFINITELY==
repeat interval 必須大于等于0辙售,為0可能導致重復觸發(fā)
==Quartz’s DateBuilder==便于創(chuàng)建tigger 的fire時間(在startTime和endTime內(nèi))
如果指定了endtime tigger會在startTime和endTime區(qū)間內(nèi)重復執(zhí)行job,這樣你可以自定在此區(qū)間內(nèi)執(zhí)行次數(shù)為==REPEAT_INDEFINITELY==或者設(shè)置一個比較大的執(zhí)行次數(shù)(遠遠超出endtime到來所能夠的執(zhí)行次數(shù))
使用TriggerBuilder構(gòu)建simpleTrigger
import static org.quartz.TriggerBuilder.*;
import static org.quartz.SimpleScheduleBuilder.*;
import static org.quartz.DateBuilder.*:
5.1 指定時間點執(zhí)行一次
SimpleTrigger trigger = (SimpleTrigger) newTrigger()
.withIdentity("trigger1", "group1")
.startAt(myStartTime) // some Date
.forJob("job1", "group1") // identify job with name, group strings
.build();
5.2 指定時間點開始執(zhí)行飞涂,然后沒10秒鐘執(zhí)行一次圾亏,共執(zhí)行10次
trigger = newTrigger()
.withIdentity("trigger3", "group1")
.startAt(myTimeToStartFiring) // if a start time is not given (if this line were omitted), "now" is implied
.withSchedule(simpleSchedule()
.withIntervalInSeconds(10)
.withRepeatCount(10)) // note that 10 repeats will give a total of 11 firings
.forJob(myJob) // identify job with handle to its JobDetail itself
.build();
5.3 未來5分鐘執(zhí)行一次
trigger = (SimpleTrigger) newTrigger()
.withIdentity("trigger5", "group1")
.startAt(DateBuilder.futureDate(5, IntervalUnit.MINUTE)) // use DateBuilder to create a date in the future
.forJob(myJobKey) // identify job with its JobKey
.build();
5.4 現(xiàn)在開始執(zhí)行十拣,每5分鐘執(zhí)行一次一直到22:00點結(jié)束執(zhí)行
trigger = newTrigger()
.withIdentity("trigger7", "group1")
.withSchedule(simpleSchedule()
.withIntervalInMinutes(5)
.repeatForever())
.endAt(dateOf(22, 0, 0))
.build();
5.5 下個小時開始時開始執(zhí)行,每2小時執(zhí)行一次志鹃,直到永遠
trigger = newTrigger()
.withIdentity("trigger8") // because group is not specified, "trigger8" will be in the default group
.startAt(DateBuilder.evenHourDate(null)) // get the next even-hour (minutes and seconds zero ("00:00"))
.withSchedule(simpleSchedule()
.withIntervalInHours(2)
.repeatForever())
// note that in this example, 'forJob(..)' is not called
// - which is valid if the trigger is passed to the scheduler along with the job
.build();
scheduler.scheduleJob(trigger, job);
花點時間好好熟悉一下==TriggerBuilder==和==SimpleScheduleBuilder==的可用方法
==請注意夭问,TriggerBuilder(和Quartz的其他生成器)通常會為未顯式設(shè)置的屬性選擇一個合理的值。如果不調(diào)用startAt(..)曹铃,則假定當前時間(立即)缰趋。==
5.6 SimpleTrigger Misfire Instructions
SimpleTrigger有幾個指令,可以用來通知Quartz在發(fā)生==miessFire==時應(yīng)該做什么陕见。這些指令被定義為SimpleTrigger本身上的常量
MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY
MISFIRE_INSTRUCTION_FIRE_NOW
MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT
MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT
MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT
MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT
前面的章節(jié)已經(jīng)講述了所有的trigger都有==Trigger.MISFIRE_INSTRUCTION_SMART_POLICY==這個也是默認值
trigger = newTrigger()
.withIdentity("trigger7", "group1")
.withSchedule(simpleSchedule()
.withIntervalInMinutes(5)
.repeatForever()
.withMisfireHandlingInstructionNextWithExistingCount())
.build();
6. CronTrigger
CronTrigger通常比SimpleTrigger要更有用秘血,如果需要一個基于類似日歷的概念(而不是根據(jù)==SimpleTrigger==的精確指定間隔)的job觸發(fā)計劃。
使用CronTrigger评甜,您可以指定諸如“每周五中午”灰粮、“每周五和周日上午9:30”、甚至“每周一忍坷、三粘舟、五周一上午9:00到10:00之間的每5分鐘”之類的解雇時間表。
CronTrigger和SimpleTrigger一樣可以指定==startTime==和==endTime==來指定任務(wù)執(zhí)行時間區(qū)間佩研。
6.1 Cron Expressions
- [x] Seconds
- [x] Minutes
- [x] Hours
- [x] Day-of-Month
- [x] Month
- [x] Day-of-Week
- [x] Year (optional field)
一個完整的cron表達式是一個字符串柑肴,比如==0 0 12 ? * WED==意味著每周三的下午12:00
單個子表達式可以包含范圍和/或列表。比如旬薯,上面的==WED==中的==DAY OF WEEK==字段可以替換為==MON-FRI==晰骑、==MON,WED==,==FRI==,甚至==MON-WED,SAT==绊序。
==DAY OF WEEK==字段中的 ==*== 顯然意味著==一周中的每一天==硕舆。
所有字段都有一組可以指定的有效值。這些值是非常符合常理的骤公。例如秒和分鐘的數(shù)值0到59抚官,小時的數(shù)值0到23。一個月的天數(shù)可以是1-31天淋样,但是你需要注意一個月有多少天!==Months==可以指定值0到11之間,或通過使用字符串==JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV and DEC==,==Days-of-Week==之間可以指定值1和7(1 =周日)或通過使用字符串的==SUN, MON, TUE, WED, THU, FRI and SAT==耗式。
字符' / '可用于指定值的增量。例如趁猴,如果在==Minutes==字段中輸入==0/15==刊咳,意思是“每隔15分鐘,從0分鐘開始”儡司。如果您在分鐘字段中使用“3/20”娱挨,它將意味著“每20分鐘,從第3分鐘開始”,換句話說捕犬,它與在分鐘字段中指定==3,23,43==相同跷坝。請注意酵镜,==/35==并不意味著==每35分鐘==,它的意思是==每個小時中的35分鐘,從0分鐘開始==柴钻,或者換句話說淮韭,與指定==0,35==相同。
==?== 字符可以用于月中的日和星期中的日字段
“L”字符可以用于月中的日期和星期中的日期字段贴届。這個字符==last==的簡寫靠粪,但是在這兩個字段中含義不同。例如毫蚓,==DAY OF MONTH== 字段中的值“L”表示“月份的最后一天” ==1月31日==占键,==非閏年2月28日==。如果單獨在==DAT OF WEEK==字段中使用元潘,它的意思就是==7==或==SAT==畔乙。但是如果用在==DAY OF WEEK==字段指定值得后面,它表示“一個月的最后一個xxx日”——例如“6L”或“FRIL”都表示“一個月的最后一個星期五”翩概。您還可以指定從該月最后一天開始的偏移量牲距,例如“L-3”,它表示日歷月的第三到最后一天氮帐。當使用“L”選項時嗅虏,需要注意不要指定列表或值的范圍洛姑,會得到混亂或意外的結(jié)果上沐。
==W==用于指定最接近給定日期的工作日(星期一至星期五)。例如楞艾,如果指定==15W==作為月份字段的值参咙,其含義是:“到本月15日最近的工作日”。
==#==用于指定每月第==n==個工作日硫眯。例如蕴侧,==6#3==或==FRI#3==在==DAY OF WEEK==字段中的值表示“一個月的第三個星期五”。
6.2 Example Cron Expressions
- [x] ==“0 0/5 * * * ?”== 每五分鐘
- [x] ==“0 0/5 * * * ?”== 每五分鐘后的第10秒
- [x] ==“0 30 10-13 ? * WED,FRI”== 每周三两入、周五的10:30净宵、11:30、12:30和13:30
- [x] ==“0 0/30 8-9 5,20 * ?”== 每月的5號至20號的8點到10點間沒隔30分鐘執(zhí)行一次裹纳,注意==trigger==不會再10:00am執(zhí)行择葡,僅會在8:00,8:30,9:00,9:30時間段執(zhí)行;
6.3 Building CronTriggers
==CronTrigger==實例可以通過==TriggerBuilder==構(gòu)建trigger的主要屬性,再通過==CronScheduleBuilder==構(gòu)建==CronTrigger==的指定屬性
import static org.quartz.TriggerBuilder.*;
import static org.quartz.CronScheduleBuilder.*;
import static org.quartz.DateBuilder.*:
6.3.1 創(chuàng)建一個trigger在每天的上午8點到下午5點每間隔2分鐘觸發(fā)一次
trigger = newTrigger()
.withIdentity("trigger3", "group1")
.withSchedule(cronSchedule("0 0/2 8-17 * * ?"))
.forJob("myJob", "group1")
.build();
6.3.2 創(chuàng)建一個trigger在每天的上午10:42執(zhí)行一次
trigger = newTrigger()
.withIdentity("trigger3", "group1")
.withSchedule(dailyAtHourAndMinute(10, 42))
.forJob(myJobKey)
.build();
或者
trigger = newTrigger()
.withIdentity("trigger3", "group1")
.withSchedule(cronSchedule("0 42 10 * * ?"))
.forJob(myJobKey)
.build();
6.3.3 創(chuàng)建一個trigger在每周三的上午10:42執(zhí)行一次剃氧,并指定時區(qū)
trigger = newTrigger()
.withIdentity("trigger3", "group1")
.withSchedule(weeklyOnDayAndHourAndMinute(DateBuilder.WEDNESDAY, 10, 42))
.forJob(myJobKey)
.inTimeZone(TimeZone.getTimeZone("America/Los_Angeles"))
.build();
或者
trigger = newTrigger()
.withIdentity("trigger3", "group1")
.withSchedule(cronSchedule("0 42 10 ? * WED"))
.inTimeZone(TimeZone.getTimeZone("America/Los_Angeles"))
.forJob(myJobKey)
.build();
6.4 CronTrigger Misfire Instructions
下面的執(zhí)行可以告知==Quartz==當CronTrigger錯過執(zhí)行時該干點啥敏储,以下指令作為靜態(tài)常量存儲在==CronTrigger==中
CronTrigger 中的misfire指令靜態(tài)常量
MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY
MISFIRE_INSTRUCTION_DO_NOTHING
MISFIRE_INSTRUCTION_FIRE_NOW
所有的trigger 都擁有指令==Trigger.MISFIRE_INSTRUCTION_SMART_POLICY==,并且這個指令也是所有trigger的默認misfire類型朋鞍,不過在==CronTrigger==中被替換為==MISFIRE_INSTRUCTION_FIRE_NOW==
創(chuàng)建一個==CronTrigger==并指定 simple schedule 中的misfire 指令
trigger = newTrigger()
.withIdentity("trigger3", "group1")
.withSchedule(cronSchedule("0 0/2 8-17 * * ?")
..withMisfireHandlingInstructionFireAndProceed())
.forJob("myJob", "group1")
.build();
7. TriggerListeners and JobListeners
trigger 事件監(jiān)聽 job 事件監(jiān)聽已添,==TriggerListeners==trigger的監(jiān)聽事件妥箕,==JobListeners==job的監(jiān)聽事件;
7.1 TriggerListener 接口
包括 trigger fire 和 trigger misfire
public interface TriggerListener {
public String getName();
public void triggerFired(Trigger trigger, JobExecutionContext context);
public boolean vetoJobExecution(Trigger trigger, JobExecutionContext context);
public void triggerMisfired(Trigger trigger);
public void triggerComplete(Trigger trigger, JobExecutionContext context,
int triggerInstructionCode);
}
7.2 JobListener 接口
job 相關(guān)的事件主要包括job即將被執(zhí)行和job已經(jīng)執(zhí)行完畢
public interface JobListener {
public String getName();
public void jobToBeExecuted(JobExecutionContext context);
public void jobExecutionVetoed(JobExecutionContext context);
public void jobWasExecuted(JobExecutionContext context,
JobExecutionException jobException);
}
7.3 配置自己的監(jiān)聽器
只要實現(xiàn)==org.quartz.TriggerListener== 或者 ==org.quartz.JobListener interface==更舞,便實現(xiàn)了自己的監(jiān)聽器畦幢,然后把監(jiān)聽器注冊到==scheduler==就可以使用了,前提你要給你的監(jiān)聽器起個名字
除了簡單實現(xiàn)上面這兩個接口外缆蝉,你也可以實現(xiàn)==JobListenerSupport==或==TriggerListenerSupport==來實現(xiàn)對自己感興趣的trigger 和 job 進行監(jiān)聽
使用==Matcher==就可以指定希望哪些==Jobs/Triggers==接收到事件
7.3.1 執(zhí)行job添加jobListener
scheduler.getListenerManager().addJobListener(myJobListener, KeyMatcher.jobKeyEquals(new JobKey("myJobName", "myJobGroup")));
需要導入的類
import static org.quartz.JobKey.*;
import static org.quartz.impl.matchers.KeyMatcher.*;
import static org.quartz.impl.matchers.GroupMatcher.*;
import static org.quartz.impl.matchers.AndMatcher.*;
import static org.quartz.impl.matchers.OrMatcher.*;
import static org.quartz.impl.matchers.EverythingMatcher.*;
...etc.
7.3.2 上面的例子也可以這樣寫
scheduler.getListenerManager().addJobListener(myJobListener, jobKeyEquals(jobKey("myJobName", "myJobGroup")));
7.3.3 給指定組下的所有job添加listener
scheduler.getListenerManager().addJobListener(myJobListener, jobGroupEquals("myJobGroup"));
7.3.4 給指定兩組的job添加listener
scheduler.getListenerManager().addJobListener(myJobListener, or(jobGroupEquals("myJobGroup"), jobGroupEquals("yourGroup")));
7.3.5 給所有的job添加listener
scheduler.getListenerManager().addJobListener(myJobListener, allJobs());
8. SchedulerListeners
除了Scheduler本身的一些通知事件外呛讲,==SchedulerListeners== 和 ==TriggerListeners==,==JobListeners==的功能很相似
事件主要包括job/trigger的添加返奉,移除贝搁,==scheduler==的一些異常通知,==scheduler==的==shutdown==通知等芽偏;
8.1 SchedulerListener
public interface SchedulerListener {
public void jobScheduled(Trigger trigger);
public void jobUnscheduled(String triggerName, String triggerGroup);
public void triggerFinalized(Trigger trigger);
public void triggersPaused(String triggerName, String triggerGroup);
public void triggersResumed(String triggerName, String triggerGroup);
public void jobsPaused(String jobName, String jobGroup);
public void jobsResumed(String jobName, String jobGroup);
public void schedulerError(String msg, SchedulerException cause);
public void schedulerStarted();
public void schedulerInStandbyMode();
public void schedulerShutdown();
public void schedulingDataCleared();
}
==SchedulerListeners== 使用 ==scheduler’s ListenerManager==注冊監(jiān)聽器
添加
scheduler.getListenerManager().addSchedulerListener(mySchedListener);
移除
scheduler.getListenerManager().removeSchedulerListener(mySchedListener);
9. Job Stores
jobstore 用來存儲scheduler下的job雷逆、trigger、calender等==work data==污尉,選擇合適的store方式非常重要
9.1 內(nèi)存存儲
任務(wù)信息存儲在內(nèi)容中膀哲,scheduler 被關(guān)閉或機器故障后,數(shù)據(jù)就丟了
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
9.2 JDBCJobStore
支持的數(shù)據(jù)庫有==Oracle, PostgreSQL, MySQL, MS SQLServer, HSQLDB, and DB2==被碗,需要創(chuàng)建quartz單獨的數(shù)據(jù)庫表某宪,表結(jié)構(gòu)語句在==“docs/dbTables”==下,默認的事務(wù)類型==JobStoreTX==(最常見的)锐朴,如果你需要quartz和你的應(yīng)用服務(wù)使用同一個事務(wù)呵晚,需要使用事務(wù)類型為==JobStoreCMT==,這樣的化漓雅,quartz會讓應(yīng)用服務(wù)來管理quartz事務(wù)胆筒;
9.2.1 配置quartz 使用JobStoreTx
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
9.2.2 配置數(shù)據(jù)庫委托
數(shù)據(jù)庫委托信息在包==org.quartz.impl.jdbcjobstore==下
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
9.2.3 quartz數(shù)據(jù)庫表的前綴
org.quartz.jobStore.tablePrefix = QRTZ_
9.2.4 配置數(shù)據(jù)源
org.quartz.jobStore.dataSource = myDS
可以指定==org.quartz.jobStore.useProperties==為==true==,這樣的就是以==String==類型存儲==JobDataMaps==信息酱酬,而不是==BLOB==
9.3 TerracottaJobStore
TerracottaJobStore可以是集群壶谒,也可以是單點的,不過都可以為作業(yè)數(shù)據(jù)提供存儲介質(zhì)膳沽,因為數(shù)據(jù)存儲在Terracotta服務(wù)器中汗菜,因此在應(yīng)用程序重新啟動期間是持久存儲的,挑社。它的性能比JDBCJobStore使用數(shù)據(jù)庫要好得多(大約好一個數(shù)量級)陨界,但是比RAMJobStore慢得多。
9.3.1 配置使用TerracottaJobStore
org.quartz.jobStore.class = org.terracotta.quartz.TerracottaJobStore
org.quartz.jobStore.tcConfigUrl = localhost:9510
10. Configuration, Resource Usage and SchedulerFactory
在使用quartz之前需要配置如下東西:
- [x] 線程池 ThreadPool
- [x] 任務(wù)存儲方式 JobStore
- [x] 數(shù)據(jù)庫(如果必要的化)DataSources
- [x] 調(diào)度器 Scheduler
ThreadPool
指定了任務(wù)同時執(zhí)行的并發(fā)數(shù)量滔灶,通常來說5個就夠了普碎,官方建議