首页 > 代码库 > Spring整合Quartz实现定时任务
Spring整合Quartz实现定时任务
近日在做项目时要用到定时任务,也借此机会了解了一些常用定时任务,由于项目使用了spring框架,所以下面我将结合spring框架来介绍。
一.分类
-
从实现的技术上来分类,目前主要有三种技术(或者说有三种产品)
- Java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务。使用这种方式可以让你的程序按照某一个频度执行,但不能在指定时间运行。一般用的较少,这篇文章将不做详细介绍。
- 使用Quartz,这是一个功能比较强大的的调度器,可以让你的程序在指定时间执行,也可以按照某一个频度执行,配置起来稍显复杂,稍后会详细介绍。
- Spring3.0以后自带的task,可以将它看成一个轻量级的Quartz,而且使用起来比Quartz简单许多,这篇文章将不做详细介绍。
-
从作业类的继承方式来讲,可以分为两类:
- 作业类需要继承自特定的作业类基类,如Quartz中需要继承自org.springframework.scheduling.quartz.QuartzJobBean;java.util.Timer中需要继承自java.util.TimerTask。
- 作业类即普通的java类,不需要继承自任何基类。
注:个人推荐使用第二种方式,因为这样所有的类都是普通类,不需要事先区别对待。
-
从任务调度的触发时机来分,这里主要是针对作业使用的触发器,主要有以下两种:
- 每隔指定时间则触发一次,在Quartz中对应的触发器为:org.springframework.scheduling.quartz.SimpleTriggerBean
- 每到指定时间则触发一次,在Quartz中对应的调度器为:org.springframework.scheduling.quartz.CronTriggerBean
注:并非每种任务都可以使用这两种触发器,如java.util.TimerTask任务就只能使用第一种。Quartz和spring task都可以支持这两种触发条件。
二.用法说明
本文将详细介绍Quartz定时调度任务的使用方式。
第一种,作业类继承自特定的基类:org.springframework.scheduling.quartz.QuartzJobBean。
第一步:编写任务类
package com.ncs.hj; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.springframework.scheduling.quartz.QuartzJobBean; public class SpringQtz extends QuartzJobBean{ private static int counter = 0; protected void executeInternal(JobExecutionContext context) throws JobExecutionException { System.out.println(); long ms = System.currentTimeMillis(); System.out.println("\t\t" + new Date(ms)); System.out.println(ms); System.out.println("(" + counter++ + ")"); String s = (String) context.getMergedJobDataMap().get("service"); System.out.println(s); System.out.println(); } }
第二种,作业类不继承特定基类。
Spring能够支持这种方式,归功于两个类:
org.springframework.scheduling.timer.MethodInvokingTimerTaskFactoryBean
org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean
这两个类分别对应spring支持的两种实现任务调度的方式,即前文提到到java自带的timer task方式和Quartz方式。这里我只写MethodInvokingJobDetailFactoryBean的用法,使用该类的好处是,我们的任务类不再需要继承自任何类,而是普通的pojo。
第一步:编写任务类
package com.ncs.hj; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.springframework.scheduling.quartz.QuartzJobBean; import java.util.Date; public class SpringQtz { private static int counter = 0; protected void execute() { long ms = System.currentTimeMillis(); System.out.println("\t\t" + new Date(ms)); System.out.println("(" + counter++ + ")"); } }
第二步:Spring的配置文件
<!------------ 配置调度程序quartz ,其中配置JobDetail有两种方式--------------> <!--方式一:使用JobDetailBean,任务类必须实现Job接口 --> <bean id="myjob" class="org.springframework.scheduling.quartz.JobDetailBean"> <property name="name" value="exampleJob"></property> <property name="jobClass" value="com.ncs.hj.SpringQtz"></property> <property name="jobDataAsMap"> <map> <entry key="service"><value>simple is the beat</value></entry> </map> </property> </bean> <!--运行时请将方式一注释掉! --> <!-- 方式二:使用MethodInvokingJobDetailFactoryBean,任务类可以不实现Job接口,通过targetMethod指定调用方法--> <!-- 定义目标bean和bean中的方法 --> <bean id="SpringQtzJob" class="com.ncs.hj.SpringQtz"/> <bean id="SpringQtzJobMethod" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject"> <ref bean="SpringQtzJob"/> </property> <property name="targetMethod"> <!-- 要执行的方法名称 --> <value>execute</value> </property> </bean> <!-- ======================== 调度触发器 ======================== --> <bean id="CronTriggerBean" class="org.springframework.scheduling.quartz.CronTriggerBean"> <property name="jobDetail" ref="SpringQtzJobMethod"></property> <property name="cronExpression" value="0/5 * * * * ?"></property> </bean> <!-- ======================== 调度工厂 ======================== --> <bean id="SpringJobSchedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="CronTriggerBean"/> </list> </property> </bean>
到此,spring中Quartz的基本配置就介绍完了,当然了,使用之前,要导入相应的spring的包与Quartz的包,这些就不消多说了。
关于cronExpression表达式,这里讲解一下:
字段 允许值 允许的特殊字符
秒 0-59 , - * /
分 0-59 , - * /
小时 0-23 , - * /
日期 1-31 , - * ? / L W C
月份 1-12 或者 JAN-DEC , - * /
星期 1-7 或者 SUN-SAT , - * ? / L C #
年(可选) 留空, 1970-2099 , - * /
表达式意义
"0 0 12 * * ?" 每天中午12点触发
"0 15 10 ? * *" 每天上午10:15触发
"0 15 10 * * ?" 每天上午10:15触发
"0 15 10 * * ? *" 每天上午10:15触发
"0 15 10 * * ? 2005" 2005年的每天上午10:15触发
"0 * 14 * * ?" 在每天下午2点到下午2:59期间的每1分钟触发
"0 0/5 14 * * ?" 在每天下午2点到下午2:55期间的每5分钟触发
"0 0/5 14,18 * * ?" 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发
"0 0-5 14 * * ?" 在每天下午2点到下午2:05期间的每1分钟触发
"0 10,44 14 ? 3 WED" 每年三月的星期三的下午2:10和2:44触发
"0 15 10 ? * MON-FRI" 周一至周五的上午10:15触发
"0 15 10 15 * ?" 每月15日上午10:15触发
"0 15 10 L * ?" 每月最后一日的上午10:15触发
"0 15 10 ? * 6L" 每月的最后一个星期五上午10:15触发
"0 15 10 ? * 6L 2002-2005" 2002年至2005年的每月的最后一个星期五上午10:15触发
"0 15 10 ? * 6#3" 每月的第三个星期五上午10:15触发
每天早上6点
0 6 * * *
每两个小时
0 */2 * * *
晚上11点到早上8点之间每两个小时,早上八点
0 23-7/2,8 * * *
每个月的4号和每个礼拜的礼拜一到礼拜三的早上11点
0 11 4 * 1-3
1月1日早上4点
0 4 1 1 *
参考:http://gong1208.iteye.com/blog/1773177
http://kevin19900306.iteye.com/blog/1397744
Spring整合Quartz实现定时任务