下载和安装
如果是采用maven管理依赖,则依赖配置如下:
- <dependency>
- <groupId>org.quartz-scheduler</groupId>
- <artifactId>quartz</artifactId>
- <version>2.2.3</version>
- </dependency>
- <dependency>
- <groupId>org.quartz-scheduler</groupId>
- <artifactId>quartz-jobs</artifactId>
- <version>2.2.3</version>
- </dependency>
如果不是的话,所需依赖包可以到官网下载
http://www.quartz-scheduler.org/downloads/
关键接口
Scheduler
一个scheduler的生命周期是有限的,从通过SchedulerFactory创建开始直到调用它的shutdown()方法。scheduler接口一旦创建,就能添加、移除、和列出job和trigger,并执行另一些与调度相关的操作(例如暂停trigger),然而,在scheduler被start()方法启动前,它不会作用于任何trigger(执行job)。
Job
一个job就是实现了Job接口的类。如下所示,这个接口只有一个简单的方法:
- package org.quartz;
-
- public interface Job {
-
- public void execute(JobExecutionContext context)
- throws JobExecutionException;
- }
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 程序
- import org.quartz.Job;
- import org.quartz.JobExecutionContext;
- import org.quartz.JobExecutionException;
-
- import java.util.Date;
-
- public class HelloJob implements Job {
-
- /**
- * 需要一个无参的public构造以便scheduler在它需要的时候可以实例化这个class.
- */
- public HelloJob() {
- }
-
-
- /**
- * 要执行的代码
- *
- * @param context JobExecutionContext
- * @throws JobExecutionException
- */
- public void execute(JobExecutionContext context) throws JobExecutionException {
- System.out.println("Hello World! - " + new Date());
- }
- }
- import org.quartz.DateBuilder;
- import org.quartz.JobBuilder;
- import org.quartz.JobDetail;
- import org.quartz.Scheduler;
- import org.quartz.SchedulerFactory;
- import org.quartz.Trigger;
- import org.quartz.TriggerBuilder;
- import org.quartz.impl.StdSchedulerFactory;
-
- import java.util.Date;
-
- public class SimpleExample {
-
- public void run() throws Exception {
-
- System.out.println("------- 初始化 ----------------------");
-
- // 首先要实例化scheduler
- SchedulerFactory schedulerFactory = new StdSchedulerFactory();
- Scheduler scheduler = schedulerFactory.getScheduler();
-
- System.out.println("------- 初始化完成 -----------");
-
- // 获取给定时间的下一个完整分钟的时间,例如给定时间 08:13:54 则会反回 08:14:00
- Date runTime = DateBuilder.evenMinuteDate(new Date());
-
- System.out.println("------- Job安排 -------------------");
-
- // 获取job实例
- JobDetail job = JobBuilder.newJob(HelloJob.class).withIdentity("job1", "group1").build();
-
- // 在下一轮分钟触发运行
- Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").startAt(runTime).build();
-
- // 告诉quartz使用某个trigger执行某个job
- scheduler.scheduleJob(job, trigger);
- System.out.println(job.getKey() + " 将会运行于: " + runTime);
-
- // 启动scheduler
- scheduler.start();
-
- System.out.println("------- 开始安排 -----------------");
-
- System.out.println("------- 等待65秒 -------------");
- Thread.sleep(65L * 1000L);
-
- // 关闭scheduler
- System.out.println("------- 关闭 ---------------------");
- scheduler.shutdown(true);
- System.out.println("------- 关闭完成 -----------------");
- }
-
- public static void main(String[] args) throws Exception {
- SimpleExample example = new SimpleExample();
- example.run();
- }
- }
更多关于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接口的一个实现,并且添加一些便利的方法来存储和检索数据的原始类型。
存放数据
- JobDetail job = newJob(DumbJob.class)
- .withIdentity("myJob", "group1") // name "myJob", group "group1"
- .usingJobData("jobSays", "Hello World!")
- .usingJobData("myFloatValue", 3.141f)
- .build();
获取数据
- public class DumbJob implements Job {
-
- public DumbJob() {
- }
-
- public void execute(JobExecutionContext context)
- throws JobExecutionException
- {
- JobKey key = context.getJobDetail().getKey();
-
- JobDataMap dataMap = context.getJobDetail().getJobDataMap();
-
- String jobSays = dataMap.getString("jobSays");
- float myFloatValue = dataMap.getFloat("myFloatValue");
-
- System.err.println("Instance " + key + " of DumbJob says: " + jobSays + ", and val is: " + myFloatValue);
- }
- }
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使用,如下所示:
- HolidayCalendar cal = new HolidayCalendar();
- cal.addExcludedDate( someDate );
- cal.addExcludedDate( someOtherDate );
-
- sched.addCalendar("myHolidays", cal, false,false);
-
-
- Trigger t = newTrigger()
- .withIdentity("myTrigger")
- .forJob("myJob")
- .withSchedule(dailyAtHourAndMinute(9, 30)) // execute job daily at 9:30
- .modifiedByCalendar("myHolidays") // but not on holidays
- .build();
-
- // .. schedule job with trigger
-
- Trigger t2 = newTrigger()
- .withIdentity("myTrigger2")
- .forJob("myJob2")
- .withSchedule(dailyAtHourAndMinute(11, 30)) // execute job daily at 11:30
- .modifiedByCalendar("myHolidays") // but not on holidays
- .build();
-
- // .. 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(..),则设定为当前的时间(立即执行)。
首先静态引入:
- import static org.quartz.TriggerBuilder.*;
- import static org.quartz.SimpleScheduleBuilder.*;
- import static org.quartz.DateBuilder.*:
创建一个指定时间执行的trigger,没有重复次数
- SimpleTrigger trigger = (SimpleTrigger) newTrigger()
- .withIdentity("trigger1", "group1")
- .startAt(myStartTime) // some Date
- .forJob("job1", "group1") // identify job with name, group strings
- .build();
在指定的时间创建一个trigger,然后每10秒触发一次,共触发10次
- trigger = newTrigger()
- .withIdentity("trigger3", "group1")
- .startAt(myTimeToStartFiring) // if a start time is not given (if this line were omitted), "now" is implied
- .withSchedule(simpleSchedule()
- .withIntervalInSeconds(10)
- .withRepeatCount(10)) // note that 10 repeats will give a total of 11 firings
- .forJob(myJob) // identify job with handle to its JobDetail itself
- .build();
创建一个触发一次的trigger,5分钟后触发
- trigger = (SimpleTrigger) newTrigger()
- .withIdentity("trigger5", "group1")
- .startAt(futureDate(5, IntervalUnit.MINUTE)) // use DateBuilder to create a date in the future
- .forJob(myJobKey) // identify job with its JobKey
- .build();
创建一个立即触发的trigger,每5分钟触发一次,直到22:00结束
- trigger = newTrigger()
- .withIdentity("trigger7", "group1")
- .withSchedule(simpleSchedule()
- .withIntervalInMinutes(5)
- .repeatForever())
- .endAt(dateOf(22, 0, 0))
- .build();
建立一个trigger,每小时开始的时候触发,每2小时出发一次,直到永远
- trigger = newTrigger()
- .withIdentity("trigger8") // because group is not specified, "trigger8" will be in the default group
- .startAt(evenHourDate(null)) // get the next even-hour (minutes and seconds zero ("00:00"))
- .withSchedule(simpleSchedule()
- .withIntervalInHours(2)
- .repeatForever())
- // note that in this example, 'forJob(..)' is not called
- // - which is valid if the trigger is passed to the scheduler along with the job
- .build();
-
- 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的一部分。
- trigger = newTrigger()
- .withIdentity("trigger7", "group1")
- .withSchedule(simpleSchedule()
- .withIntervalInMinutes(5)
- .repeatForever()
- .withMisfireHandlingInstructionNextWithExistingCount())
- .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触发 |
注意:当不指定一周中的第几天和一月中的第几天,你必须在这两个字段之一使用”?”。
首先静态导入:
- import static org.quartz.TriggerBuilder.*;
- import static org.quartz.CronScheduleBuilder.*;
- import static org.quartz.DateBuilder.*:
- trigger = new Trigger()
- .withIdentity("trigger3", "group1")
- .withSchedule(cronSchedule("0 42 10 ? * WED"))
- .inTimeZone(TimeZone.getTimeZone("America/Los_Angeles"))
- .forJob(myJobKey)
- .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的失败说明。
- trigger = newTrigger()
- .withIdentity("trigger3", "group1")
- .withSchedule(cronSchedule("0 0/2 8-17 * * ?")
- ..withMisfireHandlingInstructionFireAndProceed())
- .forJob("myJob", "group1")
- .build();
使用TriggerListener和JobListener
TriggerListener和JobListener
监听器是你基于scheduler中事件的活动创建的对象。就像它们名字所示,TriggerListener接收与trigger有关的事件,JobListener接收与Job有关的事件。
与trigger有关的事件包括trigger触发,trigger触发失败,trigger执行完成(trigger完成job执行完毕)。
org.quartz.TriggerListener接口
- publicinterface TriggerListener {
- public String getName();
-
- publicvoid triggerFired(Trigger trigger, JobExecutionContext context);
-
- publicboolean vetoJobExecution(Trigger trigger, JobExecutionContext context);
-
- publicvoid triggerMisfired(Trigger trigger);
-
- publicvoid triggerComplete(Trigger trigger, JobExecutionContext context, inttriggerInstructionCode);
- }
与job有关的时间包括:job即将进行的通知,和job已经完成的通知。
org.quartz.JobListener接口
- publicinterface JobListener {
- public String getName();
-
- publicvoid jobToBeExecuted(JobExecutionContext context);
-
- publicvoid jobExecutionVetoed(JobExecutionContext context);
-
- publicvoid jobWasExecuted(JobExecutionContext context, JobExecutionException jobException);
- }
创建你自己的监听器
要创建一个监听器,需要简单创建一个实现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上。例如:
- #============================================================================
- # Configure Main Scheduler Properties
- #============================================================================
-
- org.quartz.scheduler.instanceName: TestScheduler
- org.quartz.scheduler.instanceId: AUTO
-
- org.quartz.scheduler.skipUpdateCheck: true
-
- #============================================================================
- # Configure ThreadPool
- #============================================================================
-
- org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
- org.quartz.threadPool.threadCount: 3
- org.quartz.threadPool.threadPriority: 5
-
- #============================================================================
- # Configure JobStore
- #============================================================================
-
- org.quartz.jobStore.misfireThreshold: 60000
-
- org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore
-
- #org.quartz.jobStore.class: org.quartz.impl.jdbcjobstore.JobStoreTX
- #org.quartz.jobStore.driverDelegateClass: org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
- #org.quartz.jobStore.useProperties: false
- #org.quartz.jobStore.dataSource: myDS
- #org.quartz.jobStore.tablePrefix: QRTZ_
- #org.quartz.jobStore.isClustered: false
-
- #============================================================================
- # Configure Datasources
- #============================================================================
-
- #org.quartz.dataSource.myDS.driver: org.postgresql.Driver
- #org.quartz.dataSource.myDS.URL: jdbc:postgresql://localhost/dev
- #org.quartz.dataSource.myDS.user: jhouse
- #org.quartz.dataSource.myDS.password:
- #org.quartz.dataSource.myDS.maxConnections: 5
-
-
-
- #============================================================================
- # Configure Plugins
- #============================================================================
-
- org.quartz.plugin.triggHistory.class: org.quartz.plugins.history.LoggingJobHistoryPlugin
-
- org.quartz.plugin.jobInitializer.class: org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin
- org.quartz.plugin.jobInitializer.fileNames: quartz_data.xml
- org.quartz.plugin.jobInitializer.failOnFileNotFound: true
- org.quartz.plugin.jobInitializer.scanInterval: 120
- org.quartz.plugin.jobInitializer.wrapInUserTransaction: false
日志
Quartz使用SLF4J框架。