使用的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个)有空格分隔的时间元素,从左到右分别代表
- 秒(0-59)
- 分(0-59)
- 小时(0-23)
- 月份中的日期(1-31)
- 月份(1-12或JAN-DEC)
- 星期中的日期(1-7或SUN-SAT)
- 年份(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>