Spring本身不提供任务调度的直接实现,但是Spring在自身框架原则前提下提供了对Timer和Quartz的集成。使用spring容器可以轻松地对既有的bean进行任务调度。

在说明如何在spring中使用任务调度之前,首先来看看Timer本身。

JDK中提供的Timer是比Quartz更为简单的调度方法,当然,Quartz提供了更为强大的功能。相比Timer,Quartz独有的特性包括:

1、支持持久性作业。Quartz允许将作业状态持久化,在应用服务器重启之间,也能够保持一致的作业状态。

2、类Cron的定时支持。通过Quartz的CronTrigger,Quartz允许使用类似Unix调度的方式来制定作业何时执行。而Timer只允许执行时间和间隔的规范。

3、线程处理模型。Timer是使用单线程实现作业,而Quartz使用线程池来执行作业。线程池的大小以及实现都可以用Quartz属性来制定。

4、提供成熟的事件模型,用于监控调度系统的各个方面包括调度器,触发器和作业。

5、另外Quartz还提供了哑火指令用于指定当任务没有正常激活该做什么。提供了插件支持,提供了servlet用以初始化。

Spring提供了一致的方式来支持这两种调度机制。

1)首先来看Timer,在spring中使用Timer与使用原生态的Timer有所不同,在spring最简单的方法就是使用MethodInvokingTimerTaskFactoryBean方法来创建任务,配置如下

<bean id="methodInvokingTask" class="org.springframework.scheduling.timer.MethodI/nvokingTimerTaskFactoryBean">

      <property name="targetObject"> <ref bean="exampleBusinessObject"/></property>

      <property name="targetMethod"> <value>doSomething</value></property>

</bean>

以上的配置就会创建一个TimerTask,调用exampleBusinessObject的idoSomething。

接下来需要配置的是该timerTask的调度策略:

<bean id="scheduledTask" class="org.springframework.scheduling.timer.ScheduledTimerTask">

      <property name="delay">

               <value>60000</value>

      </property>

      <property name="period">

               <value>60000</value>

       </property>

       <property name="timerTask">

               <ref bean="methodInvokingTask"/>

        </property>

</bean>

以上两个配置指定了要运行什么任务,何时运行,现在还需要预定这些任务:

<bean id="timerFactory" class="org.spring.framework.Scheduling.timer.TimerFactoryBean">

      <property name="ScheduledTimerTask">

             <list>

                  <ref local="ScheduledTask"/>

              </list>

      </property>

</bean>

TimerFactoryBean允许多个ScheduledTask,它会创建和管理Timer实例。

我们除了使用methodInvokingTask这种非侵入方式的TimeTask而外,我们还可以使用自己定义的TimerTask。

Package org.springframework.prospring.scheduling;

public class CustomTask extends TimerTask{   

      public void run(){// do something}
 }

然后直接以spring bean方式配置,替换methodInvokingTask。

2)然后来看看使用Quartz对上述任务的配置。

 

<bean id="methodInvokingJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">

      <property name="targetObject"> <ref bean="exampleBusinessObject"/></property>

      <property name="targetMethod"> <value>doSomething</value></property>

</bean>

<bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">

       <property name="startDelay"><value>6000</value></property>

       <property name="repeatInterval"><value>6000</value></property>

</bean>

<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">

       <property name="triggers">

              <list><ref local="simpleTrigger"/></list>

       </property>

</bean>

在Timer中只有两个概念TimerTask和Timer,至于调度细节是通过重载Timer的schedule方法来制定,只是在spring集成中spring将其分解成为了三个步骤。而Quartz确有四个概念,Scheduler(调度器)Trigger(触发器)Job(任务)JobDetail(工作细节),接下来详细来看这四个元素,以及spring对它们的支持:

job

job是具体任务的实现,需要继承自QuartzJobBean并在executeInternal方法中实现具体的任务细节。该方法接受一个参数,JobExcutionContext,其中包含了几乎所有信息的引用,以及需要存放的数据,以供在作业执行之间传递信息。实例代码如下:

package org.springframework.prospring.scheduling;

 

public class ExampleJob extends QuartzJobBean{

      private long lastExecutionDate;

      public void setListExecutionDate(long lastExecutionDate){

            this.lastExecutionDate = lastExecutionDate;

      }

      protected void executeInternal(JobExcutionContext context){

            //do some thing

            // read or write data

            JobDataMap map = context,getJobDetail().getJobDataMap();

            map.put(”lastExecutionDate",System.currentTimeMills());

      }

}

该类的初始化时在Quartz中进行的,需要首先包裹在JobDetail中,JobDetail中负责持有当前任务的相关默认数据。配置如下

<bean id="exampleJobBean" class="org.springframework.quartz.JobDetailBean">

       <property name="name"><value>example</value>

       <property name="group"><value>examples</value>

       ......

       <property name="jobClass">

              <value>org.springframework.prospring.scheduling.ExampleJob</value>

       </property>

<bean>

触发器,触发器中描述了作业的触发策略。之前的例子中已经提到一种方式,其实Quartz提供了两种方式触发器,simple和cron。cron使用类似于Unix中的调度描述表达式,配置如下:

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

       <property name="jobDetail">

              <ref bean="exampleJobDetail"/>

       </property>

       <property name="cronExpression">

               <value>0 15 4 ? * MON-FRI</value>

       </property> 

<bean>

触发器中还可以指定哑火指令,指定监听器。

调度器,作为Quartz系统的主要部分,它维护了所有的作业细节和关联触发器的一个注册项;它在作业被激活的时候,它管理作业的创建和运行,并且负责保持作业的状态信息。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐