前言
因为自己的毕设项目要用到Quartz,并且在实习工作的时候也是用到了Quartz,所以在这里进行总结。
Quartz是一个任务调度框架。比如你遇到这样的问题:
- 想每月25号,信用卡自动还款
- 每天自动生成报表,并发邮箱给某某人。
- 每个小时自动去查询当前系统的在线人数
这些问题总结起来就是:在某一个有规律的时间点干某件事。并且时间的触发的条件可以非常复杂
(比如每月最后一个工作日的17:50),复杂到需要一 个专门的框架来干这个事。 Quartz就是来
干这样的事,你给它一个触发条件的定义,它负责到了时间点,触发相应的Job起来干活。
一、Quartz概述
1.1 Quartz简介
- 官网上解释说,quartz是开源且具有丰富特性的”任务调度库”,能够集成于任何的java应用,
小到独立的应用,大至电子商业系统。 - quartz能够创建亦简单亦复杂的调度,以执行上十、上百,甚至上万的任务。任务job被定义
为标准的java组件,能够执行任何你想quartz调度框架包含许多企业级的特性,如JTA事务、
集群的支持。要实现的功能。 - Quartz是一个完全由Java编写的开源任务调度的框架,通过触发器设置作业定时运行规则,
控制作业的运行时间。其中quartz集群通过故障切换和负载平衡的功能,能给调度器带来高可
用性和伸缩性。主要用来执行定时任务,如:定时发送信息、定时生成报表等等。 - 简而言之,quartz就是基于java实现的任务调度框架,用于执行你想要执行的任何任务。
其次,quartz也支持.Net平台。
1.2 Quart特点
- 简单易用,调度功能强大
支持丰富多样的调度方法,可以满足各种常规及 特殊需求 - 灵活性
作为Spring默认的调度框架,支持任务和调度的多种组合方式,支持调度数据的多种存储方式 - 分布式和集群能力
伸缩性,高可用性,负载均衡
二、Quartz体系结构概述
Quartz的核心主要包括三部分:作业(Job)、触发器(Trigger)和调度器(Scheduler),
其中Scheduler是整个系统框架的心脏和灵魂。调度器作为作业的总指挥,触发器作为作业的操作者,
作业为应用的功能模块。
其关系如下图所示:
Job为作业的接口,为任务调度的对象。
JobDetail用来描述Job的实现类及其它相关的静态信息。
Trigger做为作业的定时管理工具,一个Trigger只能对应一个作业实例,
而一个作业实例可对应多个触发器。Scheduler做为定时任务容器,是quartz最上层的东西,它提携了所有触发
器和作业,使它们协调工作,每个Scheduler都存有JobDetail和Trigger的
注册,一个Scheduler中可以注册多个JobDetail和多个Trigger。
2.1 Job(作业或者任务)
- Job是一个接口,只有一个方法void execute(JobExecutionContext context),
JobExecutionContext类提供了调度上下文的各种信息。每次执行该Job均重新创建
一个Job实例。 JobExecutionContext类
JobExecutionContext类提供了调度上下文的各种信息,如获取执行中的JobDetail实例
和执行完成后的Trigger对象。当Scheduler决定什么时候执行Job的时候,他会传
JobExecutionContext给Job;JobExecutionContext包含了Quartz的运行环境和Job本身
的明细数据,相当于ServletContext一样。举例:
public class DDNJob implements Job{
public void execute(JobExecutionContext arg0) throws JobExecutionException {
perform();
}
public void perform(){ //执行报表统计入口函数
//业务逻辑
System.out.println("自动DDN预授权开始执行-------------执行时间:"+new Date());
}
}
- 注:DDNJob类为需要定时执行的类,execute为定时执行的方法。一个定时任务对应一个Job实现类。
2.2 JobDetail
- Quartz在每次执行Job时,都重新创建一个Job实例,所以它不直接接受一个Job的实例,相反
它接收一个Job实现类,以便运行时通过newInstance()的反射机制实例化Job。因此需要通过一
个类来描述Job的实现类及其它相关的静态信息,如Job名字、描述、关联监听器等信息,
JobDetail承担了这一角色。JobDetail 用来保存我们作业的详细信息。一个JobDetail
可以有多个Trigger,但是一个Trigger只能对应一个JobDetail。
JobDetail jobDetail = new JobDetail("myJob","myGroup",DDNJob.class)
说明:
myJob:job 名
myGroup:job 组(为'null'时,使用缺省的组sched.DEFAULT_GROUP)
DDNJob.class:要被执行的Java类。
- 运用spring集成的MethodInvokingJobDetailFactoryBean时spring能自动生成
符合quartz要去的JobDetail。
Spring中applicationContext.xml配置如下:
<!-- detail任务描述 -->
<bean name="DDNDetail"
class="com.mangocity.mpm.common.autoDDN.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" value="DDNJob" />
<property name="concurrent" value="false"/>(并发执行)
<property name="shouldRecover" value="true"/>
</bean>
2.3 Trigger(触发器)
1)概述
- Trigger是一个类,描述触发Job执行的时间触发规则。主要有SimpleTrigger和
CronTrigger这两个子类。 - 仅需触发一次或者以固定时间间隔周期执行,SimpleTrigger是最适合的选择;
而CronTrigger则 可以通过Cron表达式定义出各种复杂时间规则的调度方案:
如每早晨9:00执行,周一、周三、周五下午5:00执行等。
2)常见的触发器属性
使用 TriggerKey 追踪定位一个触发器,使用TriggerBuilder创建触发器时设置各个属性
- jobKey
- startTime 在起始时间范围类开始触发
- endTime 在超过这个时间范围后,这个触发器不再有效。
3)SimpleTrigger
- SimpleTrigger特性
start-time 启动时间
end-time 结束时间
repeat count 重复次数:整型, SimpleTrigger.REPEAT_INDEFINITELY(-1)表示无限循环
repeat interval 重复间隔,如果太短会照成多个实例并发执行
4)SimpleTrigger举例
- 指定时间执行,没有重复
SimpleTrigger trigger = (SimpleTrigger) newTrigger()
.withIdentity("trigger1", "group1")
.startAt(new Date()) // some Date
.build();
- 指定时间执行,重复10次,每次间隔10秒
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger3", "group1")
.startAt(new Date()) // 如果开始时间没有给出,那么就以当前时间
.withSchedule(simpleSchedule()
.withIntervalInSeconds(10)
.withRepeatCount(10)) // 注意,重复10次将总共11触发
.forJob(job) // identify job with handle to its JobDetail itself
.build();
- 创建未来指定时间
SimpleTrigger trigger = (SimpleTrigger) newTrigger()
.withIdentity("trigger5", "group1")
.startAt(DateBuilder.futureDate(10, DateBuilder.IntervalUnit.SECOND)) // 开始时间是未来10秒
.forJob(job)
.build();
DateBuilder : 常用的时间生成,如 下一个整点,未来5秒等
- 从当前时间开始,每隔5分钟执行一次,一直循环,直到22:00:00结束
trigger = newTrigger()
.withIdentity("trigger7", "group1")
.withSchedule(simpleSchedule()
.withIntervalInMinutes(5)
.repeatForever())
.endAt(dateOf(22, 0, 0)) //失效时间,未指定开始时间则按当前时间
.build();
- 开始时间为下一个整点:00:00,间隔两小时执行一次,永远循环
trigger = newTrigger()
.withIdentity("trigger8") // 没有指定组,将在默认组
.startAt(evenHourDate(null)) // 获取下一个整点,如现在是0:24,获取到的时间是: 1:00:00
.withSchedule(simpleSchedule()
.withIntervalInHours(2)
.repeatForever())
.build();
scheduler.scheduleJob(trigger, job);
5)CronTrigger 表达式触发器
以日历作为对象描述执行时间,而不是按 simpleTrigger 那样简单的循环间隔或则指定时间,
如 每周五中午,每个工作日等。但是和 simpleTrigger 一样也能指定开始时间和失效时间。
由7个子表达式来描述日程安排的细节:
- Seconds
- Minutes
- Hours
- Day-of-Month : 自然月中的日期
- Month
- Day-of-Week : 一周中的第几天,与Day-of-Month互斥
- Year (optional field)
比如:每周三 12:00:00 : 0 0 12 ? * WED
通配符: 一般都能作用于所有字段,除非特殊说明
2.4 Scheduler(调度器)
- Scheduler就是Quartz的大脑,所有任务都是由它来设施。
Schduelr包含一个两个重要组件: JobStore和ThreadPool。
JobStore
JobStore是会来存储运行时信息的,包括Trigger,Schduler,JobDetail,业务锁等。
它有多种实现RAMJob(内存 实现),JobStoreTX(JDBC,事务由Quartz管理),JobStoreCMT
(JDBC,使用容器事 务),ClusteredJobStore(集群实现)、TerracottaJobStore。- ThreadPool
ThreadPool就是线程池,Quartz有自己的线程池实现。所有任务的都会由线程池执行。