Quartz入門指南html
看到官網的教程對於新手來講不夠全面和連貫,所以結合本身的使用過程寫下這個入門指南,用以解惑。本文基於Quartz2.2.2版本。請注意,本文爲了易於上手,省略了許多重要的概念,建議閱讀Quartz2.2.x官方教程。java
下載、解壓後,進入lib文件夾,將全部jar文件放入項目指定目錄,而後在BuildPath中添加。Jar包共6個,以下所示。api
Quartz的運行依賴於log4j.xml和quartz.properties這兩個配置文件。關於它們的配置方法,請查閱各自官網。咱們偷個懶,就用下載包中的吧。在」quartz-2.2.2-distribution\quartz-2.2.2\examples\example11」目錄下找到這倆文件,拷貝到項目指定位置,我是專門新建了個Config文件夾。而後在Eclipse中右擊該目錄,選擇」Build Path -> Use as Source Folder」,便可。oracle
Quartz中最核心的組件是任務、觸發器和調度器。任務就是你指定的完成指定業務的執行單元。觸發器規定了任務的執行時間、重複週期和頻率。調度器將任務和觸發器鏈接起來,它實際上管理着一個線程池和全部的任務和觸發器,並進行統一的調度。框架
Quartz包含4種觸發器,其中SimpleTrigger 和CronTrigger多是最經常使用的,官方文檔中對它們進行了詳細的解釋(請查看Quartz2.2.x官方教程,這裏再也不詳述)。另外兩種雖然只在javadoc中有隻言片語的介紹,但在特定場景下仍具備不可替代性。ide
SimpleTrigger :在指定時間激活,而後以指定週期重複指定的次數。好比,14:30分開始,每隔10秒激活一次,重複100次。函數
CronTrigger:經過一個cron表達式來指定任務激活的年月日星期時分秒,以及重複週期。cron表達式具備必定的語法結構,能夠達成很是強大的效果。不受夏令時引發的時鐘偏移影響。ui
CalendarIntervalTrigger 根據一個給定的日曆時間進行重複,能夠設置啓動時間。它能夠完成 SimpleTrigger(好比每月,由於月不是一個肯定的秒數)和CronTrigger(好比5個月,由於5個月並非12個月的公約數)不能完成的一些任務。注意,使用month做爲週期單位時,若是起始日期是在某月的最後一天,好比1月31日,那麼下一個激活日在2月28日,之後全部的激活日都在當月的28日。若是你要嚴格限制在每個月的最後一天激活,那你須要使用cronTrigger。不受夏令時引發的時鐘偏移影響。url
DailyTimeIntervalTrigger:在給定的時間窗口或指定的星期以秒、分鐘、小時爲週期進行重複。好比,天天早上8:00到11:00之間,每隔72分鐘激活;或者每週的週一到週五9:20到16:47之間,每隔23分鐘激活。注意它的名稱Daily,所以重複週期必須在1天之內,不能爲星期,月之類的。spa
Quartz提供了構造器風格的API用於構造調度相關的實體。從官方給出的示例代碼能夠看出,各類實體都是使用構造器來生成的。Quartz中的構造器主要有如下幾種:
TriggerBuilder:實例化觸發器。
JobBuilder:構造JobDetail。
ScheduleBuilder:構造調度器,前面介紹的4種觸發器分別有一個對應的調度器構造器。
DateBuilder:構造一個日期。
經過其成員函數,可以定義觸發器的開始、中止時間、job的各類屬性及ScheduleBuilder。
具備4個子類,分別是SimpleScheduleBuilder,CronScheduleBuilder,CalendarIntervalScheduleBuilder,DailyTimeIntervalScheduleBuilder,對應4種觸發器。在每一個子類中,其成員函數均對其特有屬性進行配置。好比說,SimpleScheduleBuilder具備repeatForever(),repeatHourlyForTotalCount(int count, int hours) 等方法來設置其重複週期和次數。其他方法再也不具體介紹,請查閱javadoc。
用於構造JobDetail,可想而知,它的成員方法均用於設置JobDetail的各類屬性,好比description,dataMap,identity等等。
具備4個子類,分別爲CalendarIntervalScheduleBuilder, CronScheduleBuilder, DailyTimeIntervalScheduleBuilder, SimpleScheduleBuilder,對應4個觸發器,分別用於構造具體的某一種觸發器。好比說,構造SimpleTrigger時,須要調用SimpleScheduleBuilder的simpleSchedule() 和build()方法;,構造CronTrigger時,須要調用CronScheduleBuilder的cronSchedule(String cronExpression) 和build()方法。其中,build()是由父類繼承的,用於生成觸發器。
用於根據各類條件來構造一個日期。好比,dateOf(int hour,int minute, int second, int dayOfMonth, int month, int year),atHourOfDay(int atHour),evenHourDate(Date date),nextGivenMinuteDate(Date date, int minuteBase) ,tomorrowAt(int hour, int minute, int second),validateDayOfMonth(int day) 等等。
使用SimpleTrigger的代碼以下所示:
public void SimpleTriggerTest() throws Exception { SchedulerFactory sf = new StdSchedulerFactory(); Scheduler sched = sf.getScheduler(); JobDetail job1 = newJob(SimpleJob.class).withIdentity("job1", "group1") .build(); Trigger trigger1 = newTrigger()//TriggerBuilder.newTrigger() .startAt(DateBuilder.dateOf(10, 10, 10, 13, 3, 2016)) .withSchedule( simpleSchedule().repeatSecondlyForTotalCount(5, 2))//<SBT extends T> TriggerBuilder<SBT> withSchedule(ScheduleBuilder<SBT> schedBuilder) .build(); Date ft = sched.scheduleJob(job1, trigger1); sched.start(); }
有幾個地方須要說明:
1.TriggerBuilder.newTrigger()。這是構造器,因爲在頭文件中已經使用了」import static org.quartz.TriggerBuilder.newTrigger;」靜態引用因此不須要體現類名TriggerBuilder。startAt是它的方法,能夠指定觸發器的開始時間。
2.withSchedule方法的參數是一個schedBuilder,返回一個TriggerBuilder。
3.repeatSecondlyForTotalCount方法用於設置重複週期和次數,它是由simpleSchedule這個構造器提供的,而不是最終生成的simpleTrigger提供的,simpleTrigger沒有相應方法。
完整的示例代碼以下:
QuartzDemo.java
import static org.quartz.CalendarIntervalScheduleBuilder.calendarIntervalSchedule; import static org.quartz.CronScheduleBuilder.cronSchedule; import static org.quartz.DailyTimeIntervalScheduleBuilder.dailyTimeIntervalSchedule; import static org.quartz.JobBuilder.newJob; import static org.quartz.SimpleScheduleBuilder.simpleSchedule; import static org.quartz.TriggerBuilder.newTrigger; import java.util.Calendar; import java.util.Date; import java.util.HashSet; import java.util.Set; import org.quartz.DateBuilder; import org.quartz.JobDetail; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.SchedulerFactory; import org.quartz.TimeOfDay; import org.quartz.Trigger; import org.quartz.DateBuilder.IntervalUnit; import org.quartz.impl.StdSchedulerFactory; public class QuartzDemo { public void CalendarIntervalTriggerTest() throws SchedulerException{ SchedulerFactory sf = new StdSchedulerFactory(); Scheduler sched = sf.getScheduler(); JobDetail job = newJob(SimpleJob.class).withIdentity("job", "group1").build(); //每隔5個月,在指定日期和時間激活任務 Trigger trigger = newTrigger().startAt(DateBuilder.dateOf(10, 10, 10, 13, 3, 2016)).withSchedule(calendarIntervalSchedule().withInterval(5, IntervalUnit.MONTH)).build(); Date ft = sched.scheduleJob(job, trigger); sched.start(); } public void CronTriggerTest() throws SchedulerException{ SchedulerFactory sf = new StdSchedulerFactory(); Scheduler sched = sf.getScheduler(); JobDetail job = newJob(SimpleJob.class).withIdentity("job2", "group1").build(); //每一個週一到週五,早上8點-11點的整點激活任務,從明天早上9點開始 Trigger trigger = newTrigger().startAt(DateBuilder.tomorrowAt(9, 0, 0)).withIdentity("trigger2", "group1").withSchedule(cronSchedule("* 0 8-11 ? * MON-FRI")) .build(); Date ft = sched.scheduleJob(job, trigger); sched.start(); } public void DailyTimeIntervalTriggerTest() throws SchedulerException{ SchedulerFactory sf = new StdSchedulerFactory(); Scheduler sched = sf.getScheduler(); JobDetail job = newJob(SimpleJob.class).withIdentity("job2", "group1").build(); Set<Integer> daysOfWeek = new HashSet<Integer>(); daysOfWeek.add(Calendar.SATURDAY); daysOfWeek.add(Calendar.SUNDAY); //每一個週末,20點-20點30分,每隔1分鐘激活1次 Trigger trigger = newTrigger().startNow().withSchedule(dailyTimeIntervalSchedule().onDaysOfTheWeek(daysOfWeek).withInterval(1, IntervalUnit.MINUTE).withRepeatCount(5).startingDailyAt(new TimeOfDay(20,00)).endingDailyAt(new TimeOfDay(20,30))) .build(); Date ft2 = sched.scheduleJob(job, trigger); sched.start(); } public void SimpleTriggerTest() throws Exception { SchedulerFactory sf = new StdSchedulerFactory(); Scheduler sched = sf.getScheduler(); JobDetail job = newJob(SimpleJob.class).withIdentity("job1", "group1") .build(); //在指定時間,按照指定週期和次數重複激活 Trigger trigger = newTrigger()//TriggerBuilder.newTrigger() .startAt(DateBuilder.dateOf(10, 10, 10, 13, 3, 2016)) .withSchedule( simpleSchedule().repeatSecondlyForTotalCount(5, 2))//<SBT extends T> TriggerBuilder<SBT> withSchedule(ScheduleBuilder<SBT> schedBuilder) .build(); Date ft = sched.scheduleJob(job, trigger); sched.start(); } public static void main(String[] args) throws Exception { QuartzDemo example = new QuartzDemo(); //example.SimpleTriggerTest(); //example.DailyTimeIntervalTriggerTest(); //example.CalendarIntervalTriggerTest(); example.CronTriggerTest(); } }
SimpleJob.java
import java.util.Date; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; public class SimpleJob implements Job{ public SimpleJob() { } public void execute(JobExecutionContext context) throws JobExecutionException { System.out.printf("SimpleJob executed at %s%n", new Date()); } }
到這裏,你應該對各類觸發器的功能和參數設置方法有了必定的瞭解,可是仍然建議你看完如下實例,由於有一些你可能沒有想到的問題。
使用SimpleTrigger 就好。
使用SimpleTrigger或CalendarIntervalTrigger均可以。
使用CalendarIntervalTrigger 或CronTrigger。不建議使用SimpleTrigger ,由於夏令時的存在可能會使今天14點的24小時之後是明天的13點或者15點。
使用CalendarIntervalTrigger。不建議使用SimpleTrigger,緣由如上。也不建議使用CronTrigger。試想一下,你的CronExpress的「日」這一位可能會寫成「2/2」這樣,表示每個月的2號開始,每一個2天。那麼在7月的30號激活後,下一次激活是在8月的2號,這個間隔就是3天而不是2天(7月有31天)。
使用CronTrigger或者CalendarIntervalTrigger均可以。
與「2天」一樣的緣由,使用CronTrigger會有問題,所以建議使用CalendarIntervalTrigger。
使用CronTrigger或CalendarIntervalTrigger。
使用CalendarIntervalTrigger。與「2天」一樣的緣由,使用CronTrigger會有問題。試想一下,你的CronExpress的「月」這一位可能會寫成「3/5」這樣,那麼8月激活後,下一個激活點在第二年3月,這個間隔就成了7個月。
Quartz Scheduler Example Programs and Sample Code