平常都是使用 JDK 自帶的 TimerTask 與 Timer 來完成需要 Scheduling 的工作, 抑或是利用 Shell script 並透過 crontab/at 命令來完成. 剛剛 Google 了一下, 原來還有一個 Quartz 套件提供更強大與相容於 Java 的 Scheduling 利器:
底下以一個門外漢的角度來看看怎麼使用這個套件.
Hello Quartz:
要學一樣語言或是套件, 免不了 Say Hello. 底下的範例代碼會以 40 秒為周期執行 HelloJob 上的 execute(...) 方法; 並於 5 分鐘後結束 Scheduling:
- package demo;
- import static org.quartz.JobBuilder.newJob;
- import static org.quartz.SimpleScheduleBuilder.simpleSchedule;
- import static org.quartz.TriggerBuilder.newTrigger;
- import org.apache.log4j.PropertyConfigurator;
- import org.quartz.JobDetail;
- import org.quartz.Scheduler;
- import org.quartz.SchedulerException;
- import org.quartz.Trigger;
- import org.quartz.impl.StdSchedulerFactory;
- public class QuartzTest {
- public static void main(String args[])
- {
- try {
- // Configuration of log4j
- PropertyConfigurator.configure("log4j.properties");
- // Grab the Scheduler instance from the Factory
- Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
- // and start it off
- scheduler.start();
- // define the job and tie it to our HelloJob class -> JobBuilder.newJob()
- JobDetail job = newJob(HelloJob.class)
- .withIdentity("job1", "group1")
- .build();
- // Trigger the job to run now, and then repeat every 40 seconds -> TriggerBuilder.newTrigger()
- Trigger trigger = newTrigger()
- .withIdentity("trigger1", "group1")
- .startNow()
- .withSchedule(simpleSchedule()
- .withIntervalInSeconds(40)
- .repeatForever())
- .build();
- // Tell quartz to schedule the job using our trigger
- scheduler.scheduleJob(job, trigger);
- Thread.sleep(1000*60*5); // Sleep 5 minutes
- scheduler.shutdown();
- }
- catch (SchedulerException se)
- {
- se.printStackTrace();
- }
- catch (Exception e)
- {
- }
- }
- }
- trigger = newTrigger()
- .withIdentity("trigger3", "group1")
- .withSchedule(cronSchedule("0 42 10 * * ?"))
- .forJob(myJobKey)
- .build();
- trigger = newTrigger()
- .withIdentity("trigger3", "group1")
- .withSchedule(dailyAtHourAndMinute(10, 42))
- .forJob(myJobKey)
- .build();
The Quartz API:
Quartz API 常見的使用介面包括:
Scheduler 的生命週期從使用 SchedulerFactory 建立 Scheduler 物件開始; 並在呼叫該物件的 shutdown() 方法結束. 建立 Scheduler 物件後, 你可以透過上面的方法添加或移除 Jobs 與Triggers 並執行 scheduling-related 操作 (如 pausing a trigger). 但這一切的動作都只會在執行 Scheduler 物件上的 start() 方法後才會生效!
Quartz 提供許多的 "builder" 類別, 並透過這些類別定義一些 Domain Specific Language (or DSL, also sometimes referred to as a "fluent interface"), 而這些 "builder" 類別在前面範例出現的代碼片段如下:
- // define the job and tie it to our HelloJob class -> JobBuilder.newJob()
- JobDetail job = newJob(HelloJob.class)
- .withIdentity("job1", "group1")
- .build();
- // Trigger the job to run now, and then repeat every 40 seconds -> TriggerBuilder.newTrigger()
- Trigger trigger = newTrigger()
- .withIdentity("trigger1", "group1")
- .startNow()
- .withSchedule(simpleSchedule()
- .withIntervalInSeconds(40)
- .repeatForever())
- .build();
- // Tell quartz to schedule the job using our trigger
- scheduler.scheduleJob(job, trigger);
- 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.*;
底下是一些使用的範例代碼:
- Date now = new Date();
- System.out.printf("\t[Info] Now is: %s!\n", now);
- System.out.printf("\t[Info] dateOf(10,10,10)->%s\n", dateOf(10,10,10));
- System.out.printf("\t[Info] evenHourDate(now)->%s\n", evenHourDate(now));
- System.out.printf("\t[Info] futureDate(2, DateBuilder.IntervalUnit.DAY)->%s\n", futureDate(2, DateBuilder.IntervalUnit.DAY));
- System.out.printf("\t[Info] tomorrowAt(2,2,2)->%s\n", tomorrowAt(2,2,2));
Jobs and Triggers:
在 Quartz 中的 Job 必須實作 Job 介面, 上面定義了一個需要實作的方法:
- package org.quartz;
- public interface Job {
- public void execute(JobExecutionContext context)
- throws JobExecutionException;
- }
常見 Trigger 介面的種類有 SimpleTrigger 與 CronTrigger. SimpleTrigger 在你只需要執行一次的場合相當方便 (在特定時間點執行); 如果你需要重複執行 N 次並且能夠 delay 指定時間後才開始 scheduling 的話 (such as "every Friday, at noon" or "at 10:15 on the 10th day of every month."), 那 CronTrigger 會是不錯的選擇.
Identities:
Jobs 與 Triggers 都需要一個唯一的 identifying keys 來向 Quartz scheduler 註冊. 而這些 identifying keys 可以被 group 起來, 方便你對這些 Jobs 與 Triggers 進行管理 (such as "reporting jobs" and "maintenance jobs"). 而在 Scheduler 介面定義的方法中, 常見來管理這些註冊的 Jobs 與 Triggers 有:
Supplement:
* Quartz Documentation][u]Quartz Document
* Tutorial Lesson 1: Using Quartz
* Tutorial Lesson 2: The Quartz API, Jobs And Triggers
* Tutorial Lesson 3: More About Jobs & JobDetails
* Tutorial Lesson 4: More About Triggers.
* Tutorial Lesson 5: SimpleTriggers
* Tutorial Lesson 6: CronTriggers
* Tutorial Lesson 7: TriggerListeners & JobListeners
* Tutorial Lesson 8: SchedulerListeners
* Tutorial Lesson 9: JobStores
* Tutorial Lesson 10: Configuration, Resource Usage and SchedulerFactory
* Tutorial Lesson 11: Advanced (Enterprise) Features
* Tutorial Lesson 12: Miscellaneous Features
沒有留言:
張貼留言