Spring 3.x 使用 Quartz Scheduler

使用的spring的版本为3.1.1,quartz的版本为1.8.6(可以去http://quartz-scheduler.org下载),本来是用最新版2.1.6的,不过由于该版本与spring不兼容。
后来发现:org.springframework.scheduling.quartz.CronTriggerBean继承了org.quartz.CronTrigger,而在quartz-2.1.6中org.quartz.CronTrigger是个接口,而在quartz-1.8.6中org.quartz.CronTrigger是个类,从而造成无法在applicationContext中配置触发器。这是spring3和quartz2版本不兼容的一个bug。
按照Spring Reference Documentation 里的说法,实现Quartz Scheduler有两种方法:

第一种

使用JobDetailBean,任务类继承QuartzJobBean类。

public class ExampleJob extends QuartzJobBean {
  private int timeout;
  
  /**
   * Setter called after the ExampleJob is instantiated
   * with the value from the JobDetailBean (5)
   */ 
  public void setTimeout(int timeout) {
    this.timeout = timeout;
  }
  
  protected void executeInternal(JobExecutionContext ctx) throws JobExecutionException {
      // do the actual work
  }
}

在applicationContext.xml中加入

<bean name="exampleJob" class="org.springframework.scheduling.quartz.JobDetailBean">
  <property name="jobClass" value="example.ExampleJob" />
  <property name="jobDataAsMap">
    <map>
      <entry key="timeout" value="5" />
    </map>
  </property>
</bean>

第二种

在配置文件里定义任务类和要执行的方法,类和方法仍然是普通类。明显这种比第一种更加的灵活。
以下代码为任务类:

public class ExampleBusinessObject {
  
  // properties and collaborators
  public void doIt() {
    // do the actual work
  }
}

在applicationContext.xml中加入

<bean id="exampleBusinessObject" class="examples.ExampleBusinessObject"/>

<bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
  <property name="targetObject" ref="exampleBusinessObject" />
  <property name="targetMethod" value="doIt" />
  <property name="concurrent" value="false" />
</bean>

要注意的是MethodInvokingJobDetailFactoryBean类默认是并发执行的,这时候如果不设置“concurrent”为false,很可能带来并发或者死锁的问题,而且几率较小,不容易复现,请大家使用的时候注意设置“concurrent”。
以上两种方法,用任意一种都行。配置好任务类,就要开始执行它了。那就需要用到Trigger了,Trigger有两种:
第一种 SimpleTriggerBean 这种只能设置每隔多少秒执行一次任务。在applicationContext.xml中加入

<bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
    <!-- see the example of method invoking job above -->
    <property name="jobDetail" ref="jobDetail" />
    <!-- 10 seconds -->
    <property name="startDelay" value="10000" />
    <!-- repeat every 50 seconds -->
    <property name="repeatInterval" value="50000" />
</bean>

第二种 CronTriggerBean 这种比较灵活 可以设置某个时刻执行,也可以设置间隔时间执行。在applicationContext.xml中加入

<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
     <property name="jobDetail" ref="exampleJob" />
     <!-- run every morning at 6 AM -->
     <property name="cronExpression" value="0 0 6 * * ?" />
</bean>

下面简要说明一下Cron表达式
cronExpression 中的value 有至少6个(也可能7个)有空格分隔的时间元素,从左到右分别代表

  1. 秒(0-59)
  2. 分(0-59)
  3. 小时(0-23)
  4. 月份中的日期(1-31)
  5. 月份(1-12或JAN-DEC)
  6. 星期中的日期(1-7或SUN-SAT)
  7. 年份(1970-2099)

星号(*):可用在所有字段中,表示对应时间域的每一个时刻,例如,*在分钟字段时,表示“每分钟”;
问号(?):该字符只在日期和星期字段中使用,它通常指定为“无意义的值”,相当于点位符;
减号(-):表达一个范围,如在小时字段中使用10-12,则表示从10到12点,即10,11,12;
逗号(,):表达一个列表值,如在星期字段中使用MON,WED,FRI,则表示星期一,星期三和星期五;
斜杠(/):x/y表达一个等步长序列,x为起始值,y为增量步长值。如在分钟字段中使用0/15,则表示为0,15,30和45秒,而5/15在分钟字段中表示5,20,35,50,你也可以使用*/y,它等同于0/y
最后,加入Trigger之后,需要SchedulerFactoryBean来生产Trigger。在applicationContext.xml中加入

<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <property name="triggers">
        <list>
            <ref bean="cronTrigger" />
            <ref bean="simpleTrigger" />
        </list>
    </property>
</bean>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,001评论 19 139
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,974评论 6 342
  • Quartz 中集群如何工作 一个 Quartz 集群中的每个节点是一个独立的 Quartz 应用,它又管理着其他...
    那脸憔悴阅读 2,775评论 1 52
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,779评论 18 399
  • 拖着满身疲倦的身体,终于等来了下班的时刻。回家的路途需要两个半小时,但我并不认为回程距离太过遥远,这反而是一种回归...
    光阴没有名字阅读 666评论 0 0