Quartz在Spring中动态设置cronExpression (spring设置动态定时任务)------转帖

什么是动态定时任务:是由客户制定生成的,服务端只知道该去执行什么任务,但任务的定时是不确定的(是由客户制定)。

这样总不能修改配置文件每定制个定时任务就增加一个trigger吧,即便允许客户修改配置文件,但总需要重新启动web服务啊,研究了下Quartz在Spring中的动态定时,发现

         

         

              0/10 ?

         

     中cronExpression是关键,如果可以动态设置cronExpression的值,也就说如果我们可以直接调用CronTriggerBean中设置cronExpression的方法,就可以顺利解决问题了。

熟悉1的朋友可以跳过不看,下面2、3是动态定时任务的具体实现。

 

1. Quartz在Spring中的简单配置

Spring配置文件:

    

        

         targetMethod" value="simpleJobTest"/>

        

    

    

         

          cronExpression**">

              0/10 ?

         

     

    

        

            

                

            

        

 

在上面的配置中设定了

① targetMethod: 指定需要定时执行scheduleInfoAction中的simpleJobTest()方法

② concurrent:对于相同的JobDetail,当指定多个Trigger时, 很可能第一个job完成之前,第二个job就开始了。指定concurrent设为false,多个job不会并发运行,第二个job将不会在第一个job完成之前开始。

cronExpression:0/10 ?表示每10秒执行一次,具体可参考附表。

④ triggers:通过再添加其他的ref元素可在list中放置多个触发器。

 

scheduleInfoAction中的simpleJobTest()方法

注意:此方法没有参数,如果scheduleInfoAction有两个方法simpleJobTest()和simpleJobTest(String argument),则spring只会去执行无参的simpleJobTest().

public void simpleJobTest() {

         log.warn(“uh oh, Job is scheduled !’” + “‘ Success…”);

     }

 

2.Quartz在Spring中动态设置cronTrigger方法一

Spring配置文件:

         scheduler**" ref="schedulerFactory"/>

         scheduleInfoManager**" ref="scheduleInfoManager"/>

    

    

        

         reScheduleJob**"/>

        

    

     cronTrigger**" class="org.springframework.scheduling.quartz.CronTriggerBean" >

         

          cronExpression**">

              0/10 ?

         

     

    

        

            

                

            

        

 

scheduleInfoAction中的reScheduleJob ()方法及相关方法

reScheduleJob读取数据库,获得自定义定时器调度时间():

     private void reScheduleJob() throws SchedulerException, ParseException {

         // 运行时可通过动态注入的scheduler得到trigger

         CronTriggerBean trigger = (CronTriggerBean) scheduler.getTrigger(

                “cronTrigger“, Scheduler.DEFAULT_GROUP);

         String dbCronExpression = getCronExpressionFromDB();

         String originConExpression = trigger.getCronExpression();

     // 判断从DB中取得的任务时间(dbCronExpression)和现在的quartz线程中的任务时间(originConExpression)是否相等

     // 如果相等,则表示用户并没有重新设定数据库中的任务时间,这种情况不需要重新rescheduleJob

         if(!originConExpression.equalsIgnoreCase(dbCronExpression)){

             trigger.setCronExpression(dbCronExpression);

             scheduler.rescheduleJob(“cronTrigger“, Scheduler.DEFAULT_GROUP, trigger);

         }

     // 下面是具体的job内容,可自行设置

     // executeJobDetail();

}

 

② getCronExpressionFromDB():从数据库中获得dbCronExpression的具体代码,由于使用了scheduleInfoManager,所以要在定义相应的setter方法

     private String getCronExpressionFromDB(){

         String sql=”from ScheduleInfo scheduleInfo where 1=1 “;

         sql=sql+” and scheduleInfo.infoId = ‘“+”1” + “‘“;

         List scheduleList = scheduleInfoManager.queryScheduleInListBySql(sql);

         ScheduleInfo scheduleInfo = (ScheduleInfo)scheduleList.get(0);

         String dbCronExpression = scheduleInfo.getCronExpression();

         return dbCronExpression;

}

 

③ 在spring配置文件的scheduleInfoAction配置了相应的property(scheduler/ scheduleInfoManager),要为其设置setter方法

     private Scheduler scheduler;

     // 设值注入,通过setter方法传入被调用者的实例scheduler

     public void setScheduler(Scheduler scheduler) {

         this.scheduler = scheduler;

    }

     private ScheduleInfoManager scheduleInfoManager;

     // 设值注入,通过setter方法传入被调用者的实例scheduleInfoManager

     public void setScheduleInfoManager(ScheduleInfoManager scheduleInfoManager){

         this.scheduleInfoManager = scheduleInfoManager;

     }

 

3. Quartz在Spring中动态设置cronTrigger方法二

在上面的2中我们可以看到,尽管已经可以动态进行rescheduleJob了,不过依然需要我们设置一个cronExpression,如果尝试一下拿掉spring配置中的

         cronExpression**">

              0/10 ?

         

则容器(如tomcat)启动时会报错。

实际中我们希望tomcat启动时就可以直接去读数据库,拿到相应的dbCronExpression,然后定时执行一个job,而不希望配置初始的cronExpression ,观察下面的CronTriggerBean,考虑到cronExpression需要初始化,如果设定一个类InitializingCronTrigger继承CronTriggerBean,然后在这个类中做一些读取DB的初始化工作(设置cronExpression),问题就可以解决了。

 

Spring配置文件:

         scheduler**" ref="schedulerFactory"/>

         scheduleInfoManager**" ref="scheduleInfoManager"/>

    

    

        

         reScheduleJob**"/>

        

    

    cronTrigger**" class="com.lively.happyoa.jobs.webapp.action.ScheduleInfoAction.**InitializingCronTrigger**">

         

         

          scheduleInfoManager**" ref="scheduleInfoManager"/>

     

    

        

            

                

            

        

 

InitializingCronTrigger中的相关方法

注意:在注入scheduleInfoManager属性的时候,我们可以去读取DB任务时间(之所以放在setter方法中,是因为需要在设置scheduleInfoManager后进行getCronExpressionFromDB(),否则,也可以①②逻辑把放在类的构造函数中).

注意InitializingCronTrigger必须extends CronTriggerBean.

 

public class InitializingCronTrigger extends CronTriggerBean implements Serializable {

     private ScheduleInfoManager scheduleInfoManager;

     // 设值注入,通过setter方法传入被调用者的实例scheduleInfoManager

     public void setScheduleInfoManager(ScheduleInfoManager scheduleInfoManager){

         this.scheduleInfoManager = scheduleInfoManager;

         // 因为在getCronExpressionFromDB使用到了scheduleInfoManager,所以

         // 必须上一行代码设置scheduleInfoManager后进行getCronExpressionFromDB

         String cronExpression = getCronExpressionFromDB ();    // ①

         // 因为extends CronTriggerBean ,此处调用父类方法初始化cronExpression

        setCronExpression(cronExpression);                     // ②

}

     private String getCronExpressionFromDB(){

         String sql=”from ScheduleInfo scheduleInfo where 1=1 “;

         sql=sql+” and scheduleInfo.infoId = ‘“+”1” + “‘“;

         List scheduleList = scheduleInfoManager.queryScheduleInListBySql(sql);

         ScheduleInfo scheduleInfo = (ScheduleInfo)scheduleList.get(0);

         String dbCronExpression = scheduleInfo.getCronExpression();

         return dbCronExpression;

}

……

}

 

 

附表:

“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触发

至于每个符号 看看例子就好了.很简单了.

时间: 2025-01-20 13:17:51

Quartz在Spring中动态设置cronExpression (spring设置动态定时任务)------转帖的相关文章

在spring中禁止hibernate随spring启动

问题描述 我有这样一个需求,一个程序在初次启动的时候,等用户打开浏览器,在浏览器中输入数据库名,链接地址,密码,数据库类型之后开始连接数据库.但现在是hibernate随spring容器启动,怎样才能阻止hibernate启动呢,等我想让hibernate和数据库连接的时候才开始连接? 解决方案 spring配置文件中不配置datasource,sessionFactory,transactionInterceptor,transactionManager等等任何和数据源和事务有关的bean,让

Spring中的AOP(二)——AOP基本概念和Spring对AOP的支持

AOP的基本概念     AOP从运行的角度考虑程序的流程,提取业务处理过程的切面.AOP面向的是程序运行中的各个步骤,希望以更好的方式来组合业务逻辑的各个步骤.AOP框架并不与特定的代码耦合,AOP框架能处理程序执行中特定切入点,而不与具体某个类耦合(即在不污染某个类的情况下,处理这个类相关的切点).下面是一些AOP的一些术语:     切面(Aspect):业务流程运行的某个特定步骤,也就是应用运行过程的关注点,关注点通常会横切多个对象,因此常被称为横切关注点     连接点(JoinPoi

【JAVA秒会技术之搞定Quartz定时任务】Quartz在Spring中的集成与应用

  Quartz在Spring中的集成与应用   一.Quqrtz简介     Quartz是一个完全由Java编写的开源任务调度的框架,通过触发器设置作业定时运行规则,控制作业的运行时间.主要用来执行定时任务,如:定时发送信息.定时生成报表等等. 简而言之,Quartz是一个定时器组件,是可以整合Spring使用的一个定时器.     二.Quqrtz的配置文件     1.在maven中引入: <dependency> <groupId>org.quartz-scheduler

关于 Spring 中使用 context:property-placeholder 属性占位符设置配置文件

关于 Spring 中使用 context:property-placeholder 属性占位符设置配置文件 太阳火神的美丽人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作公用协议 转载请保留此句:太阳火神的美丽人生 -  本博客专注于 敏捷开发及移动和物联设备研究:iOS.Android.Html5.Arduino.pcDuino,否则,出自本博客的文章拒绝转载或再转载,谢谢合作. 该配置文件中以键值存储,键在 spr

spring中使用quartz时注入时出现的错误

错误1: 配置文件: <!-- 任务执行器的线程池 --> <bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"> <property name="corePoolSize" value="5" /> <property name="ke

Spring Boot 动态数据源(Spring 注解数据源)

本文实现案例场景: 某系统除了需要从自己的主要数据库上读取和管理数据外,还有一部分业务涉及到其他多个数据库,要求可以在任何方法上可以灵活指定具体要操作的数据库. 为了在开发中以最简单的方法使用,本文基于注解和AOP的方法实现,在spring boot框架的项目中,添加本文实现的代码类后,只需要配置好数据源就可以直接通过注解使用,简单方便. 一配置二使用1. 启动类注册动态数据源2. 配置文件中配置多个数据源3. 在需要的方法上使用注解指定数据源 1.在启动类添加 @Import({Dynamic

Spring中@Transactional事务回滚(含实例详细讲解,附源码)

版权声明:本文为博主原创文章,转载注明出处http://blog.csdn.net/u013142781 目录(?)[+] 一.使用场景举例 在了解@Transactional怎么用之前我们必须要先知道@Transactional有什么用.下面举个栗子:比如一个部门里面有很多成员,这两者分别保存在部门表和成员表里面,在删除某个部门的时候,假设我们默认删除对应的成员.但是在执行的时候可能会出现这种情况,我们先删除部门,再删除成员,但是部门删除成功了,删除成员的时候出异常了.这时候我们希望如果成员删

Spring中bean的基本xml配置

xml   在spring容器内拼凑bean叫作装配.装配bean的时候,你是在告诉容器,需要哪些bean,以及容器如何使用依赖注入将它们配合在一起.    理论上,bean装配可以从任何资源获得,包括属性文件,关系数据库等,但xml是最常见的spring 应用系统配置源.Spring中的几种容器都支持使用xml装配bean,包括:    XmlBeanFactory ,    ClassPathXmlApplicationContext ,    FileSystemXmlApplicatio

spring中关于“transactionAttributes”的相关配置

<bean id="baseTransactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" lazy-init="true" abstract="true"> <property name="transactionManager"> <ref be