spring -quartz配置详解

Spring Quartz如何动态配置时间

记录时间规则

      
我将时间规则存入数据库中,目的是为了生成历史日志,也可以存入XML文件中。当然您也可以省略此步,直接将转换后的规则放入相应的Quartz trigger中。

更新任务触发器的时间设置

到了关键的一步了,也是最简单的一步,一个方法就可以实现了。
首先,我们需要通过trigger的名称得到一个CronTriggerBean
其次,通过triggersetCronExpression(String cronExp)方法将新的表达式注入;
最后,RESCHEDULE THE JOBOK

 1     /** */ /**
 2      * 自定义定时器调度时间
 3      *  @param  triggerName 触发器名称
 4       *  @throws  Exception 
 5       */
 6      public   void  updateNotificationInterval(String triggerName, String triggerId)
 7              throws  SchedulerException, ParseException  {
 8          // 得到trigger
 9         CronTriggerBean trigger  =  (CronTriggerBean) scheduler.getTrigger(
10                 triggerName, Scheduler.DEFAULT_GROUP);
11          // 得到cron expression        
12         String cronExpression  =  schedulerDAO.getCronExpression(triggerId);
13          // 设置trigger的时间规则
14         trigger.setCronExpression(cronExpression);
15          // 重置job
16         scheduler.rescheduleJob(triggerName, Scheduler.DEFAULT_GROUP, trigger);
17     }
18

至此,目的达到了,快乐的看着您的任务在您自定义的时间下快乐的执行,您是否也想像'Happy Feet'中那只快乐的企鹅一样,Show段踢踏呢 ; - D




PS
:忘了说我的Quartz任务是怎么配置的了,罪过,罪过。

< bean  id ="compareJob"
        class
="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean" >
        
< property  name ="targetObject"  ref ="compareService"   />
        
< property  name ="targetMethod"  value ="compare"   />
        
< property  name ="concurrent"  value ="false"   />
    
</ bean >  

    
< bean  id ="compareTrigger"
        class
="org.springframework.scheduling.quartz.CronTriggerBean" >
        
< property  name ="jobDetail"  ref ="compareJob"   />
        
< property  name ="cronExpression" >             
            
< value > 0 39 16 20 * ? </ value >
        
</ property >
    
</ bean >

< bean  id ="schedulerFactory"
        class
="org.springframework.scheduling.quartz.SchedulerFactoryBean" >
        
< property  name ="triggers" >
            
< list >                     
                     < ref  local ="compareTrigger"   />
            
</ list >
        
</ property >
    
</ bean >



                                                                                   
 THE END

感觉有点像 crontab ..... 
  

其实QuartzCron Expression就是来自Unix中,所以感觉很像crontab命令  
  

上面这个updateNotificationInterval究竟写在哪个类里面呢?这个类要在xml里面怎么配置才能够得到scheduler的对象呢?
看最后声明的那部分没有这个类的部分啊。难道是直接通过context来获得么?     

updateNotificationInterval()
这个方法可以写在你的业务逻辑类中,scheduler对象在这个类中注入就可以用了。如:
public class SchedulerService {

private Scheduler scheduler;

/**
* @param scheduler The scheduler to set.
*/
public void setScheduler(Scheduler scheduler) {
this.scheduler = scheduler;
}

public void updateNotificationInterval(...) {
//...
scheduler.rescheduleJob(...);
//...
}
}
Spring中的配置如下:
<bean id="schedulerServiceTarget" class="SchedulerService">
<property name="scheduler" ref="schedulerFactory" />
</bean>
schedulerFactory这个bean我在文章中写到了
< bean id ="schedulerFactory"
class ="org.springframework.scheduling.quartz.SchedulerFactoryBean" >
< property name ="triggers" >
< list >
< ref local ="compareTrigger" />
</ list >
</ property >
</ bean >

不知道这样能不能回答你的问题呢,yy77 ;-)

  

我想请问一下:我都配置好了,程序到了制定的时间会进入方法A,我想在进入方法A后,就取得< value > 0 39 16 20 * ? </ value >这个值,应该怎么实现呢?谢谢

我理解您的意思是:
您的Method A中需要用到这个时间,但是不知道从哪里取到。

我的解决方法是将所有的时间规则放入数据库中,然后从数据库中读取最近插入的一个值就是所需时间了。

不知道这样能不能回答你的问题。  
  

感谢您的回答,可能我没表达清楚我的意思!我现在的时间是在数据库中,就用您的方法假设,我要定时触发这个方法< property name ="targetMethod" value ="compare" /> ,但是这个方法会在不同的时间点多次触发,比如每月最后1天,每个星期第一天都是触发这个方法!我这里可以配置多个时间么?< property name ="cronExpression" >
< value > 0 39 16 20 * ? </ value >
</ property >
然后把这个时间值放进数据库查询!谢谢

如果找不到调用的方法一般是什么错误?类的名字,方法名在多次查证都是正确的  回复  更多评论
 


能否把你的配置文件贴出来看看?
  


我查阅了Quartz的文档,没有找到可以为一个Job配置多个value elements的方法,所以有个比较笨的方法是设置多个Job,让它们指向同一个Method,按照不同的时间执行。
  

请问我要是调用多个方法怎么办?  
  



理论上时可以的。你可以通过加载mutiple propertys达到调用多个方法的目的。如:
<property name="targetMethod">
<list>
<value>register</value>
<value>compare</value>
</list>
</property>

不过我没有实际实验过,您可以实验一下,告诉我结果 :)
  

thrank you!
 
是这样的,客户有个需求是可以自己修改任务的间隔时间的!(这个值是设置到数据库中的),因为SimpleTriggerBean必须设置repeatInterval属性,而这个值因为是保存在数据中的,所以我想设置两个定时任务CMSTransformCRMTriggerScheduleInfoActionTriggerScheduleInfoActionTriggerCMSTransformCRMTrigger任务执行前触发:其目的是为CMSTransformCRMTrigger根据数据库的值设置其repeatInterval属性,配置文件如下:

    <bean id="CMSTransformCRMEngine" class="org.springframework.aop.framework.ProxyFactoryBean">
        
<property name="targetSource">
            
<bean class="org.springframework.aop.target.SingletonTargetSource">
                
<constructor-arg>
                    
<bean class="com.server.business.cms.CMSTransformCRMEngine"/>
                
</constructor-arg>
            
</bean>
        
</property>
        
<property name="interceptorNames">
            
<list>
                
<value>CallContextInterceptor</value>
            
</list>
        
</property>
    
</bean>

 
<bean id="CMSTransformCRMJob" class="org.springframework.scheduling.quartz.JobDetailBean">         
        
<property name="jobClass">
            
<value>com.wisecrm.server.business.cms.CMSTransformCRMScheduledTask</value>
        
</property>    
        
<property name="jobDataAsMap">
            
<map>
                
<entry key="cmsTranCRMEnginer">
                    
<ref bean="CMSTransformCRMEngine"></ref>
                
</entry>
            
</map>
        
</property>
    
</bean>
    
     
<bean id="CMSTransformCRMTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">         
        
<property name="jobDetail">
            
<ref bean="CMSTransformCRMJob"></ref>
        
</property>    
        
<property name="startDelay">
            
<value>90000</value>
        
</property>
        
<property name="repeatInterval">
            
<value>90000</value>
        
</property>
    
</bean>
    
    
<bean id="ScheduleInfoAction" class="com.wisecrm.server.business.cms.ScheduleInfoAction">         
        
<property name="dataSource" ref="DataSource"/>     
        
<property name="scheduler" ref="schedulerFactory"/>     
    
</bean>
    
    
<bean id="ScheduleInfoActionFactory" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        
<property name="targetObject" ref="ScheduleInfoAction"/>
        
<property name="targetMethod">
             
<value>setTaskTimeByPreference</value>
        
</property>
        
<!--property name="arguments">
            <list>
                <ref local="DataSource"/>
                <ref local="schedulerFactory"/>
            </list>
        </property-->

        
<property name="concurrent" value="false"/>
    
</bean>
    
    
<bean id="ScheduleInfoActionTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">         
        
<property name="jobDetail">
            
<ref bean="ScheduleInfoActionFactory"></ref>
        
</property>    
        
<property name="startDelay">
            
<value>80000</value>
        
</property>
        
<property name="repeatInterval">
            
<value>50000</value>
        
</property>
    
</bean>
    
    
<bean id="schedulerFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">         
        
<property name="triggers">             
            
<list>                 
                
<ref local="CMSTransformCRMTrigger"/>             
                
<ref local="ScheduleInfoActionTrigger"/>             
            
</list>         
        
</property>
    
</bean>


ScheduleInfoAction
动态设置间隔时间的接口:

public class ScheduleInfoAction  {

    
private Scheduler scheduler;

    
public void setTaskTimeByPreference() throws SchedulerException  {
        
if (isStartCMSTransformCRMTask())  {
            SimpleTriggerBean trigger = (SimpleTriggerBean) scheduler.getTrigger("ScheduleInfoActionTrigger
",
                            Scheduler.DEFAULT_GROUP);
            trigger.setRepeatInterval(Long.parseLong(Application.getSystemSettingService().getPrefValue(
"CMSPeriod")));
            scheduler.rescheduleJob(
"ScheduleInfoActionTrigger",
                    Scheduler.DEFAULT_GROUP, trigger);
        } 
else  {
            scheduler.shutdown();
        }
    }


    public
 boolean isStartCMSTransformCRMTask()  {
        
return Application.getSystemSettingService().getPrefValue("CMSPeriod") != null;
    }

    public
 Scheduler getScheduler()  {
        
return scheduler;
    }

    public
 void setScheduler(Scheduler scheduler)  {
        
this.scheduler = scheduler;
    }


}

  但是不知为和两个任务都不执行?

后面我再在程序启动时就通过ScheduleInfoActionfactoryBean

设置CMSTransformCRMTriggerrepeatInterval属性,只保留一个定时任务就可以了,

配置如下:

<bean id="ScheduleInfoAction" class="com.wisecrm.server.business.cms.ScheduleInfoAction">         
        
<property name="scheduler" ref="schedulerFactory"/>     
    
</bean>
    
    
<bean id="ScheduleInfoActionFactory" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        
<property name="targetObject" ref="CMSTransformCRMEngine"/>
        
<property name="targetMethod">
             
<value>run</value>
        
</property>
        
<property name="concurrent" value="false"/>
    
</bean>
    
    
<bean id="ScheduleInfoActionTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">         
        
<property name="jobDetail">
            
<ref bean="ScheduleInfoActionFactory"></ref>
        
</property>    
        
<property name="startDelay">
            
<value>80000</value>
        
</property>
        
<property name="repeatInterval">
            
<value>80000</value>
        
</property>
    
</bean>
    
    
<bean id="schedulerFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">         
        
<property name="triggers">             
            
<list>            
                
<ref bean="ScheduleInfoActionTrigger"/>             
            
</list>         
        
</property>
    
</bean>

但总感觉到有点笨拙,你帮忙参考下     


首先Scheduler是接口不是类,其次FactoryBean that sets up a Quartz Scheduler, manages its lifecycle as part of the Spring application context, and exposes the Scheduler reference for dependency injection.

您下面这个配置我不太明白是什么意思?能否把整个配置文件贴出来?
 

 

thrank you!
 
是这样的,客户有个需求是可以自己修改任务的间隔时间的!(这个值是设置到数据库中的),因为SimpleTriggerBean必须设置repeatInterval属性,而这个值因为是保存在数据中的,所以我想设置两个定时任务CMSTransformCRMTriggerScheduleInfoActionTriggerScheduleInfoActionTriggerCMSTransformCRMTrigger任务执行前触发:其目的是为CMSTransformCRMTrigger根据数据库的值设置其repeatInterval属性,配置文件如下:

    <bean id="CMSTransformCRMEngine" class="org.springframework.aop.framework.ProxyFactoryBean">
        
<property name="targetSource">
            
<bean class="org.springframework.aop.target.SingletonTargetSource">
                
<constructor-arg>
                    
<bean class="com.server.business.cms.CMSTransformCRMEngine"/>
                
</constructor-arg>
            
</bean>
        
</property>
        
<property name="interceptorNames">
            
<list>
                
<value>CallContextInterceptor</value>
            
</list>
        
</property>
    
</bean>

 
<bean id="CMSTransformCRMJob" class="org.springframework.scheduling.quartz.JobDetailBean">         
        
<property name="jobClass">
            
<value>com.wisecrm.server.business.cms.CMSTransformCRMScheduledTask</value>
        
</property>    
        
<property name="jobDataAsMap">
            
<map>
                
<entry key="cmsTranCRMEnginer">
                    
<ref bean="CMSTransformCRMEngine"></ref>
                
</entry>
            
</map>
        
</property>
    
</bean>
    
     
<bean id="CMSTransformCRMTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">         
        
<property name="jobDetail">
            
<ref bean="CMSTransformCRMJob"></ref>
        
</property>    
        
<property name="startDelay">
            
<value>90000</value>
        
</property>
        
<property name="repeatInterval">
            
<value>90000</value>
        
</property>
    
</bean>
    
    
<bean id="ScheduleInfoAction" class="com.wisecrm.server.business.cms.ScheduleInfoAction">         
        
<property name="dataSource" ref="DataSource"/>     
        
<property name="scheduler" ref="schedulerFactory"/>     
    
</bean>
    
    
<bean id="ScheduleInfoActionFactory" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        
<property name="targetObject" ref="ScheduleInfoAction"/>
        
<property name="targetMethod">
             
<value>setTaskTimeByPreference</value>
        
</property>
        
<!--property name="arguments">
            <list>
                <ref local="DataSource"/>
                <ref local="schedulerFactory"/>
            </list>
        </property-->

        
<property name="concurrent" value="false"/>
    
</bean>
    
    
<bean id="ScheduleInfoActionTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">         
        
<property name="jobDetail">
            
<ref bean="ScheduleInfoActionFactory"></ref>
        
</property>    
        
<property name="startDelay">
            
<value>80000</value>
        
</property>
        
<property name="repeatInterval">
            
<value>50000</value>
        
</property>
    
</bean>
    
    
<bean id="schedulerFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">         
        
<property name="triggers">             
            
<list>                 
                
<ref local="CMSTransformCRMTrigger"/>             
                
<ref local="ScheduleInfoActionTrigger"/>             
            
</list>         
        
</property>
    
</bean>



ScheduleInfoAction
动态设置间隔时间的接口:

 

public class ScheduleInfoAction  {

    
private Scheduler scheduler;

    
public void setTaskTimeByPreference() throws SchedulerException  {
        
if (isStartCMSTransformCRMTask())  {
            SimpleTriggerBean trigger = (SimpleTriggerBean) scheduler.getTrigger("ScheduleInfoActionTrigger
",
                            Scheduler.DEFAULT_GROUP);
            trigger.setRepeatInterval(Long.parseLong(Application.getSystemSettingService().getPrefValue(
"CMSPeriod")));
            scheduler.rescheduleJob(
"ScheduleInfoActionTrigger",
                    Scheduler.DEFAULT_GROUP, trigger);
        } 
else  {
            scheduler.shutdown();
        }
    }


    public
 boolean isStartCMSTransformCRMTask()  {
        
return Application.getSystemSettingService().getPrefValue("CMSPeriod") != null;
    }

    public
 Scheduler getScheduler()  {
        
return scheduler;
    }

    public
 void setScheduler(Scheduler scheduler)  {
        
this.scheduler = scheduler;
    }


}

 

  但是不知为和两个任务都不执行?

 

后面我再在程序启动时就通过ScheduleInfoActionfactoryBean

 

设置CMSTransformCRMTriggerrepeatInterval属性,只保留一个定时任务就可以了,

 

配置如下:

 

 

<bean id="ScheduleInfoAction" class="com.wisecrm.server.business.cms.ScheduleInfoAction">         
        
<property name="scheduler" ref="schedulerFactory"/>     
    
</bean>
    
    
<bean id="ScheduleInfoActionFactory" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        
<property name="targetObject" ref="CMSTransformCRMEngine"/>
        
<property name="targetMethod">
             
<value>run</value>
        
</property>
        
<property name="concurrent" value="false"/>
    
</bean>
    
    
<bean id="ScheduleInfoActionTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">         
        
<property name="jobDetail">
            
<ref bean="ScheduleInfoActionFactory"></ref>
        
</property>    
        
<property name="startDelay">
            
<value>80000</value>
        
</property>
        
<property name="repeatInterval">
            
<value>80000</value>
        
</property>
    
</bean>
    
    
<bean id="schedulerFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">         
        
<property name="triggers">             
            
<list>            
                
<ref bean="ScheduleInfoActionTrigger"/>             
            
</list>         
        
</property>
    
</bean>

 


但总感觉到有点笨拙,你帮忙参考下,为什么repeatInterval不能通过继承SimpleTriggerBean复写getRepeatInterval方法去设置呢?


  

问一下:
Qest1:rescheduleJob
是不是在两种场景下使用,一是服务重启时,一是用户需要更改任务的时间规则(触发器)时?

Qest2:
用户在更改任务的时间规则(触发器)时,可能还需要任务已经运行的状态信息。
场景一:某个任务从 2007/1/1 日开始,每天830运行。到了 2007/5/1 日,用户想更改为每天900运行,新触发器设为 2007/1/1 900。希望的更新触发器后第一次运行时间是 2007/5/2 900。请问quartz可以做到吗?
场景二:某任务的执行次数为100次,当执行到30次时,用户希望把执行次数改为150次,新触发器设为150次,所以任务还需执行150-100-30=80次。请问quartz可以做到吗?  
  

你好,我是刚刚搞开发不久,想学习quartz,你的这个程序的时间是从数据库里来读取的吗?能不能把你的表结构发我看看,感激不尽!  
  


表结构很简单,只需要keyvalue两个字段就可以满足要求。您也可以采用其他存储方式,如存入xml中。

 

 

 

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:102: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 *

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值