title: Quartz实现定时任务 date: 2017.05.31 01:06 categories:
- 技术博客 tags:
- 框架使用
- Quartz
定时任务这种需求不管是企业内部还是互联网项目,都算是比较常见的,举一个例子:余额宝在凌晨会自动转入余额。
从用户使用产品的角度来看,功能与其他并无区别,但从技术表现上看,区别一般就是原先人(一般是运营)做的事情换成了机器自动完成,并且一般是定时间点(比如晚上十二点)或者定时间间隔(隔一个月一次)。
如果你的项目后端是用Java写的,那么实现方式上可以有三种选择:
- JDK中的
Timer
与TimerTask
- 开源的
Quartz
框架 - Spring3.0后支持的
Task
我的博客主要是写思路,写得过于复杂对我来说意义不大,我更在乎可读性,因而本文以
Quartz
为主,其他两种方式的代码实现不涉及,我相信这样更有利于你我的进步。
开整。
1. 作业类
你也可以叫它任务类,其作用就是定义你这个定时任务中的任务到底是干啥的,比如扫描、转账、打日志等等动作,所以实现起来第一你要有个类,第二有个方法来写逻辑。
在类的定义上,我们开发也可选两种方式:
- 继承
org.springframework.scheduling.quartz.QuartzJobBean
- 直接自定义
后者看起来更自由,那我们就用它了。
写一个Java Class:
public class JobTest {
public void task(){
System.out.println("作业类中执行的任务");
}
}
复制代码
Spring框架中专门实现了MethodInvokingFactoryBean
作为这种方式创建出的作业类的支持,它的包放在了package org.springframework.beans.factory.config
中,很清晰地告诉我们这是用来配置的。
2. 作业类工厂
项目中使用了Spring的情况下,由于IOC的机制,我们将实例化对象的职责交给了框架,所以直接在XML中配置一下,告诉Spring我们需要调用哪个类下的任务方法。
配置的前提是,首先要在Maven
中引入依赖,我用的是1.8。
<bean id="jobTest" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<!--跑哪个作业类-->
<property name="targetObject">
<bean class="com.mycompany.myproject.JobTest"/>
</property>
<!--跑哪个任务方法-->
<property name="targetMethod" value="task"/>
<property name="concurrent" value="false"/>
</bean>
复制代码
3. 触发器
前面对于需求的简析中也提到了,这种定时任务,要么是定时间点,要么是定时间间隔,而触发器的作用就是来管理作业调度的方式。
框架中提供了两个类分别给予支持:
Quartz
1.8以前版本
org.springframework.scheduling.quartz.SimpleTriggerBean
org.springframework.scheduling.quartz.CronTriggerBean
Quartz
2.x版本
org.springframework.scheduling.quartz.SimpleTriggerFactoryBean
org.springframework.scheduling.quartz.CronTriggerFactoryBean
检查你IDE中到底引用了哪个版本只需要Ctrl+Shift+T
看看哪个存在即可,网上有些博客应该是抄的吧,依赖跟配置的类完全对不上,结果居然还能跑出来。
以1.8版本为例,simpleTrigger
用来配置定时间间隔:
<bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
<!--你前面配好的作业类引用-->
<property name="jobDetail" ref="jobTest"/>
<!--开始延迟毫秒数:跑到你的方法上要延迟多久-->
<property name="startDelay" value="0"/>
<!--重复间隔毫秒数-->
<property name="repeatInterval" value="2000"/>
</bean>
复制代码
cronTrigger
则用来配置定时间点:
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<!--你前面配好的作业类引用-->
<property name="jobDetail" ref="jobTest"/>
<!--cron表达式用来指定时间点-->
<property name="cronExpression" value="0 0 12 * * ?"/>
</bean>
复制代码
关于cron
我再简单提一句,这个东西源于Linux
中计划任务服务,这个词儿代表一百万年,总之这是一种机制,类Unix
系统中都能使用其命令,而我们用的时候只需要按照格式来编写即可,非常类似regex
的使用,没有必要去强记。
4. 调度工厂
经过前面的配置(这种东西用起来主要就是配置),我们的框架已经知道我们需要调用哪个作业类中的哪个任务方法,并且知道了使用哪种触发器,最后如何调用呢?
我们也就需求配置一下框架中给定的调度工厂了,对应的类是:org.springframework.scheduling.quartz.SchedulerFactoryBean
。
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="cronTrigger"/>
</list>
</property>
</bean>
复制代码
调度工厂的作用好比是带兵打仗的将军,起背后一个协调控制的作用。
到此,一个基本的定时任务就完成了,以此延展,你还可以去琢磨一下其他实现方案,然后应对不同的场景比如分布式,可能需要你更多的思考。