Quartz入門指南

Quartz入門指南html

看到官網的教程對於新手來講不夠全面和連貫,所以結合本身的使用過程寫下這個入門指南,用以解惑。本文基於Quartz2.2.2版本。請注意,本文爲了易於上手,省略了許多重要的概念,建議閱讀Quartz2.2.x官方教程java

1、 安裝與配置

下載、解壓後,進入lib文件夾,將全部jar文件放入項目指定目錄,而後在BuildPath中添加。Jar包共6個,以下所示。api

 

Quartz的運行依賴於log4j.xmlquartz.properties這兩個配置文件。關於它們的配置方法,請查閱各自官網。咱們偷個懶,就用下載包中的吧。在quartz-2.2.2-distribution\quartz-2.2.2\examples\example11目錄下找到這倆文件,拷貝到項目指定位置,我是專門新建了個Config文件夾。而後在Eclipse中右擊該目錄,選擇Build Path -> Use as Source Folder,便可。oracle

 

2、 Quartz框架

2.1 基本概念

Quartz中最核心的組件是任務、觸發器和調度器。任務就是你指定的完成指定業務的執行單元。觸發器規定了任務的執行時間、重複週期和頻率。調度器將任務和觸發器鏈接起來,它實際上管理着一個線程池和全部的任務和觸發器,並進行統一的調度。框架

2.2 觸發器

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做爲週期單位時,若是起始日期是在某月的最後一天,好比131日,那麼下一個激活日在228日,之後全部的激活日都在當月的28日。若是你要嚴格限制在每個月的最後一天激活,那你須要使用cronTrigger。不受夏令時引發的時鐘偏移影響。url

DailyTimeIntervalTrigger:在給定的時間窗口或指定的星期以秒、分鐘、小時爲週期進行重複。好比,天天早上8:0011:00之間,每隔72分鐘激活;或者每週的週一到週五9:2016:47之間,每隔23分鐘激活。注意它的名稱Daily,所以重複週期必須在1天之內,不能爲星期,月之類的。spa

2.3 構造器

Quartz提供了構造器風格的API用於構造調度相關的實體。從官方給出的示例代碼能夠看出,各類實體都是使用構造器來生成的。Quartz的構造器主要有如下幾種:

TriggerBuilder:實例化觸發器。

JobBuilder:構造JobDetail

ScheduleBuilder:構造調度器,前面介紹的4種觸發器分別有一個對應的調度器構造器。

DateBuilder:構造一個日期。

2.3.1 TriggerBuilder

經過其成員函數,可以定義觸發器的開始、中止時間、job的各類屬性及ScheduleBuilder

具備4個子類,分別是SimpleScheduleBuilderCronScheduleBuilderCalendarIntervalScheduleBuilderDailyTimeIntervalScheduleBuilder,對應4種觸發器。在每一個子類中,其成員函數均對其特有屬性進行配置。好比說,SimpleScheduleBuilder具備repeatForever()repeatHourlyForTotalCount(int count, int hours) 等方法來設置其重複週期和次數。其他方法再也不具體介紹,請查閱javadoc。

2.3.2 JobBuilder

用於構造JobDetail,可想而知,它的成員方法均用於設置JobDetail的各類屬性,好比descriptiondataMapidentity等等。

2.3.3 ScheduleBuilder

具備4個子類,分別爲CalendarIntervalScheduleBuilder, CronScheduleBuilder, DailyTimeIntervalScheduleBuilder, SimpleScheduleBuilder,對應4個觸發器,分別用於構造具體的某一種觸發器。好比說,構造SimpleTrigger時,須要調用SimpleScheduleBuildersimpleSchedule() build()方法;,構造CronTrigger時,須要調用CronScheduleBuildercronSchedule(String cronExpression) build()方法。其中,build()是由父類繼承的,用於生成觸發器。

2.3.4 DateBuilder

用於根據各類條件來構造一個日期。好比,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) 等等。

3、 示例代碼

 

使用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());
    }
}

 

 

 

4、 觸發器選用實例

到這裏,你應該對各類觸發器的功能和參數設置方法有了必定的瞭解,可是仍然建議你看完如下實例,由於有一些你可能沒有想到的問題。

4.1 每隔10秒

使用SimpleTrigger 就好。

4.2 每隔90分鐘

使用SimpleTriggerCalendarIntervalTrigger均可以。

4.3 每隔1天

使用CalendarIntervalTrigger CronTrigger。不建議使用SimpleTrigger ,由於夏令時的存在可能會使今天14點的24小時之後是明天的13點或者15點。

4.4 每隔2天

使用CalendarIntervalTrigger。不建議使用SimpleTrigger,緣由如上。也不建議使用CronTrigger。試想一下,你的CronExpress的「日」這一位可能會寫成「2/2」這樣,表示每個月的2號開始,每一個2天。那麼在7月的30號激活後,下一次激活是在8月的2號,這個間隔就是3天而不是2天(7月有31天)。

4.5 每隔1周

使用CronTrigger或者CalendarIntervalTrigger均可以。

4.6 每隔2周

與「2天」一樣的緣由,使用CronTrigger會有問題,所以建議使用CalendarIntervalTrigger

4.7 每隔1個月

使用CronTriggerCalendarIntervalTrigger

4.8 每隔5個月

使用CalendarIntervalTrigger。與「2天」一樣的緣由,使用CronTrigger會有問題。試想一下,你的CronExpress的「月」這一位可能會寫成「3/5」這樣,那麼8月激活後,下一個激活點在第二年3月,這個間隔就成了7個月。

5、 參考資料

Quartz Scheduler Example Programs and Sample Code

Quartz Enterprise Job Scheduler 2.2.1 API

相關文章
相關標籤/搜索