spring整合quartz.docx

上传人:b****7 文档编号:10407878 上传时间:2023-02-11 格式:DOCX 页数:20 大小:76.26KB
下载 相关 举报
spring整合quartz.docx_第1页
第1页 / 共20页
spring整合quartz.docx_第2页
第2页 / 共20页
spring整合quartz.docx_第3页
第3页 / 共20页
spring整合quartz.docx_第4页
第4页 / 共20页
spring整合quartz.docx_第5页
第5页 / 共20页
点击查看更多>>
下载资源
资源描述

spring整合quartz.docx

《spring整合quartz.docx》由会员分享,可在线阅读,更多相关《spring整合quartz.docx(20页珍藏版)》请在冰豆网上搜索。

spring整合quartz.docx

spring整合quartz

Spring整合quartz

1Quartz简介

Quartz是OpenSymphony开源组织在Jobscheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用。

Quartz可以用来创建简单或为运行十个,百个,甚至是好几万个Jobs这样复杂的日程序表。

Jobs可以做成标准的Java组件或EJBs。

Quartz在开源任务调度框架中的翘首,它提供了强大任务调度机制,难能可贵的是它同时保持了使用的简单性。

Quartz允许开发人员灵活地定义触发器的调度时间表,并可以对触发器和任务进行关联映射。

此外,Quartz提供了调度运行环境的持久化机制,可以保存并恢复调度现场,即使系统因故障关闭,任务调度现场数据并不会丢失。

此外,Quartz还提供了组件式的侦听器、各种插件、线程池等功能。

1.1主要解决问题

Quartz是一个任务日程管理系统,一个在预先确定(被纳入日程)的时间到达时,负责执行(或者通知)其他软件组件的系统。

网页游戏中会大量涉及到Scheduler的操作:

网页游戏中挂机自动修炼如8个小时,人物相关数值进行成长;当使用某道具后,时间减少到4个小时,人物对应获得成长值等。

企业中如每天凌晨2点触发数据同步、发送Email等操作。

hrsebs中每天18点加号统计提醒,定时短信通知科秘;hrshrecord每天17点病例提醒,诊后反馈提醒;每天19点开始每5分钟医生当天诊后随访汇总等等。

1.2下载和安装

Quartz的下载:

http:

//www.quartz-scheduler.org/

下载完成,将得到quartz-*.tar.gz,解压后得到的目录结构是:

1)doc:

API和各种数据库的建表sql,Quartz应用到集群,和持久化作业的时候会用到。

2)examples:

官方给写的例子了,也就是我们本次学习的重点

3)lib:

Quartz所依赖的jar,相信你的工程中已经添加了吧,主要是logc3p0什么的

4)quartz:

源码…………

在2.x版本之后,Quartz的语法已经有了很大的不同。

其中最主要的一点就是,Quartz废弃了很多类的构造方法,而改为采用这些类的建造者类(Builder)来初始化它们,包括Scheduler、Job及Trigger。

此版本Quartz中大量使用链式写法,与jQuery的写法有几分相似,实现也比较简单,如:

Triggertrigger=TriggerBuilder

.newTrigger()

.withIdentity("trigger1","group1")

.startNow()

.withSchedule(

CronScheduleBuilder.cronSchedule("0309**?

"))

.build();

1.3主要概念

Quartz对任务调度的领域问题进行了高度的抽象,提出了调度器、任务和触发器这3个核心的概念,并在org.quartz通过接口和类对重要的这些核心概念进行描述:

●Job:

是一个接口,只有一个方法voidexecute(JobExecutionContextcontext),开发者实现该接口定义运行任务,JobExecutionContext类提供了调度上下文的各种信息。

Job运行时的信息保存在JobExecutionContext实例中;

●JobDetail:

Quartz在每次执行Job时,都重新创建一个Job实例,所以它不直接接受一个Job的实例,相反它接收一个Job实现类,以便运行时通过newInstance()的反射机制实例化Job。

因此需要通过一个类来描述Job的实现类及其它相关的静态信息,如Job名字、描述、关联监听器等信息,JobDetail承担了这一角色。

通过该类的构造函数可以更具体地了解它的功用:

JobDetail(java.lang.Stringname,java.lang.Stringgroup,java.lang.ClassjobClass),该构造函数要求指定Job的实现类,以及任务在Scheduler中的组名和Job名称,新版本已经变成接口;

●Trigger:

是一个类,描述触发Job执行的时间触发规则。

主要有SimpleTrigger和CronTrigger这两个子类。

当仅需触发一次或者以固定时间间隔周期执行,SimpleTrigger是最适合的选择;而CronTrigger则可以通过Cron表达式定义出各种复杂时间规则的调度方案:

如每早晨9:

00执行,周一、周三、周五下午5:

00执行等;

●Calendar:

org.quartz.Calendar和java.util.Calendar不同,它是一些日历特定时间点的集合(可以简单地将org.quartz.Calendar看作java.util.Calendar的集合——java.util.Calendar代表一个日历时间点,无特殊说明后面的Calendar即指org.quartz.Calendar)。

一个Trigger可以和多个Calendar关联,以便排除或包含某些时间点。

假设,我们安排每周星期一早上10:

00执行任务,但是如果碰到法定的节日,任务则不执行,这时就需要在Trigger触发机制的基础上使用Calendar进行定点排除。

针对不同时间段类型,Quartz在org.quartz.impl.calendar包下提供了若干个Calendar的实现类,如AnnualCalendar、MonthlyCalendar、WeeklyCalendar分别针对每年、每月和每周进行定义;

●Scheduler:

代表一个Quartz的独立运行容器,Trigger和JobDetail可以注册到Scheduler中,两者在Scheduler中拥有各自的组及名称,组及名称是Scheduler查找定位容器中某一对象的依据,Trigger的组及名称必须唯一,JobDetail的组和名称也必须唯一(但可以和Trigger的组和名称相同,因为它们是不同类型的)。

Scheduler定义了多个接口方法,允许外部通过组及名称访问和控制容器中Trigger和JobDetail。

Scheduler可以将Trigger绑定到某一JobDetail中,这样当Trigger触发时,对应的Job就被执行。

一个Job可以对应多个Trigger,但一个Trigger只能对应一个Job。

可以通过SchedulerFactory创建一个Scheduler实例。

Scheduler拥有一个SchedulerContext,它类似于ServletContext,保存着Scheduler上下文信息,Job和Trigger都可以访问SchedulerContext内的信息。

SchedulerContext内部通过一个Map,以键值对的方式维护这些上下文数据,SchedulerContext为保存和获取数据提供了多个put()和getXxx()的方法。

可以通过Scheduler#getContext()获取对应的SchedulerContext实例;

●ThreadPool:

Scheduler使用一个线程池作为任务运行的基础设施,任务通过共享线程池中的线程提高运行效率。

Job有一个StatefulJob子接口,代表有状态的任务,该接口是一个没有方法的标签接口,其目的是让Quartz知道任务的类型,以便采用不同的执行方案。

无状态任务在执行时拥有自己的JobDataMap拷贝,对JobDataMap的更改不会影响下次的执行。

而有状态任务共享同一个JobDataMap实例,每次任务执行对JobDataMap所做的更改会保存下来,后面的执行可以看到这个更改,也即每次执行任务后都会对后面的执行发生影响。

正因为这个原因,无状态的Job可以并发执行,而有状态的StatefulJob不能并发执行,这意味着如果前次的StatefulJob还没有执行完毕,下一次的任务将阻塞等待,直到前次任务执行完毕。

有状态任务比无状态任务需要考虑更多的因素,程序往往拥有更高的复杂度,因此除非必要,应该尽量使用无状态的Job。

如果Quartz使用了数据库持久化任务调度信息,无状态的JobDataMap仅会在Scheduler注册任务时保持一次,而有状态任务对应的JobDataMap在每次执行任务后都会进行保存。

Trigger自身也可以拥有一个JobDataMap,其关联的Job可以通过JobExecutionContext#getTrigger().getJobDataMap()获取Trigger中的JobDataMap(该JobDataMap和JobDetail所拥有的JobDataMap不是同一个哦)。

不管是有状态还是无状态的任务,在任务执行期间对Trigger的JobDataMap所做的更改都不会进行持久,也即不会对下次的执行产生影响。

1.4调用原理

图1Scheduler结构图

一个Scheduler可以拥有多个Triger组和多个JobDetail组,注册Trigger和JobDetail时,如果不显式指定所属的组,Scheduler将放入到默认组中,默认组的组名为Scheduler.DEFAULT_GROUP。

组名和名称组成了对象的全名,同一类型对象的全名不能相同。

Scheduler本身就是一个容器,它维护着Quartz的各种组件并实施调度的规则。

Scheduler还拥有一个线程池,线程池为任务提供执行线程——这比执行任务时简单地创建一个新线程要拥有更高的效率,同时通过共享节约资源的占用。

通过线程池组件的支持,对于繁忙度高、压力大的任务调度,Quartz将可以提供良好的伸缩性。

提示:

Quartz完整下载包examples目录下拥有10多个实例,它们是快速掌握Quartz应用很好的实例。

1.5Cron表达式

Quartz使用类似于Linux下的Cron表达式定义时间规则,Cron表达式是一个字符串,字符串以5或6个空格隔开,分为6或7个域,每一个域代表一个含义,Cron有如下两种语法格式:

SecondsMinutesHoursDayofMonthMonthDayofWeekYear或

SecondsMinutesHoursDayofMonthMonthDayofWeek,每一个域可出现的字符如表1所示:

表1Cron表达式时间字段

由于"月份中的日期"和"星期中的日期"这两个元素互斥的,必须要对其中一个设置为?

,举例说明:

"0012**?

"每天中午12点触发

"01510?

**"每天上午10:

15触发

"01510**?

"每天上午10:

15触发

"01510**?

*"每天上午10:

15触发

"01510**?

2005"2005年的每天上午10:

15触发

"0*14**?

"在每天下午2点到下午2:

59期间的每1分钟触发

"00/514**?

"在每天下午2点到下午2:

55期间的每5分钟触发

"00/514,18**?

"在每天下午2点到2:

55期间和下午6点到6:

55期间的每5分钟触发

"00-514**?

"在每天下午2点到下午2:

05期间的每1分钟触发

"010,4414?

3WED"每年三月的星期三的下午2:

10和2:

44触发

"01510?

*MON-FRI"周一至周五的上午10:

15触发

"0151015*?

"每月15日上午10:

15触发

"01510L*?

"每月最后一日的上午10:

15触发

"01510?

*6L"每月的最后一个星期五上午10:

15触发

"01510?

*6L2002-2005"2002年至2005年的每月的最后一个星期五上午10:

15触发

"01510?

*6#3"每月的第三个星期五上午10:

15触发

如果Cron表达式不正确,触发器也可以编译但是触发器就不会触发,因此最好有针对CronExpession合法性的校验类。

2Quartz的任务调度存储

2.1JobStore的概念

JobStore的作用是保存所有你给scheduler的“工作数据”:

Job、Trigger、Calendar等等。

为你的QuartzScheduler实例选择合适的JobStore是很重要的一步。

幸运的是,如果你明白了各个JobStore之间的不同,那么选择起来将会非常容易。

声明使用哪个JobStore需要使用到属性文件,这个属性文件可以提供给SchedulerFactory用于创建scheduler实例。

不要在你的代码中直接使用JobStore对象。

基于某些原因,有很多开发者会这么做。

JobStore在Quartz中应该是在幕后工作。

你需要告诉Quartz使用那个JobStore(通过配置文件quartz.properties),然后在你的代码中只使用Scheduler对象。

Quartz提供两种基本作业存储类型。

第一种类型叫做RAMJobStore,第二种类型叫做JDBC作业存储。

在默认情况下Quartz将任务调度的运行信息保存在内存中,这种方法提供了最佳的性能,因为内存中数据访问最快。

不足之处是缺乏数据的持久性,当程序路途停止或系统崩溃时,所有运行的信息都会丢失。

2.2RAMJobStore

RAMJobStore是使用上最简单的JobStore,它也拥有最高的性能(从CPU时间来计算)。

从RAMJobStore的名字来看:

它将保存所有数据在RAM中。

这也是为什么它最轻快并且配置最简单。

但是缺点是,当你的应用结束或崩溃,那么所有的scheduler数据将会丢失——这意味着,RAMJobStore不会遵守在Job和Trigger上的“non-volatility”设置。

对有的应用程序来说,这是可接受的(甚至期望如此),但是对另一些应用程序来说,可能是个灾难。

要使用RAMJobStore(假设你正在使用StdSchedulerFactory),只需简单的在Quartz配置文件中设置JobStore配置项的值为org.quartz.simpl.RAMJobStore即可:

org.quartz.jobStore.class=org.quartz.simpl.RAMJobStore

接下来,你不需要再考虑其它的配置。

2.3JDBCJobStore

JDBCJobStore将所有的数据通过JDBC保存到数据库中。

因此,配置上比RAMJobStore稍微复杂一些,它的速度也比较慢。

然而,这个性能的落后并不是特别大,尤其是当你在创建数据库表的时候为主键创建了索引的情况下。

如果一组机器组建的LAN(在scheduler和数据库之间)条件不错,那么获取并更新触发Trigger整个过程一般不会超过10毫秒。

JDBCJobStore可以几乎跟任何数据库结合使用,包括Oracle、PostgreSQL、MySQL、MSSQLServer、HSQLDB和DB2。

要使用JDBCJobStore,你必须先为Quartz创建一组数据库表。

创建表的脚本在Quartz发布包的“docs/dbTables”目录下。

如果脚本不适合你所使用的数据库类型,你可以根据需要自己修改脚本。

有一点需要注意,在这些脚本中,所有的数据库表都有“QRTZ_”前缀(例如表“QRTZ_TRIGGERS”和“QRTZ_JOB_DETAIL”)。

实际上,你可以使用你喜欢的任意前缀,只需要在Quartz属性文件中告诉JDBCJobStroe使用哪个前缀即可。

如果你需要在同一个数据库中为多个scheduler实例使用不同的数据库表保存数据,那么使用不同的前缀将会非常有用。

将所有的数据通过JDBC保存到数据库中也称作Quartz持久化。

3Quartz持久化

如果确实需要持久化任务调度信息,Quartz允许你通过调整其属性文件,将这些信息保存到数据库中。

使用数据库保存任务调度信息后,即使系统崩溃后重新启动,任务的调度信息将得到恢复。

3.1数据库表

版本不同相应的表结构稍有不同,最新的表结构为11张:

qrtz_job_details存储每一个已配置的Job的详细信息

qrtz_triggers存储已配置的Trigger信息

qrtz_simple_triggers存储简单的Trigger,包括重复次数,间隔,已触发次数

qrtz_cron_triggers存储cron表达式和时区信息

qrtz_blob_triggers存储作为Blob类型的Trigger

qrtz_calendars存储Calendars信息

qrtz_fired_triggers存储已触发的Trigger相关状态信息

qrtz_paused_trigger_grps存储已暂停的Trigger组的信息

qrtz_scheduler_state存储少量的有关Scheduler的状态信息

qrtz_locks存储程序的锁信息

qrtz_simprop_triggers存储Scheduler相关的Trigger的基本信息

3.2JDBCJobStore选择

一旦数据库表创建好,在使用JDBCJobStore之前,还需要做一个决定。

你需要决定你的应用程序要使用哪种类型的事务机制。

如果你不需要绑定你的scheduler命令(例如增加和删除Trigger)到其它的事务,那么JosStore可以通过JobStoreTX管理事务(这也是最常用的选择)。

如果你需要Quzrtz协同其它事务一起工作(例如,在JavaEE应用服务器中),那么你需要使用JobStoreCMT——这样,Quartz将会让应用程序服务器来管理事务。

3.3JDBCJobStore配置

最后一点是如何创建DataSource,好让JDBCJobStore从你的数据库中获取连接。

.DataSource在Quartz属性文件中,使用quartz.properties文件有几种不同的配置方法。

1)直接配置本地数据源:

org.quartz.jobStore.dataSource=NAME

org.quartz.dataSource.NAME.driver=数据库驱动(requried)

org.quartz.dataSource.NAME.URL=连接数据库的url(requried)

org.quartz.dataSource.NAME.user=连接的数据库的用户名(notrequried)

org.quartz.dataSource.NAME.password=连接的数据库的密码(notrequried)

org.quartz.dataSource.NAME.maxConnections=连接池中最大连接数(notrequried)

org.quartz.dataSource.NAME.validationQuery=sql查询语句(notrequried)

注:

org.quartz.dataSource.NAME中的NAME是自己随便定义的一个数据源的名字。

2)使用自定义的ConnectionProvider配置数据源:

自定义一个ConnectionProvider类,并在quartz.properties文件中依据ConnectionProvider类配置它。

org.quartz.dataSource.myConProvider(数据源名).connectionProvider.class=XXXXX(自定义的ConnectionProvider)。

3)使用应用服务器中DataSource的属性:

org.quartz.dataSource.NAME.jndiURL=dataSource的JNDIurl

org.quartz.dataSource.NAME.java.naming.factory.initial=使用的JNDIInitialContextFactory类名。

org.quartz.dataSource.NAME.java.naming.provider.url=连接JNDI的URL

org.quartz.dataSource.NAME.java.naming.security.principal=连接JNDI的用户名

org.quartz.dataSource.NAME.java.naming.security.credentials=连接到JNDI的用户凭证

详细的配置可以参考“docs/config”目录下的配置文件。

接下来,你需要设置JogStore使用的DriverDelegate。

DriverDelegate的作用是为特定的数据库执行JDBC的工作。

StdJDBCDelegate使用标准JDBC代码(和SQL语句)来做这个工作,如果没有其它合适的delegate适用于你的数据库,那么你可以试试使用StdJDBCDelegate。

其它的delegate可以在“org.quartz.impl.jdbcjobstore”包,或者在它的子包中找到。

其它delegate包括DB2v6Delegate(DB2版本6或早期版本)、HSQLDBDelegate(HSQLDB)、MSSQLDelegate(MicrosoftSQLServer)、PostgreSQLDelegate(PostgreSQL)、WeblogicDelegate(使用Weblogic创建的JDBC驱动)、OracleDelegate(Oracle)、等等。

接下来,需要配置JobStore使用的数据库表前缀:

org.quartz.jobStore.tablePrefix=QRTZ_

此外,可以设置org.quartz.jobStore.useProperties属性值为true(默认是false),目的是为了让JDBCJobStore中的JobDataMap中的所有值都是String类型,这样方便存储键值对,而不是使用序列化的方式将复杂的对象存储到BLOB字段中。

在长期看来,这将会更安全,因为你避免了类的版本的问题。

4Quartz集群

Quartz是通过借助关系数据库和JDBC作业存储来实现集群管理的。

4.1集群基本原理

集群通过故障切换和负载平衡的功能,能给调度器带来高可用性和伸缩性。

目前集群只能工作在JDBC-JobStore(JobStoreTX或者JobStoreCMT)方式下,quartz持久化是实现集群的基础。

从本质上来说,是使集群上的每一个节点通过共享同一个数据库来工作的(Quartz通过启动两个维护线程来维护数据库状态实现集群管理,一个是检测节点状态线程,一个是恢复任务线程)。

如下图2所示。

图2Quartz集群示意图

负载平衡是自动完成的,集群的每个节点会尽快触发任务。

当一个触发器的触发时间到达时,第一个节点将会获得任务(通过锁定),成为执行任务的节点。

故障切换的发生是在当一个节点正在执行一个或者多个任务失败的时候。

当一个节点

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 军事

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1