《2022年Quartz学习资料 .pdf》由会员分享,可在线阅读,更多相关《2022年Quartz学习资料 .pdf(31页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、Quartz 学习资料(完全)介绍 Quartz Quartz 是一个开源的任务调度系统,它能用来调度很多任务的执行。运行环境Quartz 能嵌入在其他应用程序里运行。Quartz 能在一个应用服务器里被实例化(或 servlet 容器 ), 并且参与XA 事务Quartz 能独立运行(通过JVM) ,或者通过RMI Quartz 能被集群实例化任务调度当一个指定给任务的触发器发生时,任务就被调度执行. 触发器能被创建为: 一天的某个时间(精确到毫秒级 ) 一周的某些天一个月的某些天一年的某些天不在一个Calendar 列出的某些天(例如工作节假日) 在一个指定的次数重复重复到一个指定的时间/
2、日期无限重复在一个间隔内重复能够给任务指定名称和组名.触发器也能够指定名称和组名,这样可以很好的在调度器里组织起来 .一个加入到调度器里的任务可以被多个触发器注册。在 J2EE 环境里, 任务能作为一个分布式( XA)事务的一部分来执行。任务执行任务能够是任何实现Job 接口的 Java 类。任务类能够被Quartz 实例化 ,或者被你的应用框架。当一个触发器触发时,调度器会通知实例化了JobListener 和 TriggerListener 接口的0 个或者多个Java对象 (监听器可以是简单的Java对象 , EJBs, 或 JMS 发布者等 ). 在任务执行后,这些监听器也会被通知。当
3、任务完成时,他们会返回一个JobCompletionCode ,这个代码告诉调度器任务执行成功或者失败.这个代码也会指示调度器做一些动作-例如立即再次执行任务。任务持久化名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 1 页,共 31 页 - - - - - - - - - Quartz 的设计包含JobStore 接口,这个接口能被实现来为任务的存储提供不同的机制。应用 JDBCJobStore, 所有被配置成“稳定”的任务和触发器能通过JDBC 存储在关系数据库里。应用 RAMJ
4、obStore, 所有任务和触发器能被存储在RAM 里因此不必在程序重起之间保存 -一个好处就是不必使用数据库。事务使用 JobStoreCMT( JDBCJobStore 的子类),Quartz 能参与 JTA 事务。Quartz 能管理 JTA 事务 (开始和提交 )在执行任务之间,这样,任务做的事就可以发生在 JTA 事务里。集群Fail-over. Load balancing. 监听器和插件通过实现一个或多个监听接口,应用程序能捕捉调度事件来监控或控制任务/触发器的行为。插件机制可以给Quartz 增加功能,例如保持任务执行的历史记录,或从一个定义好的文件里加载任务和触发器。Quar
5、tz 装配了很多插件和监听器。1.使用 Quartz 在我们用调度器之前,调度器需要实例化。我们用SchedulerFactory 来实例它。一旦调度器被实例,我们就可以启动它,置它为stand-by 模式,最后关闭它。注意:一旦一个调度器被关闭了, 如果我们不重新实例化它,它就不可能被再次启动。直到调度器启动了或者当调度器处于暂停状态,触发器才能够触发。下面有个简单的例子:SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory(); Scheduler sched = schedFact.getSchedule
6、r(); sched.start(); JobDetail jobDetail = new JobDetail(myJob,null, DumbJob.class); Trigger trigger = TriggerUtils.makeHourlyTrigger(); / 每个小时触发trigger.setStartTime(TriggerUtils.getEvenHourDate(new Date(); / 在下个小时开始trigger.setName(myTrigger); sched.scheduleJob(jobDetail, trigger);就象你看到的,使用Quartz 是很简
7、单的。在下一节我们介绍Jobs和 Triggers。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 2 页,共 31 页 - - - - - - - - - 2.Jobs 和 Triggers 就象以前提到的,一个实现了Job 接口的 Java类就能够被调度器执行。接口如下:package org.quartz; public interface Job public void execute(JobExecutionContext context) throws JobExecut
8、ionException; 很简的,当Job的 trigger 触发时, Job 的 execute(.)方法就会被调度器调用。被传递到这个方法里来的JobExecutionContext 对象提供了带有job 运行时的信息: 执行它的调度器句柄、触发它的触发器句柄、job 的 JobDetail 对象和一些其他的项。JobDetail 对象是 Job 在被加到调度器里时所创建的,它包含有很多的Job 属性设置,和JobDataMap 一样,可以用来存储job 实例时的一些状态信息。Trigger 对象是用来触发执行Job 的。当调度一个job 时,我们实例一个触发器然后调整它的属性来满足jo
9、b 执行的条件。触发器也有一个和它相关的JobDataMap,它是用来给被触发器触发的job 传参数的。Quartz 有一些不同的触发器类型,不过,用得最多的是SimpleTrigger和 CronTrigger 。如果我们需要在给定时刻执行一次job 或者在给定时刻触发job 随后间断一定时间不停的执行的话, SimpleTrigger 是个简单的解决办法;如果我们想基于类似日历调度的触发job的话,比如说, 在每个星期五的中午或者在每个月第10 天的 10: 15 触发 job 时,CronTrigger是很有用的。为什么用jobs 和 triggers 呢?很多任务调度器并没有任务和触发
10、器的概念,一些任务调度器简单定义一个“job”为在一个执行时间伴随一些小任务标示,其他的更像Quartz 里 job 和trigger 对象的联合体。在开发Quartz 时,开发者们决定,在调度时间表和在这上面运行的工作应该分开。这是很有用的。例如, job 能够独立于触发器被创建和储存在任务调度器里,并且,很多的触发器能够与同一个job 关联起来。 这个松耦合的另一个好处就是在与jobs 关联的触发器终止后,我们能够再次配置保留在调度器里的jobs,这样的话,我们能够再次调度这些jobs 而不需要重新定义他们。我们也可以在不重新定义一个关联到job 的触发器的情况下,修改或替代它。当 Job
11、s和 triggers 被注册到 Quartz 的调度器里时,他们就有了唯一标示符。他们也可以被放到“ groups”里, Groups 是用来组织分类jobs 和 triggers 的,以便今后的维护。在一个组里的 job 和 trigger 的名字必须是唯一的,换句话说, 一个 job 和 trigger 的全名为他们的名字加上组名。如果把组名置为” null” ,系统会自动给它置为Scheduler.DEFAULT_GROUP现在,我们大概有了一些jobs 和 triggers 的理解,随后2 节我们将根多的了解它们。3.更多关于 Jobs & JobDetails Jobs 很容易实现
12、, 这儿有更多我们需要理解的东西:jobs 的本质, job 接口的 execute(.)方法,关于 JobDetails。当我们实现的一个class 是真正的 ” job” 时, Quartz 需要知道各种job 有的属性,这是通过 JobDetail 类做到的。在没用JobDetail 之前, JobDetail 的功能的实现是通过在每个job 的实现类上加上所有的现在JobDetail 的 get 方法来实现的。 这就在每个job 类上强加了一些实名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - -
13、 - - - 第 3 页,共 31 页 - - - - - - - - - 现一样功能的代码,就显得每个job 类很笨重,于是,Quartz 开发者们就创造了JobDetail类。现在, 我们来讨论一下在Quartz 里 job 的本质和job 实例的生命周期。首先我们来看看第一节的代码片段:JobDetail jobDetail = new JobDetail(myJob, / job 名称sched.DEFAULT_GROUP, / job组名 (可以写 null 来用 default group) DumbJob.class); /要执行的java 类Trigger trigger =
14、TriggerUtils.makeDailyTrigger(8, 30); trigger.setStartTime(new Date(); trigger.setName(myTrigger); sched.scheduleJob(jobDetail, trigger);现在我们定义“DumbJob”类:public class DumbJob implements Job public DumbJob() public void execute(JobExecutionContext context) throws JobExecutionException System.err.prin
15、tln(DumbJob is executing.); 可以看到我们给调度器一个JobDetail 实例,并且,它通过job 的类代码引用这个job 来执行。每次调度器执行job 时,它会在调用job 的 execute(.)方法之前创建一个他的实例。这就带来了两个事实:一、job 必须有一个不带参数的构造器,二、在job 类里定义数据成员并没有意义,因为在每次job 执行的时候他们的值会被覆盖掉。你可能现在想要问“我怎样给一个job 实例提供属性 /配置?”和“在几次执行间我怎样能跟踪 job 的状态?”这些问题的答案是一样的:用JobDataMap- JobDetail 对象的一部分。Jo
16、bDataMap JobDataMap 能够支持任何序列化的对象,当job 执行时,这些对象能够在job 实例中可用。JobDataMap 实现了 Java Map 接口,它有一些附加的方法,这些方法用来储存和跟踪简单类型的数据。如下代码可以很快地给job 增加 JobDataMap:jobDetail.getJobDataMap().put(jobSays, Hello World!); jobDetail.getJobDataMap().put(myFloatValue, 3.141f); jobDetail.getJobDataMap().put(myStateData, new Arr
17、ayList(); 在 job 执行时,我们可以在job 里通过如下代码得到JobDataMap:public class DumbJob implements Job public DumbJob() public void execute(JobExecutionContext context) throws JobExecutionException 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 4 页,共 31 页 - - - - - - - - - String inst
18、Name = context.getJobDetail().getName(); String instGroup = context.getJobDetail().getGroup(); JobDataMap dataMap = context.getJobDetail().getJobDataMap(); String jobSays = dataMap.getString(jobSays);float myFloatValue = dataMap.getFloat(myFloatValue); ArrayList state = (ArrayList)dataMap.get(myStat
19、eData);state.add(new Date(); System.err.println(Instance + instName + of DumbJob says: + jobSays); 如果用一个持久JobStore(在指南JobStore 章节讨论),我们就应该注意在JobDataMap 里放些什么,因为在它里面的对象将会被序列化,并且这些对象会因此产生一些class-versioning 问题。 明显的, 标准 Java 类型应该是很安全的,但是, 任何时候某人改变了一个你已经序列化的实例的类的定义时,我们就要注意不能够破坏兼容性了。在这个方面的进一步信息可以在Java Dev
20、eloper Connection Tech Tip: Serialization In The Real World里找到。 我们能把 JDBC-JobStore 和 JobDataMap 放到一个模式里, 在那里,只有简单类型和String型能被储存在Map 里,从而消去任何以后的序列化问题。Stateful vs. Non-Stateful Jobs 触发器也有与它们关联的JobDataMaps。假设我们有一个储存在调度器里被多个触发器关联的 job,然而,对于每个独立的触发器,我想提供给job 不同的数据输入,在这个时候,JobDataMaps 就很有用了。在 job执行期间,JobD
21、ataMaps 能够在 JobExecutionContext 里获得。JobDataMap 融合在 Trigger和 JobDetail 类里, JobDataMap 里面的值能够利用key 来更新。以下例子显示,在job 执行期间从JobExecutionContext 里的 JobDataMap 得到数据:public class DumbJob implements Job public DumbJob() public void execute(JobExecutionContext context) throws JobExecutionException String instN
22、ame = context.getJobDetail().getName(); String instGroup = context.getJobDetail().getGroup(); JobDataMap dataMap = context.getJobDataMap(); / 注意:不同于以前的例子String jobSays = dataMap.getString(jobSays);float myFloatValue = dataMap.getFloat(myFloatValue); ArrayList state = (ArrayList)dataMap.get(myStateDa
23、ta);state.add(new Date(); System.err.println(Instance + instName + of DumbJob says: + jobSays); 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 5 页,共 31 页 - - - - - - - - - StatefulJob 现在, 关于 job 状态数据的一些附加要点:一个 job 实例能定义为有状态的 或者 无状态的。无状态的jobs 仅当它们在被加入到调度器里时才存储JobDataM
24、ap。这就意味着,在jobs执行期间对JobDataMap 里数据的任何改变都会丢失,下次执行时job 将看不到这些数据。你可能会猜到,一个有状态的job 就是它的反面例子-它的 JobDataMap 是在每次执行完job后再次储存的。一个缺点就是有状态的job 不能够并发执行。换句话说,如果job 是有状态的,一个触发器尝试触发这个已经执行了的job 时,这个触发器就会等待直到这次执行结束。用实现 StatefulJob 接口来标记一个job 是有状态的。Job Instances 我们能够创建一个单独的job 类,并且通过创建多个JobDetails 实例在调度器里储存很多它的“实例定义”
25、,每个都有它自己的属性集和JobDataMap ,把它们都加入到调度器里。当一个触发器触发时, 与它关联的job 就是通过配置在调度器上的JobFactory 来实例化的。默认的 JobFactory 简单的调用在job 类上的 newInstance()方法,你可能想要创建自己的JobFactory 实现来完成一些自己想要的事情,如:拥有应用程序的IoC 或者 DI 容器进程 /初始化 job 实例。job 的其他属性这儿有一个其他属性的总结,这些属性是通过JobDetail 对象为一个job 实例定义的。持久性 如果一个job 是非持久的,一旦没有任何可用的触发器与它关联时,他就会自动得从
26、调度器里被删除。不稳定性 -如果一个job 是不稳定的,他就不会在重起Quartz 调度器之间持久化。请求恢复 如果一个job“请求恢复” ,在调度器“硬关闭” (如:该进程崩溃,机器被关掉)时这个job 还在执行,过后,当调度器再次启动时,他就会再次执行。在这种情况下, JobExecutionContext.isRecovering() 方法将会返回true. Job 监听器 一个 job 能够有 0 个或者多个与它关联的监听器。当job 执行时,监听器就会被通知。在监听器的更多讨论请看TriggerListeners & JobListeners JobExecutionExceptio
27、n 最后,我们来看看Job.execute(.)方法的一些细节。你能够从execute方法里抛出的仅有的异常类型就是JobExecutionException 。因为这样,我们应该使用try-catch 块包围整个execute方法内容。 我们还应该花一些时间看看JobExecutionException 文档。当 job 执行发生异常时,通过设置JobExecutionException ,可以让此job 再次进入调度器或者今后不再运行。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - -
28、第 6 页,共 31 页 - - - - - - - - - 4.更多关于 Triggers 象 jobs 一样, triggers 也相对来说很容易。但是,我们还是要理解它的一些特性。Quartz 里也有很多类型的trigger 提供给我们使用。Calendars Quartz Calendar 对象(不是 java.util.Calendar 对象)能够在 trigger 储存在调度器时和trigger关联起来。 Calendars 主要用来在trigger 配置时排除一些时间。例如,你能够创建一个在每个工作日早上9:30 触发的 trigger,然后为这个trigger 增加一个排除所有
29、商业的节假日的Calendar。Calendars 能够是任何序列化的对象,只要这些对象实现了Calendar 接口:package org.quartz; public interface Calendar public boolean isTimeIncluded(long timeStamp); public long getNextIncludedTime(long timeStamp); 注意到这些方法的参数类型是long。这意味着calendars能够排除毫秒级的时间段。大部分地,我们感兴趣的是一整天的,所以在Quartz 里,有个实现类提供了方便:org.quartz.impl.
30、HolidayCalendar Calendars 必须被实例化并且通过addCalendar(.)方法注册到调度器里。如果你用HolidayCalendar ,在实例它之后,你应该用它的addExcludedDate(Date date)方法以便组装上你想排除的那几天。一个calendar 实例能够被多个triggers 使用:HolidayCalendar cal = new HolidayCalendar(); cal.addExcludedDate( someDate ); sched.addCalendar(myHolidays, cal, false); Trigger trigg
31、er = TriggerUtils.makeHourlyTrigger(); / 每小时触发trigger.setStartTime(TriggerUtils.getEvenHourDate(new Date(); / 下 一 个 小 时 开 始trigger.setName(myTrigger1); trigger.setCalendarName(myHolidays); / . schedule job with trigger Trigger trigger2 = TriggerUtils.makeDailyTrigger(8, 0); / 每天早上 8 点触发trigger2.setS
32、tartTime(new Date(); / 立即开始trigger2.setName(myTrigger2); trigger2.setCalendarName(myHolidays); / . schedule job with trigger2名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 7 页,共 31 页 - - - - - - - - - 不触发 (misfire)指令触发器的另外一个重要的属性是“不触发指令”。如果一个持久的触发器由于调度器被关闭了而没有找到它的触发时
33、间,那么一个不触发将会发生。不同的触发器类型有不同的不触发指令。默认的,他们都用“smart policy ”指令 -这是一个基于触发器类型和配置的动态行为。当调度器启动时,他将会搜寻所有没触发的持久化的triggers,然后基于他们各个配置的不触发指令来更新他们。当你用 Quartz,你应该熟悉各个不触发指令,我们在以下章节有一些介绍。给一个trigger 实例配置不触发指令,要用此实例的setMisfireInstruction(.)方法。TriggerUtils - T riggers Made Easy TriggerUtils 类(在 org.quartz 包里)包含了很多方便的工具
34、。能够帮你创建triggers 和 datas。用这个类能够很容易制造一些trigges,这些 triggers 能够在每分钟,每小时,每周,每个月等等触发。用它也能产生一些接近某个秒、分钟、小时的天-这在设置trigger 的启动时间很有帮助。TriggerListeners 最后, triggers有一些注册了的监听器,象job 一样。实现了TriggerListener接口的对象将接受一个trigger被触发的通知。5. SimpleTrigger 详细介绍一下它的构造器:public SimpleTrigger(String name, /trigger名称String group,
35、/trigger 的组名Date startTime, /开始时间Date endTime, / 结束时间int repeatCount, / 重复次数long repeatInterval)/ 重复间隔举几个常用例子:从现在开始10 秒后执行一次:long startTime = System.currentTimeMillis() + 10000L; SimpleTrigger trigger = new SimpleTrigger(myTrigger, null, new Date(startTime), null, 0, 0L); 立即执行, 60 秒间隔无限制重复:SimpleTri
36、gger trigger = new SimpleTrigger(myTrigger, 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 8 页,共 31 页 - - - - - - - - - null, new Date(), null, SimpleTrigger.REPEAT_INDEFINITELY, 60L * 1000L); 从现在开始立即执行,每10 秒重复,直到40 秒后:long endTime = System.currentTimeMillis() + 4000
37、0L; SimpleTrigger trigger = new SimpleTrigger(myTrigger, myGroup, new Date(), new Date(endTime), SimpleTrigger.REPEAT_INDEFINITELY, 10L * 1000L); 在 2002 年 3 月 17 号 10:30am 触发,重复5 次(一共 6 次), 30 秒间隔:java.util.Calendar cal = new java.util.GregorianCalendar(2002, cal.MARCH, 17); cal.set(cal.HOUR, 10); c
38、al.set(cal.MINUTE, 30); cal.set(cal.SECOND, 0); cal.set(cal.MILLISECOND, 0); Data startTime = cal.getTime(); SimpleTrigger trigger = new SimpleTrigger(myTrigger, null, startTime, null, 5, 30L * 1000L); SimpleTrigger 不触发指令MISFIRE_INSTRUCTION_FIRE_NOW MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_R
39、EPEAT_COUNTMISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNTMISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT 6.CronTrigger 构造器CronTrigger(String name, / 触发器名称String group, / 触发器的组名String jobName, /job 名称名师资料总结 - - -精品资料欢迎下载
40、 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 9 页,共 31 页 - - - - - - - - - String jobGroup, /job的组名Date startTime, / 开始时间Date endTime, / 结束时间String cronExpression, / 克隆表达式TimeZone timeZone)/ 时区还有一些其它参数少一些的构造器,参考 JavaDoc。通常我们如下简单地使用CronTrigger;Trigger trigger = new CronTrigger(trigger1,
41、 group1);/设置触发器名称和组名trigger.setCronExpression(0 0 15 * * ?);/设置克隆表达式克隆表达式一个克隆表达式是一个由空白间隔6 个或者 7 个字段的字符串。格式:字段名必须有 ? 值范围允许的特殊字符Seconds YES 0-59 , - * / Minutes YES 0-59 , - * / Hours YES 0-23 , - * / Day of month YES 1-31 , - * ? / L W C Month YES 1-12 or JAN-DEC , - * / Day of week YES 1-7 or SUN-SA
42、T , - * ? / L C # Year NO empty, 1970-2099 , - * / 例子:* * * * ? * 0 0/5 14,18,3-39,52 ? JAN,MAR,SEP MON-FRI 2002-2010 特殊字符*表示所有值;? 表示未说明的值,即不关心它为何值;- 表示一个指定的范围;, 表示附加一个可能值;/ 符号前表示开始时间,符号后表示每次递增的值;L (last ) L 用在 day-of-month 字段意思是这个月最后一天 ;用在day-of-week名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - -
43、- - - - 名师精心整理 - - - - - - - 第 10 页,共 31 页 - - - - - - - - - 字段 , 它简单意思是7 or SA T。 如果在 day-of-week 字段里和数字联合使用,它的意思就是这个月的最后一个星期几 例如: 6L means 这个月的最后一个星期五 . 当我们用“ L”时,不指明一个列表值或者范围是很重要的,不然的话,我们会得到一些意想不到的结果。W (weekday ) 只能用在 day-of-month 字段。用来描叙最接近指定天的工作日(周一到周五)。例如:在day-of-month 字段用“ 15W”指“最接近这个月第15 天的工
44、作日” , 即如果这个月第15 天是周六,那么触发器将会在这个月第14 天即周五触发;如果这个月第15 天是周日,那么触发器将会在这个月第16 天即周一触发;如果这个月第 15 天是周二, 那么就在触发器这天触发。注意一点: 这个用法只会在当前月计算值,不会越过当前月。 “W”字符仅能在day-of-month 指明一天,不能是一个范围或列表。也可以用“ LW”来指定这个月的最后一个工作日。# -只能用在 day-of-week 字段。用来指定这个月的第几个周几。例:在day-of-week字段用 6#3指这个月第3 个周五(6 指周五, 3 指第 3 个) 。如果指定的日期不存在,触发器就不
45、会触发。C (calendar ) 指和 calendar 联系后计算过的值。例:在 day-of-month 字段用“5C”指在这个月第5 天或之后包括calendar 的第一天; 在 day-of-week 字段用“1C”指在这周日或之后包括calendar 的第一天。在 MONTH 和 Day of week 字段里对字母大小写不敏感。一些例子表达式意思(触发时刻)0 0 12 * * ? 每天中午 12 点0 15 10 * * ? 2005 在 2005 年的每天 10:25 0 10,44 14 ? 3 WED 在 3 月里每个周三的14:10 和 14:44 0 15 10 ?
46、* 6L 2002-2005 从 2002 年到 2005 年里,每个月的最后一个星期五的10:15 0 0 12 1/5 * ? 从当月的第一天开始,然后在每个月每隔5 天的 12:00 0 15 10 ? * 6#3 每个月第 3 个周五的10:15 注意在 day-of-week 和 day-of-month 字段里使用“?”和“*”的效果。注意对“ C”的支持并不很完全。对在 day-of-week 字段和在 day-of-month 字段同时使用也不是很完全(目前你必须在这两个字段中的一个用“?”指定)。当设置在午夜和凌晨1 点之间触发时要仔细。不触发指令:名师资料总结 - - -精
47、品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 11 页,共 31 页 - - - - - - - - - MISFIRE_INSTRUCTION_FIRE_ONCE_NOW MISFIRE_INSTRUCTION_DO_NOTHING 7.TriggerListeners 和 JobListeners 与 Trigger 相关的事件有:触发器触发,触发器的不触发(参考先前章节),触发器完成。public interface TriggerListener public String getName(); p
48、ublic void triggerFired(Trigger trigger, JobExecutionContext context); public boolean vetoJobExecution(Trigger trigger, JobExecutionContext context); public void triggerMisfired(Trigger trigger); public void triggerComplete(Trigger trigger, JobExecutionContext context, int triggerInstructionCode); 与
49、 job 相关的事件有:job 准备执行, job 执行完毕。public interface JobListener public String getName(); public void jobToBeExecuted(JobExecutionContext context); public void jobExecutionV etoed(JobExecutionContext context); public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException); 使用
50、 Listeners 创建一个监听器,就是创建一个实现了org.quartz.TriggerListener 和 org.quartz.JobListener接口的对象。 在运行的期间用调度器注册监听器,必须要给它提供一个名字。监听器能够注册成为全局的或者不是全局的,全局监听器接受所有的事件,而非全局的则仅接受指定给triggers/jobs 了的事件。监听器是在运行期间被调度器注册的,他们没有伴随jobs 和 triggers 储存在 JobStore 里。 Jobs和 triggers 仅储存和它们相关的监听器的名字。因此,每次程序运行时,监听器需要被调度器再次注册。scheduler.a