打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Quartz2.2基础教程

下载和安装


如果是采用maven管理依赖,则依赖配置如下:

  1. <dependency>  
  2.     <groupId>org.quartz-scheduler</groupId>  
  3.     <artifactId>quartz</artifactId>  
  4.     <version>2.2.3</version>  
  5. </dependency>  
  6. <dependency>  
  7.     <groupId>org.quartz-scheduler</groupId>  
  8.     <artifactId>quartz-jobs</artifactId>  
  9.     <version>2.2.3</version>  
  10. </dependency>  
如果不是的话,所需依赖包可以到官网下载http://www.quartz-scheduler.org/downloads/


关键接口


Scheduler


一个scheduler的生命周期是有限的,从通过SchedulerFactory创建开始直到调用它的shutdown()方法。scheduler接口一旦创建,就能添加、移除、和列出job和trigger,并执行另一些与调度相关的操作(例如暂停trigger),然而,在scheduler被start()方法启动前,它不会作用于任何trigger(执行job)。

Job


一个job就是实现了Job接口的类。如下所示,这个接口只有一个简单的方法:
  1. package org.quartz;  
  2.   
  3.   public interface Job {  
  4.   
  5.     public void execute(JobExecutionContext context)  
  6.       throws JobExecutionException;  
  7.   }  
JobExecutionContext对象就是通过这个方法提供job实例的信息,如运行环境,包括scheduler执行的句柄,trigger触发执行的句柄,job的JobDetail对象,和一些其它信息。

JobDetail


JobDetail对象由Quartz客户端(你的程序)在job添加进scheduler的时候创建。这个对象包含了很多job的属性设置,和JobDataMap一样,它能够存储你的job实例的状态信息。JobDetail对象本质上是定义的job实例。

Trigger


trigger对象常常用于触发job的执行(或者触发),当你希望安排一个job,你可以实例化一个trigger,并调整其属性来提供你想要的调度。trigger可能有一个与它们关联的JobDataMap对象。JobDataMap用于传递特定于触发器触发的工作参数。Quartz附带一些不同的触发类型,但是最常用的就是SimpleTrigger和CronTrigger。
SimpleTrigger很方便,如果你需要一次性执行(只是在一个给定时刻执行job),或者如果你需要一个job在一个给定的时间,并让它重复N次,并在执行之间延迟T。
CronTrigger是有用的,如果你想拥有引发基于当前日历时间表,如每个星期五,中午或在每个月的第十天 10:15。

JobBuilder


用于定义/构建已经定义了Job实例的JobDetail实例。

TriggerBuilder


用于定义/构建Trigger实例。

特性


当job和trigger被登记到Quartz scheduler时给出了identifying key。Job和trigger(JobKey和TriggerKey)的key允许它们被放置到group中,group可用于分类组织job和trigger,例如“报表job”和“维护job”。Job或者trigger的identifying key值的name部分在group中必须是唯一的。换句话说,job或trigger的完整的identifying key是由name和group组成。

第一个quartz 程序


  1. import org.quartz.Job;  
  2. import org.quartz.JobExecutionContext;  
  3. import org.quartz.JobExecutionException;  
  4.   
  5. import java.util.Date;  
  6.   
  7. public class HelloJob implements Job {  
  8.   
  9.     /** 
  10.      * 需要一个无参的public构造以便scheduler在它需要的时候可以实例化这个class. 
  11.      */  
  12.     public HelloJob() {  
  13.     }  
  14.   
  15.   
  16.     /** 
  17.      * 要执行的代码 
  18.      * 
  19.      * @param context JobExecutionContext 
  20.      * @throws JobExecutionException 
  21.      */  
  22.     public void execute(JobExecutionContext context) throws JobExecutionException {  
  23.         System.out.println("Hello World! - " + new Date());  
  24.     }  
  25. }  
  1. import org.quartz.DateBuilder;  
  2. import org.quartz.JobBuilder;  
  3. import org.quartz.JobDetail;  
  4. import org.quartz.Scheduler;  
  5. import org.quartz.SchedulerFactory;  
  6. import org.quartz.Trigger;  
  7. import org.quartz.TriggerBuilder;  
  8. import org.quartz.impl.StdSchedulerFactory;  
  9.   
  10. import java.util.Date;  
  11.   
  12. public class SimpleExample {  
  13.   
  14.     public void run() throws Exception {  
  15.   
  16.         System.out.println("------- 初始化 ----------------------");  
  17.   
  18.         // 首先要实例化scheduler  
  19.         SchedulerFactory schedulerFactory = new StdSchedulerFactory();  
  20.         Scheduler scheduler = schedulerFactory.getScheduler();  
  21.   
  22.         System.out.println("------- 初始化完成 -----------");  
  23.   
  24.         // 获取给定时间的下一个完整分钟的时间,例如给定时间 08:13:54 则会反回 08:14:00  
  25.         Date runTime = DateBuilder.evenMinuteDate(new Date());  
  26.   
  27.         System.out.println("------- Job安排 -------------------");  
  28.   
  29.         // 获取job实例  
  30.         JobDetail job = JobBuilder.newJob(HelloJob.class).withIdentity("job1", "group1").build();  
  31.   
  32.         // 在下一轮分钟触发运行  
  33.         Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").startAt(runTime).build();  
  34.   
  35.         // 告诉quartz使用某个trigger执行某个job  
  36.         scheduler.scheduleJob(job, trigger);  
  37.         System.out.println(job.getKey() + " 将会运行于: " + runTime);  
  38.   
  39.         // 启动scheduler  
  40.         scheduler.start();  
  41.   
  42.         System.out.println("------- 开始安排 -----------------");  
  43.   
  44.         System.out.println("------- 等待65秒 -------------");  
  45.         Thread.sleep(65L * 1000L);  
  46.   
  47.         // 关闭scheduler  
  48.         System.out.println("------- 关闭 ---------------------");  
  49.         scheduler.shutdown(true);  
  50.         System.out.println("------- 关闭完成 -----------------");  
  51.     }  
  52.   
  53.     public static void main(String[] args) throws Exception {  
  54.         SimpleExample example = new SimpleExample();  
  55.         example.run();  
  56.     }  
  57. }  

更多关于Job and JobDetail


我们给scheduler一个JobDetail实例,它知道要执行的job的类型,只需提供我们构建JobDetail的job类。每次scheduler执行job,它会在调用它的execute(..)方法之前创建这个类的新实例。当执行完成,job实例的引用被删除,然后垃圾收集器回收实例。这种行为的后果之一是job必须有一个无参数的构造函数(当使用默认JobFactory实现),另一个是在job类上定义状态数据字段没有意义,它们的值在Job执行期间不会被保存。你可能现在想问,我如何为一个job实例提供属性或者配置?我如何在执行job期间追踪状态?
答案就是JobDataMap,它是JobDetail对象的一部分。

JobDataMap


JobDataMap可以用来保存大量那些在job实例执行时你希望得到的 (序列化)数据对象。JobDataMap是Java Map接口的一个实现,并且添加一些便利的方法来存储和检索数据的原始类型。

存放数据
  1. JobDetail job = newJob(DumbJob.class)  
  2.     .withIdentity("myJob", "group1") // name "myJob", group "group1"  
  3.     .usingJobData("jobSays", "Hello World!")  
  4.     .usingJobData("myFloatValue", 3.141f)  
  5.     .build();  

获取数据
  1. public class DumbJob implements Job {  
  2.   
  3.     public DumbJob() {  
  4.     }  
  5.   
  6.     public void execute(JobExecutionContext context)  
  7.       throws JobExecutionException  
  8.     {  
  9.       JobKey key = context.getJobDetail().getKey();  
  10.   
  11.       JobDataMap dataMap = context.getJobDetail().getJobDataMap();  
  12.   
  13.       String jobSays = dataMap.getString("jobSays");  
  14.       float myFloatValue = dataMap.getFloat("myFloatValue");  
  15.   
  16.       System.err.println("Instance " + key + " of DumbJob says: " + jobSays + ", and val is: " + myFloatValue);  
  17.     }  
  18.   }  

trigger也可以有与他们有关的JobDataMap,例如TriggerBuilder.newTrigger().usingJobData。
JobDataMap dataMap = context.getMergedJobDataMap()。这个可以获取到jobDetail和trigger上的所有数据,trigger上相同名字的值将覆盖前者。

更多关于trigger


通用的trigger属性


属性jobKey是trigger启动时将要执行的job的标识。
startTime是trigger第一次生效的时间。值是一个java.util.Date对象,定义了一个给定的日期时间。对于一些类型的trigger来说,trigger会在这个时间准确启动。对于其它类型来说仅仅标志着时间表开始被跟踪。这意味着你可以这样存储一个schedule的trigger,例如一月“每月的第5天执行”,如果startTime属性设置为4月1日,在首次触发前,还要过几个月。
endTime属性表示trigger的计划不再有效。换句话说,一个“每月5号”的trigger,endTime为7月1号,它上次执行的时间就是6月5号。

优先级


有时,当你有很多触发器(或者你得Quartz线程池有很多工作线程),Quartz也许没有足够的资源在同一时间触发所有的trigger。这种情况下,你也许想控制你的哪些触发器可以优先获得Quartz的工作线程。为此,你需要设置trigger的优先级属性。如果N个触发器同一时间触发,但是当前仅有Z和可用的工作线程,前Z个具有高优先级的触发器将首先执行。任何整数,正数或者负数都允许作为优先级。如果你的trigger没有设定优先级它将使用默认的优先级为5。
注意:优先级仅仅在同一时间触发的trigger中才有效。一个在10:59触发的trigger将永远比在11:00触发的trigger先执行。
注意:当触发器被监测到需要恢复时,它的优先级将与原始的优先级相同。

触发失败说明


Trigger另一个重要的属性就是“过时触发指令”。如果因为当前scheduler被关闭或者Quartz的线程池没有可用的线程用来执行job导致当前的触发器错过了触发时间,就是出现错误。不同类型的trigger有不同的失败处理方式。默认情况下,它们使用“智能策略”,其拥有基于trigger类型和配置的动态行为。Scheduler启动时,它将搜索所有失败的持久化的trigger,然后基于它们的失败配置来更新它们。

日历


Quartz日历对象(不是java.util.Calendar对象)能够与在scheduler中定义和存储的trigger时间相关联。日历可用于从trigger的触发计划中排除某些时间。例如,你可以创建一个trigger在工作日的9:30触发,但是排除法定假日。日历可以使任何实现了org.quartz.Calendar接口的序列化对象。注意这些方法的参数类型是long。这是毫秒的时间戳格式。这意味着日历可以“阻挡”精确至一毫秒的时间。最有可能的是你会对“屏蔽”一整天感兴趣。Quartz包括一个org.quartz.impl.HolidayCalendar就是干这个的,非常方便。
日历必须通过addCalendar(..)方法实例化并注册到scheduler中。如果你使用HolidayCalendar,实例化之后,你应该使用它的addExcludedDate(Date date)方法将你想排除在调度器之外的日期添加进去。同一个日历实例可以被多个trigger使用,如下所示:
  1. HolidayCalendar cal = new HolidayCalendar();  
  2. cal.addExcludedDate( someDate );  
  3. cal.addExcludedDate( someOtherDate );  
  4.   
  5. sched.addCalendar("myHolidays", cal, false,false);  
  6.   
  7.   
  8. Trigger t = newTrigger()  
  9.     .withIdentity("myTrigger")  
  10.     .forJob("myJob")  
  11.     .withSchedule(dailyAtHourAndMinute(9, 30)) // execute job daily at 9:30  
  12.     .modifiedByCalendar("myHolidays") // but not on holidays  
  13.     .build();  
  14.   
  15. // .. schedule job with trigger  
  16.   
  17. Trigger t2 = newTrigger()  
  18.     .withIdentity("myTrigger2")  
  19.     .forJob("myJob2")  
  20.     .withSchedule(dailyAtHourAndMinute(11, 30)) // execute job daily at 11:30  
  21.     .modifiedByCalendar("myHolidays") // but not on holidays  
  22.     .build();  
  23.   
  24. // .. schedule job with trigger2  
上面的代码创建了两个触发器,每天都会执行。然而,任何发生在排除日历的触发将被跳过。org.quartz.impl.calendar包提供了许多Calendar的实现,也许可以满足你的需求。
addCalendar(String calName,
                 Calendar calendar,
                 boolean replace,
                 boolean updateTriggers)
                 throws SchedulerException
第一个参数是日历名称
第二个参数是日历实例
第三个参数是是否替换,如果日历名称重复但是replace为false,那么会报异常
第四个参数是是否更新引用了已经存在的日历的trigger,以便使scheduler基于正确的trigger

SimpleTrigger


如果你需要一个job在特定的时间执行一次或者在特定的时间,以特定的间隔执行多次SimpleTrigger能够满足你的需求。例如:你想让一个trigger在2015年1月13号11:23:54分触发,或者你想在那个时间执行,执行5次,每10秒一次。这样描述,你也许不难发现SimpleTrigger的属性:开始时间,结束时间,重复次数,重复间隔。所有这些属性正是你期望的,只有一组与结束时间关联的特殊属性。
重复的次数可以是0,正数或者常数SimpleTrigger.REPEAT_INDEFINITELY。重复的间隔属性必须是0或一个正的长整型,代表毫秒值。注意,间隔为0将导致触发器同时触发“重复次数”这么多次(尽可能接近scheduler的并发管理数)。
如果你还不熟悉Quartz的DateBuilder类,你可能发现依赖于你的开始时间(或结束时间)计算trigger的触发次数很有帮助。
endTIme属性会计算并重写先前设置的重复次数的属性。如果你想创建一个每10秒触发一次的trigger直到一个给定的时刻,这也许会有用,而不必计算开始时间和结束时间间的重复次数,你可以简单的指出结束时间然后使用REPEAT_INDEFINITELY表明重复次数(你甚至可以指定较大的重复次数超过在结束时间到达之前trigger触发的次数)。SimpleTrigger实例通过使用TriggerBuilder(创建trigger的主属性)和SimpleScheduleBuilder(创建SimpleTrigger特殊属性)创建。
注意:如果你不显示的设置属性TriggerBuilder(和其它的quartz创建者)会选取一个合理的值。例如,如果你不调用withIdentity(..)的某个方法,TriggerBuilder将为你的trigger生成一个随机的名字,同样,如果你没有调用startAt(..),则设定为当前的时间(立即执行)。

首先静态引入:
  1. import static org.quartz.TriggerBuilder.*;  
  2. import static org.quartz.SimpleScheduleBuilder.*;  
  3. import static org.quartz.DateBuilder.*:  

创建一个指定时间执行的trigger,没有重复次数
  1. SimpleTrigger trigger = (SimpleTrigger) newTrigger()  
  2.     .withIdentity("trigger1", "group1")  
  3.     .startAt(myStartTime) // some Date  
  4.     .forJob("job1", "group1") // identify job with name, group strings  
  5.     .build();  

在指定的时间创建一个trigger,然后每10秒触发一次,共触发10次
  1. trigger = newTrigger()  
  2.     .withIdentity("trigger3", "group1")  
  3.     .startAt(myTimeToStartFiring)  // if a start time is not given (if this line were omitted), "now" is implied  
  4.     .withSchedule(simpleSchedule()  
  5.         .withIntervalInSeconds(10)  
  6.         .withRepeatCount(10)) // note that 10 repeats will give a total of 11 firings  
  7.     .forJob(myJob) // identify job with handle to its JobDetail itself                     
  8.     .build();  

创建一个触发一次的trigger,5分钟后触发
  1. trigger = (SimpleTrigger) newTrigger()  
  2.     .withIdentity("trigger5", "group1")  
  3.     .startAt(futureDate(5, IntervalUnit.MINUTE)) // use DateBuilder to create a date in the future  
  4.     .forJob(myJobKey) // identify job with its JobKey  
  5.     .build();  

创建一个立即触发的trigger,每5分钟触发一次,直到22:00结束
  1. trigger = newTrigger()  
  2.     .withIdentity("trigger7", "group1")  
  3.     .withSchedule(simpleSchedule()  
  4.         .withIntervalInMinutes(5)  
  5.         .repeatForever())  
  6.     .endAt(dateOf(22, 0, 0))  
  7.     .build();  

建立一个trigger,每小时开始的时候触发,每2小时出发一次,直到永远
  1. trigger = newTrigger()  
  2.     .withIdentity("trigger8") // because group is not specified, "trigger8" will be in the default group  
  3.     .startAt(evenHourDate(null)) // get the next even-hour (minutes and seconds zero ("00:00"))  
  4.     .withSchedule(simpleSchedule()  
  5.         .withIntervalInHours(2)  
  6.         .repeatForever())  
  7.     // note that in this example, 'forJob(..)' is not called  
  8.     //  - which is valid if the trigger is passed to the scheduler along with the job    
  9.     .build();  
  10.   
  11.     scheduler.scheduleJob(trigger, job);  

SimpleTrigger有几个指令,用来通知quartz当触发失败该怎么做。这些指令被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
所有的trigger都有MISFIRE_INSTRUCTION_SMART_POLICY属性可以使用,这个指定对所有的触发器类型都是可用的。
如果使用“智能策略”,SimpleTrigger会基于给定SimpleTrigger实例的配置和状态动态地选择触发的失败指令。SimpleTrigger.updateAfterMisfire()方法的Javadoc解释了这些动态行为的细节。也可以在创建SimpleTrigger时,指定失败指令作为简单scheduler的一部分。
  1. trigger = newTrigger()  
  2.     .withIdentity("trigger7", "group1")  
  3.     .withSchedule(simpleSchedule()  
  4.         .withIntervalInMinutes(5)  
  5.         .repeatForever()  
  6.         .withMisfireHandlingInstructionNextWithExistingCount())  
  7.     .build();  

CronTrigger


Cron是一个UNIX工具,已经存在了很长时间,所以它的调度功能强大且得到证实。CronTrigger使用“cron表达式”。
如果你需要基于类似日历的观念反复触发一个job,而不是使用SimpleTrigger指定一个固定的时间间隔,相对于SimpleTrigger,CronTrigger往往更有用。
使用CronTrigger,你可以指定一个触发计划例如“每周五的中午”,或者“每个工作日上午9:00”,甚至“1月的周一,周三和周五早上9:00至10:00每五分钟”。
即便如此,和SimpleTrigger一样, CronTrigger也有一个startTime指定计划的生效时间也有一个(可选的)endTime指定计划的停止时间。

Cron表达式
Cron表达式用于CronTrigger实例的配置。Cron表达式实际上是由7个子表达式组成,包括秒、分、时、每月的第几天、月、每周的第几天、年(可选字段),用来描述计划安排的细节。这些子表达式使用空格分割。一个完整的cron表达式是一个像这样的字符串“0 0 12 ? WED *”——这代表着“每周三的12:00”。每个子表达式都能包含范围/或列表,例如前面每周的第几天(“WED”)可以替换成“MON-FRI”,“ MON,WED,FRI”,甚至“MON-WED,SAT”。

*
用来选择一个字段上的所有值。例如:分钟字段上的“*”表示“每分钟”。

?
当你需要在允许的两个字段中的一个指定一些值的时候使用。例如,你想让你得trigger在每月的某一天触发(假如,10号),但是不关系在周几发生,你应该在每月的第几天字段上设置“10”,在每周的第几天字段上设置“?”。具体参见下面实例。

-
用于指定范围。例如,小时字段上设置“10-12”表示“10点,11点,12点”。
,
用于指定额外的值。例如,在每周的第几天设置“MON,WED,FRI”表示“周一,周三,周五”。

/
用于指定增量。例如,秒字段上“0/15”表示“0秒,15秒,30秒,45秒”。秒字段上“5/15”表示“5秒,20秒,35秒,50秒”,每月中的第几天设置“1/3”表示“从每月的第一天开始每3天触发一次”。

L
“last”简写,可用在两个字段,每个字段的含义不同。例如,“L”在每月的第几天字段上指的是“每月的最后一天”——1月31号,和非闰年的2月28号。如果用在每周的第几天,就是“7”或者“SAT”的意思。但是如果用在每周第几天的一个值后面,就意味着“每月最后一个星期的第几天”——例如“6L”表示“每月最后一个周五”。你还可以为每月的最后一天指定一个偏移量,例如“L-3”意味着每月倒数第三天。当使用“L”选项时,重要的是不要指定列表或范围值,不然你将得到混乱/不期望的结果。 

W
用来指定距离指定日期最近的工作日(周一至周五)。例如,如果你指定了“15W”在每月第几天的字段上,表示:“离本月15号最近的工作日”。所以,如果15号是周六,trigger将在14号周五触发,如果15号是周日,trigger将在16号周一触发,如果15号是周二,trigger将在15号周二触发。然而如果在每月的第几天字段指定“1W”,而且1号是周六,trigger将会在3号周一触发,它不会跳过月的边界。“W”只能指定每月第几天字段中的一天,不能指定一个范围或列表。

“L”和“W”字符也可以在每月的第几天字段组合成“LW”,表示“每月的最后一个工作日”。

#
用于指定每月中的第几个周几。例如,每周第几天字段上的“6#3”表示“每月的第3个周五”(”6“=周五,”#3“=每月的第3个)。另一个例子:”2#1“=每月的第1个周一,”4#5“每月的第5个周三。注意,如果你指定”#5”,但是该月没有第5个这一周的天数,触发器将不会执行。

注意:月份的英文名和周几的英文是不区分大小写的。MON与mon都是合法的字符。

表达式

含义

0 0 12 * * ?

每天12:00触发

0 15 10 ? * *

每天10:15触发

0 15 10 * * ?

每天10:15触发

0 15 10 * * ? *

每天10:15触发

0 15 10 * * ? 2005

2005年的每天10:15触发

0 * 14 * * ?

每天14:00至14:59每分钟触发

0 0/5 14 * * ?

每天14:00开始至14:55每5分钟触发

0 0/5 14,18 * * ?

每天14:00开始至14:55每5分钟触发,18:00开始至18:55每5分钟触发

0 0-5 14 * * ?

每天14:00开始至14:05每分钟触发

0 10,44 14 ? 3 WED

三月份的每个周三14:10和14:44触发

0 15 10 ? * MON-FRI

每个周一至周五上午10:15触发

0 15 10 15 * ?

每月15号10:15触发

0 15 10 L * ?

每月最后一天10:15触发

0 15 10 L-2 * ?

每月倒数第2天10:15触发

0 15 10 ? * 6L

每月最后一个周五10:15触发

0 15 10 ? * 6L 2002-2005

2002年至2005年每月最后一个周五10:15触发

0 15 10 ? * 6#3

每月第3个周五10:15触发

0 0 12 1/5 * ?

每月的第一天开始,每个第5天12:00触发

0 11 11 11 11 ?

每年11月11号11:11触发


注意:当不指定一周中的第几天和一月中的第几天,你必须在这两个字段之一使用”?”。

首先静态导入:
  1. import static org.quartz.TriggerBuilder.*;  
  2. import static org.quartz.CronScheduleBuilder.*;  
  3. import static org.quartz.DateBuilder.*:  
  1. trigger = new Trigger()  
  2.                    .withIdentity("trigger3", "group1")  
  3.                    .withSchedule(cronSchedule("0 42 10 ? * WED"))  
  4.                    .inTimeZone(TimeZone.getTimeZone("America/Los_Angeles"))  
  5.                    .forJob(myJobKey)  
  6.               .build();  

CronTrigger失败说明
下面的说明可以在CronTrigger失败时用来介绍Quartz信息。这些介绍是CronTrigger自己定义的常量。包括:
MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY
MISFIRE_INSTRUCTION_DO_NOTHING
MISFIRE_INSTRUCTION_FIRE_NOW
所有的trigger都有MISFIRE_INSTRUCTION_SMART_POLICY说明可供使用,这个说明也是所有trigger类型默认的。”智能策略CronTrigger解读为“MISFIRE_INSTRUCTION_FIRE_NOW。CronTrigger.updateAfterMisfire()方法的Javadoc解析了这些行为的细节。
在构建CronTrigger时,你可以指定简单schedule的失败说明。
  1. trigger = newTrigger()  
  2.     .withIdentity("trigger3", "group1")  
  3.     .withSchedule(cronSchedule("0 0/2 8-17 * * ?")  
  4.         ..withMisfireHandlingInstructionFireAndProceed())  
  5.     .forJob("myJob", "group1")  
  6.     .build();  

使用TriggerListener和JobListener


TriggerListener和JobListener


监听器是你基于scheduler中事件的活动创建的对象。就像它们名字所示,TriggerListener接收与trigger有关的事件,JobListener接收与Job有关的事件。
与trigger有关的事件包括trigger触发,trigger触发失败,trigger执行完成(trigger完成job执行完毕)。

org.quartz.TriggerListener接口
  1. publicinterface TriggerListener {  
  2.      public String getName();  
  3.    
  4.      publicvoid triggerFired(Trigger trigger, JobExecutionContext context);  
  5.    
  6.      publicboolean vetoJobExecution(Trigger trigger, JobExecutionContext context);  
  7.    
  8.      publicvoid triggerMisfired(Trigger trigger);  
  9.    
  10.      publicvoid triggerComplete(Trigger trigger, JobExecutionContext context, inttriggerInstructionCode);  
  11. }  

与job有关的时间包括:job即将进行的通知,和job已经完成的通知。
org.quartz.JobListener接口
  1. publicinterface JobListener {  
  2.      public String getName();  
  3.    
  4.      publicvoid jobToBeExecuted(JobExecutionContext context);  
  5.    
  6.      publicvoid jobExecutionVetoed(JobExecutionContext context);  
  7.    
  8.      publicvoid jobWasExecuted(JobExecutionContext context, JobExecutionException jobException);  
  9. }  

创建你自己的监听器
要创建一个监听器,需要简单创建一个实现org.quartz.TriggerListener接口或/和org.quartz.JobListener接口的对象。然后在运行时监听器被注册到scheduler中,并且必须给定一个name(或者确切的说,它们必须能够通过它们的getName()方法给出它们的名字)。为了你的方便,而不需要实现这些接口,你的类还可以继承JobListenerSupport或TriggerListenerSupport并简单的重写你感兴趣的方法。监听器被注册到scheduler的ListenerManager 。
注意:监听器在运行时被注册到scheduler,而不是一直随job和trigger存储在JobStore中。这是因为监听器通常作为你的应用程序的一个集成点。因此,你的应用每次运行,监听器都需要重新注册进scheduler。

下面的示例演示了将感兴趣的JobListener添加进不同类型的job中。以同样的方式添加可用的TriggerListener。
添加一个感兴趣的JobListener到特定的job
scheduler.getListenerManager().addJobListener(myJobListener,KeyMatcher.jobKeyEquals(new JobKey("myJobName", "myJobGroup")));
你可能想使用静态导入导入matcher和key类,这将使你清晰的匹配matcher:
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.
上面的例子将变成:
scheduler.getListenerManager().addJobListener(myJobListener,jobKeyEquals(jobKey("myJobName", "myJobGroup")));
添加一个感兴趣的JobListener到一个指定group的所有job
scheduler.getListenerManager().addJobListener(myJobListener, jobGroupEquals("myJobGroup"));
添加一个感兴趣的JobListener到两个指定的group的所有job
scheduler.getListenerManager().addJobListener(myJobListener, or(jobGroupEquals("myJobGroup"), jobGroupEquals("yourGroup")));
添加一个感兴趣的JobListener到所有job
scheduler.getListenerManager().addJobListener(myJobListener, allJobs());

使用SchedulerListener


SchedulerListener


SchedulerListener和TriggerListener及JobListener很像,除了其接收Scheduler自身事件的通知,而不必与特定的trigger和job相关联。在大量的其他事件中,Scheduler关联的事件包括:
添加一个job或trigger
移除一个trigger或job
Schduler中的一系列错误
Schduler的关闭
SchdulerListner可以是任何实现org.quartz.SchedulerListener接口的对象。

配置


quartz使用quartz.properties文件来配置。它必须位于classpath上。例如:
  1. #============================================================================  
  2. # Configure Main Scheduler Properties    
  3. #============================================================================  
  4.   
  5. org.quartz.scheduler.instanceName: TestScheduler  
  6. org.quartz.scheduler.instanceId: AUTO  
  7.   
  8. org.quartz.scheduler.skipUpdateCheck: true  
  9.   
  10. #============================================================================  
  11. # Configure ThreadPool    
  12. #============================================================================  
  13.   
  14. org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool  
  15. org.quartz.threadPool.threadCount: 3  
  16. org.quartz.threadPool.threadPriority: 5  
  17.   
  18. #============================================================================  
  19. # Configure JobStore    
  20. #============================================================================  
  21.   
  22. org.quartz.jobStore.misfireThreshold: 60000  
  23.   
  24. org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore  
  25.   
  26. #org.quartz.jobStore.class: org.quartz.impl.jdbcjobstore.JobStoreTX  
  27. #org.quartz.jobStore.driverDelegateClass: org.quartz.impl.jdbcjobstore.PostgreSQLDelegate  
  28. #org.quartz.jobStore.useProperties: false  
  29. #org.quartz.jobStore.dataSource: myDS  
  30. #org.quartz.jobStore.tablePrefix: QRTZ_  
  31. #org.quartz.jobStore.isClustered: false  
  32.   
  33. #============================================================================  
  34. # Configure Datasources    
  35. #============================================================================  
  36.   
  37. #org.quartz.dataSource.myDS.driver: org.postgresql.Driver  
  38. #org.quartz.dataSource.myDS.URL: jdbc:postgresql://localhost/dev  
  39. #org.quartz.dataSource.myDS.user: jhouse  
  40. #org.quartz.dataSource.myDS.password:   
  41. #org.quartz.dataSource.myDS.maxConnections: 5  
  42.   
  43.   
  44.   
  45. #============================================================================  
  46. # Configure Plugins   
  47. #============================================================================  
  48.   
  49. org.quartz.plugin.triggHistory.class: org.quartz.plugins.history.LoggingJobHistoryPlugin  
  50.   
  51. org.quartz.plugin.jobInitializer.class: org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin  
  52. org.quartz.plugin.jobInitializer.fileNames: quartz_data.xml  
  53. org.quartz.plugin.jobInitializer.failOnFileNotFound: true  
  54. org.quartz.plugin.jobInitializer.scanInterval: 120  
  55. org.quartz.plugin.jobInitializer.wrapInUserTransaction: false  

日志


Quartz使用SLF4J框架。
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
几种任务调度的 Java 实现方法与比较
Quartz使用入门
Quartz的基本使用之入门(2.3.0版本)
Quartz任务调度入门
定时任务框架Quartz详解-基础篇
任务调度开源框架Quartz
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服