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