林炳文Evankaka原创作品。转载请注明出处http://blog.csdn.net/evankaka
1、新建一个工程,导入相应的包Spring3.2.9+Quqrtz2.2.1+commons-logging
集成起来比较简单,对线程无需任何理解,Spring手册上也有清楚的说明。只需写一个POJO,其余的都是配置,而且若使用CronTriggerBean,可以配置很复杂的任务调度。
编写一个普通的JAVA类
根据业务,写一个简单的JAVA类,和普通的类没有区别。并配置到Spring配置文件上中。例:
package com.mucfc; import java.text.SimpleDateFormat; import java.util.Date; /** *事件类 *作者 林炳文([email protected] 博客:http://blog.csdn.net/evankaka) *时间 2015.4.29 */ public class MyJob { public void run(){ System.out.println("Hello Spring with Quzrtz "+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss ").format(new Date())); } }
1、创建job的bean实例
<!-- 配置Job的bean --> <bean id="myJob" class="com.mucfc.MyJob" />
2.使用MethodInvokingJobDetailFactoryBean建立任务
只需要配置即可,配置信息示例如下:
<!-- 配置jobDetail --> <bean id="myJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <!-- 用到的Job实例 --> <property name="targetObject"> <ref bean="myJob"/> </property> <!-- Job实例中的方法 --> <property name="targetMethod"> <value>run</value> </property> </bean>
说明:
targetObject |
目标对象,即需要定时执行的POJO |
targetMethod |
目标方法,即需要定时执行的POJO方法 |
concurrent |
默认情况下,Quartz Jobs是无状态的,可能导致jobs之间互相的影响,如果你为相同的JobDetail指定两个Trigger,很可能当第一个job完成之前,第二个job就开始了。如果Jobdetail实现了Stateful接口,就不会发生这样的事情。第二个job将不会在第一个job完成之前开始。为了使得jobs不并发运行,设置concurrent标记为false |
3、使用CronTriggerBean建立规则,调度任务
<!-- 配置触发器Trigger --> <bean id="myTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"> <property name="name" value="work_default_name"/> <property name="group" value="work_default"/> <property name="jobDetail"> <ref bean="myJobDetail"/> </property> <property name="cronExpression"> <!-- 每5秒执行一次 --> <value>0/5 * * * * ?</value> </property> </bean>
说明:
jobDetail |
任务详情,即所需要调度的任务 |
cronExpression |
调用规则,即什么时候调用。详细说明见附录1 |
<!-- 配置scheduler工厂 --> <bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="myTrigger"/> </list> </property> </bean>说明:
triggers |
触发器,调用哪些任务 |
autoStartup |
是否自动启动,该Bean被初始化后是否自动启动定时任务。 Set whether to automatically start the scheduler after initialization. |
schedulerName |
给这个计划设定一个名称。 Set the name of the Scheduler to fetch from the SchedulerFactory. |
整个配置文件如下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <!-- 配置Job的bean --> <bean id="myJob" class="com.mucfc.MyJob" /> <!-- 配置jobDetail --> <bean id="myJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <!-- 用到的Job实例 --> <property name="targetObject"> <ref bean="myJob"/> </property> <!-- Job实例中的方法 --> <property name="targetMethod"> <value>run</value> </property> </bean> <!-- 配置触发器Trigger --> <bean id="myTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"> <property name="name" value="work_default_name"/> <property name="group" value="work_default"/> <property name="jobDetail"> <ref bean="myJobDetail"/> </property> <property name="cronExpression"> <!-- 每5秒执行一次 --> <value>0/5 * * * * ?</value> </property> </bean> <!-- 配置scheduler工厂 --> <bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="myTrigger"/> </list> </property> </bean> </beans>
package com.mucfc; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MyTest { public static void main(String[] args) { ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml"); } }我们在学习Spring中知道,ApplicationContext在加载的时候它会自动生成bean的实例,也就是说这个运行后定时器就会开始执行了,结果如下:
若是不想让它一加载就启动,就可以用beanfactory来加载xml文件,然后再手动打开
package com.mucfc; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.xml.XmlBeanFactory; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; public class MyTest { public static void main(String[] args) { //ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml"); Resource res = new ClassPathResource("beans.xml"); BeanFactory bf = new XmlBeanFactory(res); Scheduler scheduler=(Scheduler)bf.getBean("scheduler"); try { scheduler.start(); } catch (SchedulerException e) { e.printStackTrace(); } } }
核心概念
Quartz cron 表达式的格式十分类似于 UNIX cron 格式,但还是有少许明显的区别。区别之一就是 Quartz 的格式向下支持到秒级别的计划,而 UNIX cron 计划仅支持至分钟级。许多我们的触发计划要基于秒级递增的(例如,每45秒),因此这是一个非常好的差异。
在 UNIX cron 里,要执行的作业(或者说命令)是存放在 cron 表达式中的,在第六个域位置上。Quartz 用 cron 表达式存放执行计划。引用了 cron 表达式的 CronTrigger 在计划的时间里会与 job 关联上。
另一个与 UNIX cron 表达式的不同点是在表达式中支持域的数目。UNIX 给出五个域(分、时、日、月和周),Quartz 提供七个域。表 5.1 列出了 Quartz cron 表达式支持的七个域。
名称 | 是否必须 | 允许值 | 特殊字符 |
秒 | 是 | 0-59 | , - * / |
分 | 是 | 0-59 | , - * / |
时 | 是 | 0-23 | , - * / |
日 | 是 | 1-31 | , - * ? / L W C |
月 | 是 | 1-12 或 JAN-DEC | , - * / |
周 | 是 | 1-7 或 SUN-SAT | , - * ? / L C # |
年 | 否 | 空 或 1970-2099 | , - * / |
不要让范围和列表值与 L 连用 虽然你能用星期数(1-7)与 L 连用,但是不允许你用一个范围值和列表值与 L 连用。这会产生不可预知的结果。 |
示例:
表达式意义
"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 ? 3WED" 每年三月的星期三的下午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 ? * 6L2002-2005" 2002年至2005年的每月的最后一个星期五上午10:15触发
"0 15 10 ? *6#3" 每月的第三个星期五上午10:15触发
林炳文Evankaka原创作品。转载请注明出处http://blog.csdn.net/evankaka