quartz 定时任务.docx
《quartz 定时任务.docx》由会员分享,可在线阅读,更多相关《quartz 定时任务.docx(15页珍藏版)》请在冰豆网上搜索。
![quartz 定时任务.docx](https://file1.bdocx.com/fileroot1/2023-1/22/e2204b2b-7f1e-4b14-a4b7-7b47b3c51a26/e2204b2b-7f1e-4b14-a4b7-7b47b3c51a261.gif)
quartz定时任务
1.触发器的监听器和作业的监听器(TriggerListeners&JobListeners)
Listener是我们创建用于监听Scheduler中关于事件发生情况的对象,其中TriggerListener接收涉及Trigger事件的情况,JobListener接收涉及Job事件的情况。
lTrigger的事件:
Trigger触发、Trigger过时触发和Trigger触发的完成。
lJob的事件:
Job的执行通知和Job的完成通知。
要创建Listener,只需简单的实现org.quartz.TriggerListener或org.quartz.JobListener接口,接着运行时把Listener注册到Scheduler中即可,在注册过程中需要为创建的Listener命名,Listener可以注册为全局的和非全局的,全局的Listener接收所有Trigger/Job的事件,非全局的Listener只接收指定设置的Trigger/Job事件,把JobListener注册到Scheduler的方法如下:
scheduler.addGlobalJobListener(myJobListener)或scheduler.addJobListener(myJobListener);
2调度监听器(SchedulerListeners)
SchedulerListener与TriggerListener和JobListener类似,SchedulerListener只接收涉及Scheduler自己的事件通知,而与指定设置的Trigger/Job无关;
有关Scheduler的事件包括:
Job/Trigger的增加、Job/Trigger的删除、Scheduler中一系列严重的事件和Scheduler的关闭等事件;
SchedulerListener的创建和注册与其他类型的Listener很相似,但是它没有区分全局和非全局的情况,只要实现了org.quartz.SchedulerListener接口的对象都是。
3.作业存储(JobStores)
JobStore负责跟踪我们对Scheduler进行配置的有关Job、Trigger和Calendar等信息的数据;选择适当的JobStore对我们的QuartzScheduler实例是很重要的,幸运的是,当我们理解了不同类型JobStore时,就可以很容易地对JobStore进行选择,我们可以通过对SchedulerFactory创建Scheduler实例所引用的配置文件中的属性进行声明,采用哪种JobStore。
3.1RAMJobStore
RAMJobStore是使用JobStore最简单的一种方式,它也是性能最高效的,顾名思义,JobStore是把它的数据都存储在RAM中,这也是它的快速和简单配置的原因;RAMJobStore的缺点是:
当我们的应用系统因为系统的崩溃而丢失了所有有关Scheduler的信息时,采用RAMJobStore方式将无法恢复原先Scheduler中有关Job和Trigger的设置;对一些应用来说,这是可以接收的,但是对其他一些应用来说,这就不是所期望的。
3.2JDBCJobStore
JDBCJobStore也是一种相当有名的JobStore,它通过JDBC把数据都保存到数据库中,所以在配置上会比RAMJobStore复杂一些,而且不像RAMJobStore那么快,但是当我们对数据库中的表的主键创建索引时,性能上的缺点就不是很关键的了。
JDBCJobStore几乎可以连接所有的数据库,广泛使用的数据库基本上有Oracle、MySQL、MSSQLServer2000、HSQLDB、PostreSQL和DB2。
使用JDBCStore,我们必须首选创建一系列的数据库表,为了提供给Quartz使用;我们可以在docs/dbTables目录中找到创建表SQL脚本文件,需要注意的是:
在这些脚本中所创建的表都以“QRTZ_”为表名的前缀,如:
QRTZ_TRIGGERS和QRTZ_JOB_DETAIL;我们可以对表名的前缀进行任意的修改,只要配置文件中有关前缀的属性值与实际的数据库表的前缀一致即可;采用前缀的方式可以在同一个数据库中保存多个Scheduler实例的数据,通过不同的前缀进行区分;
我们一旦完成了数据库表的创建,在我们配置和启用JDBCJobStore之前,需要决定在我们的应用中采用哪一种类型的事务;如果我们在执行Scheduling命令(如:
增加和删除Trigger)时不需要关联到其他的事务中,我们就可以采用JobStoreTX的方式让Quartz管理这个事务,一般情况下都是采用JobStoreTX的方式来管理事务的。
如果我们应用中需要Quartz与其他事务一起运行(如:
J2EE应用服务器),就需要采用JobStoreCMT的事务管理方式,这样Quartz将会让应用服务器容器管理事务;
最后一个难题是JDBCJobStore中有关连接数据库的DataSource的设置,Quartz属性中包含了Datasource的几种配置方法,一种是采用Quartz创建和管理DataSource的方式,提供了数据库连接的所有信息;另一种是Quartz使用应用服务器(Quartz运行当中的应用服务器)管理的DataSource,通过采用提供JDBCJobStore的JNDI名字的方式;有关配置属性的详细信息,可以参考“docs/config”目录中的配置文件。
为了使用JDBCJobStore,我们首选需要设置Quartz配置文件中JobStore类属性值为org.quartz.impl.jdbcjobstore.JobStoreTX或为org.quartz.impl.jdbcjobstore.JobStoreCMT,具体设为哪个值可根据我们的应用的需要及结合上面对JobStoreTX和JobStoreCMT的解析;比如:
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX;
下一步我们需要JobStore的DriverDelegate属性,DriverDelegate是负责执行所有与JDBC有关的处理,需要选择与指定数据库对应的Delegate;StdJDBCDelegate是使用一般的JDBC代码(和SQL语句)来执行处理的Delegate,当我们所使用的数据库没有对应的delegate时,可以试着使用StdJDBCDelegate;在org.quartz.impl.jdbcjobstore包或子包中可以找到其他的delegate,其他的delegate大概包含:
DB2v6Delegate(用于DB2version6和更低version的)、HSQLDBDelegate(用于HSQLDB)、MSSQLDelegate(用于MicrosoftSQLServer2000)、PostgreSQLDelegate(用于PostgreSQL7.x)、WeblogicDelegate(用于使用Weblogic的JDBC驱动程序)和OracleDelegate(用于Oracle8i和9i);
一旦选定delegate后,需要对driverDelegateClass属性进行设置:
org.quartz.jobStore.driverDelegate=org.quartz.impl.jdbcjobstore.StdJDBCDelegate;
接着我们需要向JobStore声明数据库表名的前缀,通过tablePrefix进行设置:
org.quartz.jobStore.tablePrefix=QRTZ_;
最后我们需要设置JobStore将使用哪个DataSource,在Quartz属性配置文件中也需要定义DataSource属性,如:
org.quartz.jobStore.dataSource=myDS。
4Spring中使用Quartz进行作业调度
Spring提供了支持时序调度(Scheduling)的整合类.现在,时序调度器通过FactoryBean建立,保持着可选的对Timers或者Triggers的引用。
更进一步的,对于QuartzScheduler和Timer两者存在一个方便的类允许我们调用目标对象(类似于通常的MethodInvokingFactoryBeans)上的某个方法。
4.1使用JobDetailBean
JobDetail对象包括了运行一个job所需要的所有信息。
于是Spring提供了一个所谓的JobDetailBean使得JobDetail拥有了一个真实的,有意义的默认值。
让我们来看个例子:
example.ExampleJob
5
Jobdetailbean拥有所有运行job(ExampleJob)的必要信息。
通过job的datamap来制定timeout。
Job的datamap可以通过JobExecutionContext(在运行时刻传递给你)来得到,但是JobDetailBean也把从job的datamap中得到的属性映射到实际job中的属性中去。
所以,如果ExampleJob中包含一个名为timeout的属性,JobDetailBean将自动为它赋值:
packageexample;
publicclassExampleJobextendsQuartzJobBean{
privateinttimeout;
/**
*SettercalledaftertheExampleJobisinstantiated
*withthevaluefromtheJobDetailBean(5)
*/
publicvoidsetTimeout(inttimeout){
this.timeout=timeout;
}
protectedvoidexecuteInternal(JobExecutionContextctx)
throwsJobExecutionException{
//dotheactualwork
}
}
所有Jobdetailbean中的一些其他的设定对你来说也是可以同样设置的.
注意:
使用name和group属性,你可以修改job在哪一个组下运行和使用什么名称。
默认情况下,job的名称等于jobdetaibean的名称(在上面的例子中为exampleJob)。
4.2使用MethodInvokingJobDetailFactoryBean
通常情况下,你只需要调用特定对象上的一个方法。
你可以使用MethodInvokingJobDetailFactoryBean准确的做到这一点:
class=”org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean”>
doIt
上面例子将导致exampleBusinessObject中的doIt方法被调用(如下):
publicclassBusinessObject{
//propertiesandcollaborators
publicvoiddoIt(){
//dotheactualwork
}
}
使用MethodInvokingJobDetailFactoryBean你不需要创建只有一行代码且只调用一个方法的job,你只需要创建真实的业务对象来包装具体的细节的对象。
默认情况下,QuartzJobs是无状态的,可能导致jobs之间互相的影响。
如果你为相同的JobDetail指定两个触发器,很可能当第一个job完成之前,第二个job就开始了。
如果JobDetail对象实现了Stateful接口,就不会发生这样的事情。
第二个job将不会在第一个job完成之前开始。
为了使得jobs不并发运行,设置MethodInvokingJobDetailFactoryBean中的concurrent标记为false。
class=”org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean”>
doIt
注意:
默认情况下,jobs在并行的方式下运行。
4.3使用triggers和SchedulerFactoryBean来包装任务
我们已经创建了jobdetails,jobs。
我们回顾了允许你调用特定对象上某一个方法的便捷的bean。
当然我们仍需要调度这些jobs。
这需要使用triggers和SchedulerFactoryBean来完成。
Quartz自带一些可供使用的triggers。
Spring提供两个子类triggers,分别为CronTriggerBean和SimpleTriggerBean。
Triggers也需要被调度。
Spring提供SchedulerFactoryBean来暴露一些属性来设置triggers。
SchedulerFactoryBean负责调度那些实际的triggers。
两个例子:
–seetheexampleofmethodinvokingjobabove–>
–10seconds–>
10000
–repeatevery50seconds–>
50000
–runeverymorningat6am–>
06**1
现在我们创建了两个triggers,其中一个开始延迟10秒以后每50秒运行一次,另一个每天早上6点钟运行。
我们需要创建一个SchedulerFactoryBean来最终实现上述的一切:
beanclass=”org.springframework.scheduling.quartz.SchedulerFactoryBean”>
更多的一些属性可以通过SchedulerFactoryBean来设置,例如
7
org.quartz.impl.jdbcjobstore.oracle.weblogic.RideOracleDelegate
BRK_
可以看相应的JavaDOC(http:
//www.springframework.org/docs/api/org/springframework/scheduling/quartz/SchedulerFactoryBean.html)来了解进一步的信息。
文章引用自:
评论(0)引用阅读(36)圈子编辑打印有奖举报
归类于:
Quartz—luminate@13:
18评论(0)
(转)作业调度(Quartz)技术总结
(二)
1.触发器(Triggers)
与Job相比,Trigger相对来说比较简单容易,但是要能完全的掌握使用Quartz,使其包含各种自定义的时间表选项,我们必须先知道和理解Trigger。
1.1日历(Calendars)
QuartzCalendar对象(不是java.util.Calendar对象)能够与被注册进Scheduler的Trigger关联。
Calendar对排除Trigger的时间段是很有用的,例如,我们可以创建一个在每个工作日上午9:
30触发Job的Trigger,就在其中增加一个排除所有工作假期的Calendar。
Calendar可以是任何实现Calendar接口的可序列化对象,如下所示:
packageorg.quartz;publicinterfaceCalendar{publicbooleanisTimeIncluded(longtimeStamp);publiclonggetNextIncludedTime(longtimeStamp);}该接口的参数都是long类型的,以毫秒为单位的timestamp;所以Calendar定义的时间可以准确到毫秒。
很可能,我们需要排除一整天,为了方便,Quartz包含了实现该功能的类ori.quartz.impl.HolidayCalendar。
Calendar必须实例化并且通过addCalendar(…)方法注册到Scheduler中,如果使用HolidayCalendar,在实例化之后,我们需要使用方法addExcludedDate(Datedate)排除我们计划日程中不需要的日期,一个Calendar实例可以用到不同的Trigger中,比如:
HolidayCalendarcal=newHolidayCalendar();cal.addExcludedDate(someDate);sched.addCalendar("myHolidays",cal,false);SimpleTriggertrigger=newSimpleTrigger("myTrigger",sched.DEFAULT_GROUP,newDate(),null,SimpleTrigger.REPEAT_INDEFINITELY,60L*1000L);trigger.setCalendarName("myHolidays");//..schedulejobwithtriggerSimpleTriggertrigger2=newSimpleTrigger("myTrigger",sched.DEFAULT_GROUP,newDate(),null,5,5L*24L*60L*60L*1000L);trigger2.setCalendarName("myHolidays");//..schedulejobwithtrigger2上面代码,我们创建了两个Trigger:
一个是每1分钟执行触发一次,没有次数限制;另一个是每5天执行触发一次,共执行5次触发;然而,任何在Calendar中被排除的时间段的触发执行都将被取消。
1.2过时触发指令(MisfireInstructions)
Trigger另一个重要的属性是“MisfireInstruction”。
过时触发发生在持久Trigger失去了触发时间,由于对应的Scheduler被关闭的原因;不同的Trigger类型有不同的过时触发指令,默认情况下是使用“smartpolicy”指令,该指令根据Trigger类型和配置具有动态的行为。
当scheduler启动时,它将搜索所有过时触发的持久Trigger,并同时根据它们各自所配置的过时触发指令进行更新;当我们在项目中要使用Quartz时,我们必须熟悉所要使用的Trigger类型的过时触发指示,在对应的JavaDOC中有对其进行说明。
可以通过方法setMisfireInstruction(…)来设置Trigger的过时触发指示。
1.3触发器的辅助类(TriggerUtils)
TriggerUtils类(在org.quartz.helpers包中)为我们创建Trigger和触发时间提供了方便,可以使我们不用