Quartz 在 Spring 中如何动态配置时间(4)

转自 http://www.iteye.com/topic/399980

五、实现自己的org.quartz.JobDetail 
在上一步中SchedulerServiceImpl需要注入org.quartz.JobDetail,在以前的静态配置中 
引用

<bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">  
<property name="targetObject" ref="simpleService" />  
<property name="targetMethod" value="testMethod" />  
</bean>

中使用 org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean。在这里使用 org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean。会报  
引用


Caused by: java.io.NotSerializableException: Unable to serialize JobDataMap for insertion into database because the value of property 'methodInvoker' is not serializable: org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean 
at org.quartz.impl.jdbcjobstore.StdJDBCDelegate.serializeJobData(StdJDBCDelegate.java:3358) 
at org.quartz.impl.jdbcjobstore.StdJDBCDelegate.insertJobDetail(StdJDBCDelegate.java:515) 
at org.quartz.impl.jdbcjobstore.JobStoreSupport.storeJob(JobStoreSupport.java:1102) 
... 11 more 


异常,google了一下,没有找到解决方法。所以在这里不能使用 org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean。,不能pojo了,需要使用 org.springframework.scheduling.quartz.JobDetailBean和org.springframework.scheduling.quartz.QuartzJobBean实现自己的QuartzJobBean,如下:  
Java代码      
  1. package com.sundoctor.example.service;  
  2.   
  3. import org.quartz.JobExecutionContext;  
  4. import org.quartz.JobExecutionException;  
  5. import org.quartz.Trigger;  
  6. import org.springframework.scheduling.quartz.QuartzJobBean;  
  7.   
  8. public class MyQuartzJobBean extends QuartzJobBean {  
  9.   
  10.     private SimpleService simpleService;  
  11.       
  12.     public void setSimpleService(SimpleService simpleService) {  
  13.         this.simpleService = simpleService;  
  14.     }  
  15.   
  16.     @Override  
  17.     protected void executeInternal(JobExecutionContext jobexecutioncontext) throws JobExecutionException {  
  18.         Trigger trigger = jobexecutioncontext.getTrigger();  
  19.         String triggerName = trigger.getName();       
  20.         simpleService.testMethod(triggerName);  
  21.     }  
  22.   
  23. }  


MyQuartzJobBean继承 org.springframework.scheduling.quartz.QuartzJobBean,注入的SimpleService如下:  
Java代码      
  1. package com.sundoctor.example.service;  
  2.   
  3. import java.io.Serializable;  
  4.   
  5. import org.slf4j.Logger;  
  6. import org.slf4j.LoggerFactory;  
  7. import org.springframework.stereotype.Service;  
  8.   
  9. @Service("simpleService")  
  10. public class SimpleService implements Serializable{  
  11.       
  12.     private static final long serialVersionUID = 122323233244334343L;  
  13.     private static final Logger logger = LoggerFactory.getLogger(SimpleService.class);  
  14.       
  15.     public void testMethod(String triggerName){  
  16.         //这里执行定时调度业务  
  17.         logger.info(triggerName);  
  18.     }  
  19.       
  20.     public void testMethod2(){  
  21.         logger.info("testMethod2");  
  22.     }  
  23. }  

SimpleService主要执行定时调度业务,在这里我只是简单打印一下log日志。SimpleService需要实现java.io.Serializable接口,否则会报  
引用
Caused by: java.io.InvalidClassException: com.sundoctor.example.service.SimpleService; class invalid for deserialization 
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:587) 
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1583) 
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1496) 
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1732) 
... 64 more

异常。  

配置applicationContext-quartz.xml文件:  
引用

<?xml version="1.0" encoding="UTF-8"?>  
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">  

<beans>  
<bean name="quartzScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">  
<property name="dataSource">   
<ref bean="dataSource" />   
</property>  
<property name="applicationContextSchedulerContextKey"  value="applicationContextKey" />  
<property name="configLocation" value="classpath:quartz.properties"/>  
</bean>  

<bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailBean">  
<property name="jobClass">  
<value>com.sundoctor.example.service.MyQuartzJobBean</value>  
</property>  

<property name="jobDataAsMap"> 
<map> 
<entry key="simpleService"> 
<ref bean="simpleService" /> 
</entry> 
</map> 
</property> 

</bean>
</beans>  


quartzScheduler中没有了  
引用

<property name="triggers">  
<list>  
...       
</list>  
/property>  

配置,通过SchedulerService动态加入CronTrigger或SimpleTrigger。  

在红色的  
引用


<property name="jobDataAsMap"> 
<map> 
<entry key="simpleService"> 
<ref bean="simpleService" /> 
</entry> 
</map> 
</property> 


中需要注入调度业务类,否则会报空指指错误。  

dataSource:项目中用到的数据源,里面包含了quartz用到的12张数据库表;  
applicationContextSchedulerContextKey: 是org.springframework.scheduling.quartz.SchedulerFactoryBean这个类中把spring上下文以key/value的方式存放在了quartz的上下文中了,可以用applicationContextSchedulerContextKey所定义的key得到对应的spring上下文;  
configLocation:用于指明quartz的配置文件的位置,如果不用spring配置quartz的话,本身quartz是通过一个配置文件进行配置的,默认名称是quartz.properties,里面配置的参数在quartz的doc文档中都有介绍,可以调整quartz,我在项目中也用这个文件部分的配置了一些属性,代码如下:  
引用

org.quartz.scheduler.instanceName = DefaultQuartzScheduler  
org.quartz.scheduler.rmi.export = false  
org.quartz.scheduler.rmi.proxy = false  
org.quartz.scheduler.wrapJobExecutionInUserTransaction = false  

org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool  
org.quartz.threadPool.threadCount = 10  
org.quartz.threadPool.threadPriority = 5  
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true  

org.quartz.jobStore.misfireThreshold = 60000  

#org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore  

org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX  
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.HSQLDBDelegate  
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate  
#org.quartz.jobStore.useProperties = true  
org.quartz.jobStore.tablePrefix = QRTZ_   
org.quartz.jobStore.isClustered = false   
org.quartz.jobStore.maxMisfiresToHandleAtATime=1  

这里面没有数据源相关的配置部分,采用spring注入datasource的方式已经进行了配置。  

六、测试  
运行如下测试类  
Java代码      
  1. package com.sundoctor.example.test;  
  2.   
  3. import java.text.ParseException;  
  4. import java.text.SimpleDateFormat;  
  5. import java.util.Date;  
  6.   
  7. import org.springframework.context.ApplicationContext;  
  8. import org.springframework.context.support.ClassPathXmlApplicationContext;  
  9.   
  10. import com.sundoctor.quartz.service.SchedulerService;  
  11.   
  12. public class MainTest {  
  13.   
  14.     /** 
  15.      * @param args 
  16.      */  
  17.     public static void main(String[] args) {  
  18.         ApplicationContext springContext = new ClassPathXmlApplicationContext(new String[]{"classpath:applicationContext.xml","classpath:applicationContext-quartz.xml"});  
  19.         SchedulerService schedulerService = (SchedulerService)springContext.getBean("schedulerService");  
  20.           
  21.         //执行业务逻辑...  
  22.           
  23.         //设置调度任务  
  24.         //每10秒中执行调试一次  
  25.         schedulerService.schedule("0/10 * * ? * * *");   
  26.           
  27.         Date startTime = parse("2009-06-01 22:16:00");  
  28.         Date endTime =  parse("2009-06-01 22:20:00");  
  29.           
  30.         //2009-06-01 21:50:00开始执行调度  
  31.         schedulerService.schedule(startTime);  
  32.   
  33.         //2009-06-01 21:50:00开始执行调度,2009-06-01 21:55:00结束执行调试  
  34.         //schedulerService.schedule(startTime,endTime);  
  35.           
  36.         //2009-06-01 21:50:00开始执行调度,执行5次结束  
  37.         //schedulerService.schedule(startTime,null,5);  
  38.   
  39.         //2009-06-01 21:50:00开始执行调度,每隔20秒执行一次,执行5次结束  
  40.         //schedulerService.schedule(startTime,null,5,20);  
  41.           
  42.         //等等,查看com.sundoctor.quartz.service.SchedulerService          
  43.     }  
  44.       
  45.     private static Date parse(String dateStr){  
  46.         SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
  47.         try {  
  48.             return format.parse(dateStr);  
  49.         } catch (ParseException e) {  
  50.             throw new RuntimeException(e);  
  51.         }  
  52.     }  
  53.   
  54. }  

输出  
引用

[2009-06-02 00:08:50]INFO  com.sundoctor.example.service.SimpleService(line:17) -2059c26f-9462-49fe-b4ce-be7e7a29459f  
[2009-06-02 00:10:20]INFO  com.sundoctor.example.service.SimpleService(line:17) -2059c26f-9462-49fe-b4ce-be7e7a29459f  
[2009-06-02 00:10:30]INFO  com.sundoctor.example.service.SimpleService(line:17) -2059c26f-9462-49fe-b4ce-be7e7a29459f  
[2009-06-02 00:10:40]INFO  com.sundoctor.example.service.SimpleService(line:17) -2059c26f-9462-49fe-b4ce-be7e7a29459f  
[2009-06-02 00:10:50]INFO  com.sundoctor.example.service.SimpleService(line:17) -2059c26f-9462-49fe-b4ce-be7e7a29459f  
[2009-06-02 00:11:00]INFO  com.sundoctor.example.service.SimpleService(line:17) -2059c26f-9462-49fe-b4ce-be7e7a29459f  
[2009-06-02 00:11:10]INFO  com.sundoctor.example.service.SimpleService(line:17) -2059c26f-9462-49fe-b4ce-be7e7a29459f  

这样只是简单的将quartz trigger名称打印出来。  

这样通过SchedulerService就可以动态配置调度时间。其实SchedulerService 还可扩展,比如可以注入多个JobDetail,调度不同的JobDetail。  

你可能感兴趣的:(java,spring,bean,xml,quartz)