Spring+Quartz整合

Quartz是一个非常优秀的任务调度引擎,详情请见官网:[url]http://www.quartz-scheduler.org/[/url]

而Spring很好地集成了Quartz,为企业级的任务调度提供了方便。

 

下面先看一个实现了Job接口的任务HelloWorldJob:

Java代码   收藏代码
  1. package com.springQuartz.example;  
  2.   
  3. import java.util.Map;  
  4.   
  5. import org.quartz.Job;  
  6. import org.quartz.JobExecutionContext;  
  7. import org.quartz.JobExecutionException;  
  8.   
  9. public class HelloWorldJob implements Job{  
  10.   
  11.     @Override  
  12.     public void execute(JobExecutionContext context) throws JobExecutionException {  
  13.           
  14.         Map properties = context.getMergedJobDataMap();  
  15.           
  16.         System.out.println("Hello World!");  
  17.         System.out.println("Previous Fire Time: "+context.getPreviousFireTime());//上次触发任务的时间  
  18.         System.out.println("Current Fire Time: "+context.getFireTime());//当然触发时间  
  19.         System.out.println("Next Fire Time: "+context.getNextFireTime());//下次触发时间  
  20.           
  21.         System.out.println(properties.get("message"));  
  22.         System.out.println();  
  23.     }  
  24.       
  25. }  

这个Job输出"HelloWorld",同时输出上次、本次及下次触发的时间。

 

我们看一下在applicationContext.xml中的配置:

Xml代码   收藏代码
  1. <bean id="job" class="org.springframework.scheduling.quartz.JobDetailBean">  
  2.     <property name="jobClass" value="com.springQuartz.example.HelloWorldJob"/>  
  3.     <property name="jobDataAsMap">  
  4.          <map>  
  5.             <entry key="triggerMessage" value="Job Message In JobDetail"/> <!--设置JobDetail中的值-->  
  6.          </map>  
  7.     </property>  
  8. </bean>  
  9.       
  10. <bean id="trigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">  
  11.     <property name="jobDetail" ref="job"/> <!--触发的job引用-->  
  12.     <property name="startDelay" value="1000"/> <!--设置延迟1秒后运行-->  
  13.     <property name="repeatInterval" value="10000"/> <!--设置每10秒触发一次-->  
  14.     <property name="jobDataAsMap">  
  15.           <map>  
  16.           <entry key="triggerMessage" value="Job Message From Trigger"/> <!--设置Trigger中的值-->  
  17.           </map>  
  18.     </property>  
  19. </bean>  
  20.   
  21. <bean id="schedulerFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">  
  22.     <property name="triggers">  
  23.         <list>  
  24.             <ref local="trigger"/>      
  25.         </list>  
  26.     </property>  
  27. </bean>  

我们将HelloWorldJob实现成JobDetailBean类,并配置触发器simpleTriggerBean

 

最后我们的测试类:

Java代码   收藏代码
  1. package com.springQuartz.test;  
  2.   
  3. import org.springframework.beans.factory.BeanFactory;  
  4. import org.springframework.context.support.ClassPathXmlApplicationContext;  
  5.   
  6. public class Test {  
  7.     public static void main(String args[]){  
  8.         BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml");  
  9.     }  
  10. }  

运行结果如下:

运行结果代码   收藏代码
  1. 2011-01-16 20:48:18,437 INFO - Starting Quartz Scheduler now  
  2. Hello World!  
  3. Previous Fire Time: null  
  4. Current Fire Time: Sun Jan 16 20:48:19 CST 2011  
  5. Next Fire Time: Sun Jan 16 20:48:29 CST 2011  
  6. Job Message From Trigger  
  7.   
  8. Hello World!  
  9. Previous Fire Time: Sun Jan 16 20:48:19 CST 2011  
  10. Current Fire Time: Sun Jan 16 20:48:29 CST 2011  
  11. Next Fire Time: Sun Jan 16 20:48:39 CST 2011  
  12. Job Message From Trigger  

下面说明几点:

1)首次触发是输出的Previous Fire Time为null

2)jobDataAsMap的说明:在HelloWorldJob.java中getMergedJobDataMap是JobDetail和Trigger上的JobDataMap的合并,两者数据如果冲突,则Trigger上的数据将覆盖JobDetail中的。运行结果也证明了,我们在Job中设置的值没有输出,而输出了"Job Message From Trigger"。

3)我们看到HelloWorldJob实现了Job接口,代码上依赖了Quartz的接口

 

下面我们讨论另外一种更普遍的,去除接口依赖的实现

 

主要的applicationContext.xml文件的配置

Xml代码   收藏代码
  1. <bean id="jobService" class="com.springQuartz.service.JobServiceImpl">  
  2. </bean>  
  3.       
  4. <bean id="invokeJob" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">  
  5.     <property name="targetObject">  
  6.         <ref bean="jobService" /> <!--目标Job-->  
  7.     </property>  
  8.     <property name="targetMethod">  
  9.         <value>JobServiceImpl中的特定方法</value> <!--目标方法-->  
  10.     </property>  
  11.     <property name="concurrent">  
  12.         <value>false</value> <!--设置是否同步-->  
  13.     </property>  
  14. </bean>  
  15.       
  16. <bean id="jobServiceCronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">  
  17.     <property name="jobDetail" ref="invokeJob" />  
  18.     <property name="cronExpression" value="5/10 * * * * ?" />  
  19. </bean>  
  20.   
  21. <bean id="schedulerFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">  
  22.     <property name="triggers">  
  23.         <list>  
  24.             <ref local="jobServiceCronTrigger"/>  
  25.         </list>  
  26.     </property>  
  27. </bean>  

 

1)首先我们配置具体的Job信息--JobServiceImpl,这个类可以不实现Quartz中的Job接口

2)最主要的MethodInvokingJobDetailFactoryBean,可以使得1)可行

3)相对于上面的例子,我们使用CronTriggerBean实现trigger,实现更灵活的时间配置

4)默认情况下,Quartz Jobs是无状态的,可能导致jobs之间互相的影响。如果你为相同的JobDetail 指定两个Trigger, 很可能当第一个job完成之前,第二个job就开始了。如果JobDetail 对象实现了Stateful 接口,就不会发生这样的事情。 第二个job将不会在第一个job完成之前开始。为了使得jobs不并发运行,设置MethodInvokingJobDetailFactoryBean 中的concurrent 标记为false 。

猜你喜欢

转载自gcc2ge.iteye.com/blog/2278157