`

spring 调度使用

阅读更多
Quartz在Spring中动态设置cronExpression (spring设置动态定时任务)

    2007-07-25 13:52

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

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

    <bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean" >

                  <property name="jobDetail" ref="schedulerJobDetail"/>
                  <property name="cronExpression">
                          <value>0/10 * * * * ?</value>
                  </property>
    </bean>
         中cronExpression是关键,如果可以动态设置cronExpression的值,也就说如果我们可以直接调用CronTriggerBean中设置cronExpression的方法,就可以顺利解决问题了。
    熟悉1的朋友可以跳过不看,下面2、3是动态定时任务的具体实现。
    1、Quartz在Spring中的简单配置

    Spring配置文件:

         <bean id="schedulerJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
                 <property name="targetObject" ref="scheduleInfoAction"/>
                 <property name="targetMethod" value="simpleJobTest"/>
                 <property name="concurrent" value="false"/>
         </bean>
         <bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean" >
                  <property name="jobDetail" ref="schedulerJobDetail"/>
                  <property name="cronExpression">
                          <value>0/10 * * * * ?</value>
                  </property>
          </bean>
         <bean id="schedulerFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
                 <property name="triggers">
                         <list>
                                 <ref local="cronTrigger"/>
                         </list>
                 </property>
    </bean>
    在上面的配置中设定了
    ① 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配置文件:
    <bean id="scheduleInfoAction" class="com.lively.happyoa.jobs.webapp.action.ScheduleInfoAction">
                 <property name="scheduler" ref="schedulerFactory"/>
                 <property name="scheduleInfoManager" ref="scheduleInfoManager"/>
         </bean>
         <bean id="schedulerJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
                 <property name="targetObject" ref="scheduleInfoAction"/>
                 <property name="targetMethod" value="reScheduleJob"/>
                 <property name="concurrent" value="false"/>
         </bean>
         <bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean" >
                  <property name="jobDetail" ref="schedulerJobDetail"/>
                  <property name="cronExpression">
                          <value>0/10 * * * * ?</value>
                  </property>
          </bean>
         <bean id="schedulerFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
                 <property name="triggers">
                         <list>
                                 <ref local="cronTrigger"/>
                         </list>
        </property>
    </bean>
    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配置中的
             <property name="cronExpression">
                      <value>0/10 * * * * ?</value>
              </property>
    则容器(如tomcat)启动时会报错。
    实际中我们希望tomcat启动时就可以直接去读数据库,拿到相应的dbCronExpression,然后定时执行一个job,而不希望配置初始的cronExpression ,观察下面的CronTriggerBean,考虑到cronExpression需要初始化,如果设定一个类InitializingCronTrigger继承CronTriggerBean,然后在这个类中做一些读取DB的初始化工作(设置cronExpression),问题就可以解决了。
    Spring配置文件:
    <bean id="scheduleInfoAction" class="com.lively.happyoa.jobs.webapp.action.ScheduleInfoAction">
                 <property name="scheduler" ref="schedulerFactory"/>
                 <property name="scheduleInfoManager" ref="scheduleInfoManager"/>
         </bean>
         <bean id="schedulerJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
                 <property name="targetObject" ref="scheduleInfoAction"/>
                 <property name="targetMethod" value="reScheduleJob"/>
                 <property name="concurrent" value="false"/>
         </bean>
        <bean id="cronTrigger" class="com.lively.happyoa.jobs.webapp.action.ScheduleInfoAction.InitializingCronTrigger">
                  <property name="jobDetail" ref="schedulerJobDetail"/>
                 <!--<property name="cronExpression">
                          <value>0/10 * * * * ?</value>
                  </property>-->
                  <property name="scheduleInfoManager" ref="scheduleInfoManager"/>
          </bean>
         <bean id="schedulerFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
                 <property name="triggers">
                         <list>
                                 <ref local="cronTrigger"/>
                         </list>
                 </property>
    </bean>
    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-59 , - * /

分 0-59 , - * /

小时 0-23 , - * /

日 1-31 , - * ? / L W C

月 1-12 or JAN-DEC , - * /

周几 1-7 or SUN-SAT , - * ? / L C #

年 (可选字段) empty, 1970-2099 , - * /

可用值详细分析如下:

“*”——字符可以用于所有字段,在“分”字段中设为"*"表示"每一分钟"的含义。

“?”——字符可以用在“日”和“周几”字段. 它用来指定 '不明确的值'. 这在你需要指定这两个字段中的某一个值而不是另外一个的时候会被用到。在后面的例子中可以看到其含义。

“-”——字符被用来指定一个值的范围,比如在“小时”字段中设为"10-12"表示"10点到12点"。

“,”——字符指定数个值。比如在“周几”字段中设为"MON,WED,FRI"表示"the days Monday, Wednesday, and Friday"。

“/”——字符用来指定一个值的的增加幅度. 比如在“秒”字段中设置为"0/15"表示"第0, 15, 30, 和 45秒"。而 "5/15"则表示"第5, 20, 35, 和 50". 在'/'前加"*"字符相当于指定从0秒开始. 每个字段都有一系列可以开始或结束的数值。对于“秒”和“分”字段来说,其数值范围为0到59,对于“小时”字段来说其为0到23, 对于“日”字段来说为0到31, 而对于“月”字段来说为1到12。"/"字段仅仅只是帮助你在允许的数值范围内从开始"第n"的值。

“L”——字符可用在“日”和“周几”这两个字段。它是"last"的缩写, 但是在这两个字段中有不同的含义。例如,“日”字段中的"L"表示"一个月中的最后一天" —— 对于一月就是31号对于二月来说就是28号(非闰年)。而在“周几”字段中, 它简单的表示"7" or "SAT",但是如果在“周几”字段中使用时跟在某个数字之后, 它表示"该月最后一个星期×" —— 比如"6L"表示"该月最后一个周五"。当使用'L'选项时,指定确定的列表或者范围非常重要,否则你会被结果搞糊涂的。

“W”——可用于“日”字段。用来指定历给定日期最近的工作日(周一到周五) 。比如你将“日”字段设为"15W",意为: "离该月15号最近的工作日"。因此如果15号为周六,触发器会在14号即周五调用。如果15号为周日, 触发器会在16号也就是周一触发。如果15号为周二,那么当天就会触发。然而如果你将“日”字段设为"1W", 而一号又是周六, 触发器会于下周一也就是当月的3号触发,因为它不会越过当月的值的范围边界。'W'字符只能用于“日”字段的值为单独的一天而不是一系列值的时候。

“L”和“W”可以组合用于“日”字段表示为'LW',意为"该月最后一个工作日"。

“#”—— 字符可用于“周几”字段。该字符表示“该月第几个周×”,比如"6#3"表示该月第三个周五( 6表示周五而"#3"该月第三个)。再比如: "2#1" = 表示该月第一个周一而 "4#5" = 该月第五个周三。注意如果你指定"#5"该月没有第五个“周×”,该月是不会触发的。

“C”—— 字符可用于“日”和“周几”字段,它是"calendar"的缩写。 它表示为基于相关的日历所计算出的值(如果有的话)。如果没有关联的日历, 那它等同于包含全部日历。“日”字段值为"5C"表示"日历中的第一天或者5号以后",“周几”字段值为"1C"则表示"日历中的第一天或者周日以后"。

对于“月份”字段和“周几”字段来说合法的字符都不是大小写敏感的。

附表:
"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触发
至于每个符号 看看例子就好了.很简单了.
分享到:
评论

相关推荐

    使用spring调度

    本篇文章将深入探讨Spring调度的使用,包括核心概念、配置方式以及源码解析。 1. **Spring调度核心组件** Spring调度主要由两个关键组件构成:`TaskScheduler`和`ThreadPoolTaskScheduler`。`TaskScheduler`是...

    spring 任务调度

    Spring Task是Spring内置的轻量级任务调度器,而Quartz是更强大的第三方调度库,可以在Spring中集成使用。 1. **Spring Task** - **基本概念**:Spring Task是Spring框架的一部分,提供了基本的定时任务调度功能,...

    spring 任务调度实现代码例子

    这个“spring 任务调度实现代码例子”很可能是包含了一些示例代码,用于演示如何在Spring应用中配置和使用任务调度。下面将详细解释Spring任务调度的关键概念和实现方法。 1. **Spring Task模块** Spring Task是...

    Spring实现任务调度

    本篇将深入探讨如何利用Spring进行任务调度,并结合代码演示和Quartz库的使用来丰富这一主题。 首先,Spring提供了两种主要的任务调度机制:Spring内置的`TaskExecution`和`TaskScheduling`以及与Quartz Scheduler...

    spring调度器用到的jar

    下面将详细介绍Spring调度器的相关知识点。 一、Spring Task模块 Spring Task是Spring Framework的一部分,提供了异步任务执行和定时任务调度的能力。它包括两个主要部分:`TaskExecutor`用于异步任务执行,而`...

    运用Spring框架实现简单调度

    当前很多开源项目也提供了比较全面的调度功能,如quartz、jcrontab、JobServer等,在这里我介绍一种比较简单的调度,没有quartz那么复杂,目的在于实用就行,这种调度就是spring提供的调度功能,该调度功能基于...

    Spring定时调度简单实现源码

    这个"Spring定时调度简单实现源码"很显然是一个关于如何在Spring中配置和使用定时任务的示例代码包。下面我们将深入探讨Spring的定时调度机制以及其核心组件。 Spring的定时任务调度主要依赖于两个关键组件:`Task...

    Spring实现任务调度.rar

    Spring框架提供了强大的任务调度能力,使得开发者能够轻松地集成和管理定时任务。本资料“Spring实现任务调度”将深入探讨如何在Spring中设置和管理定时任务。 首先,我们需要理解Spring中的任务调度机制。Spring...

    spring任务调度(Quartz )

    Spring中的任务调度是实现应用程序自动化运行任务的重要工具,而Quartz是Java领域广泛使用的开源任务调度框架。在本文中,我们将深入探讨如何在Spring中集成Quartz进行任务调度,并通过一个简单的示例来理解其工作...

    Spring调度器corn表达式

    这个是关于Spring调度器的使用 里面详细介绍了各个时间的表达式,有需要可以下载。

    spring调度器

    Spring调度器主要由两个核心组件组成:`TaskExecutor`和`TaskScheduler`,它们分别用于异步执行任务和计划任务。 **TaskExecutor** `TaskExecutor`是Spring提供的一个接口,用于执行异步任务。通过实现这个接口,你...

    Spring整合任务调度框架Quartz

    Spring 整合任务调度框架 Quartz ...Spring 整合任务调度框架 Quartz,可以使用配置文件方式或 Quartz 持久化方式来实现任务调度。开发者可以根据实际情况选择合适的方式,从而提高软件系统的自动化和可靠性。

    spring时间调度配置

    本文将详细介绍如何利用Spring进行时间调度配置,包括基本配置、定时任务实现以及Cron表达式的使用。 ### 一、Spring时间调度简介 Spring框架内置了多种任务调度的支持方式,其中最常用的是基于`org.spring...

    quartz案例,包括spring配置设置调度器和入门手册

    通过以上内容,你可以开始使用Quartz进行任务调度,并结合Spring实现更灵活的管理。继续深入学习Quartz的高级特性,如集群支持、作业监听器和触发器监听器,将有助于构建更加健壮和可扩展的定时任务系统。

    Spring中Quartz调度器的使用

    Spring 中 Quartz 调度器的使用 Spring 中 Quartz 调度器的使用是指在 Spring 框架中使用 Quartz 调度器来实现任务调度。Quartz 是一个功能强大且灵活的开源任务调度器,能够满足复杂的任务调度需求。在 Spring 中...

    Spring定时调度——将调度信息持久化到数据库中

    在IT行业中,Spring框架是Java领域最常用的轻量级开源框架之一,它的功能强大且全面,其中就包括了定时任务调度。本篇文章将探讨如何在Spring中实现定时调度,并将调度信息持久化到数据库中,这在实际业务场景中非常...

    Spring任务调度demo

    通过阅读并理解上述代码和概念,你将能够熟练地在Spring中进行任务调度,无论是使用内置功能还是集成Quartz。在`mySpringTask`这个压缩包文件中,很可能包含了这些示例的源代码,你可以进一步研究和实践。

    Spring Quartz 任务调度实例

    Spring Quartz 是一个强大的任务调度框架,它允许开发者在Java应用程序中定义和执行定时任务。结合Spring框架,可以方便地在企业级应用中实现复杂的时间触发逻辑。本实例提供了可以直接运行的任务调度解决方案,既...

    spring的三种任务调度实现方式lib

    虽然Spring Batch不直接提供定时任务调度,但它可以与Spring的`TaskScheduler`或Quartz结合使用来实现定时启动批处理作业。Spring Batch支持多种类型的读写器和处理器,适用于大量数据的导入导出、数据库更新等场景...

    spring任务调度实例

    本实例主要探讨了Spring如何实现任务调度,特别是使用Quartz和Timer两种不同的方法。 首先,Quartz是一个开源的作业调度框架,它允许开发者创建、调度和执行作业,这些作业可以是简单的Java类或者Spring Bean。...

Global site tag (gtag.js) - Google Analytics