您的位置:首页 > 编程语言 > Java开发

Spring task quartz 示例

2016-08-04 11:59 309 查看

说在前面:

本文基于Spring 4.0.6, 我们新来了解一下Spring的关于task和集成quartz的一些版本特性。

Spring 自3.0版本以后便自带的task,可以将它看成一个轻量级的Quartz,而且使用起来比Quartz简单许多。

Spring 4.0.3以后task的源码可以在spring-context-4.0.3.RELEASE-sources.jar查阅, 源码包路径:org.springframework.scheduling

Spring Task 支持注解方式和Xml方式,后文可以看到相关的示例代码。

Quartz 在 Spring.4.0.6版本中,集成源码在 spring-context-support-4.0.6.RELEASE-sources.jar, 包路径org.springframework.scheduling.quartz

Spring Quartz 继承org.quartz, 因此我们需要 quartz-2.2.1.jar 或者其他版本架包, 建议使用quartz-2.2.1.jar。

需要注意的是: Spring + Quartz 版本兼容问题

通过Spring Quartz, 我们可以使用两种方式实现Spirng定时任务:

1、继承自org.springframework.scheduling.quartz.QuartzJobBean

2、作业类即普通的java类,不需要继承自任何基类。

定时器任务有两种触发器:

1、按照一定频度调用任务,在Spring Quartz中对应的触发器为:org.springframework.scheduling.quartz.SimpleTriggerBean

2、按照指定时间调用任务,在Spring Quartz中对应的调度器为:org.springframework.scheduling.quartz.CronTriggerBean

**这两个触发器与Quartz 的 org.quartz.impl.triggers.SimpleTriggerImpl

org.quartz.impl.triggers.CronTriggerImpl 本质上没有区别。**

Spring Task示例

第一种:注解方式:

SpringTaskAnnotation.java

import java.util.Date;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

/**
* 基于注解的定时器
*/
@Component
public class SpringTaskAnnotation {

// 定时计算。每一秒执行一次
@Scheduled(cron = "0/1 * * * * *")
public void show(){
System.out.println(new Date() + " : Annotation:is show run");
}

/**
* 心跳更新。启动时执行一次,之后每隔2秒执行一次
*/
@Scheduled(fixedRate = 1000*2)
public void print(){
System.out.println(new Date() + " : Annotation:is print run");
}

// 启动加载缓存, 以上一次执行完为准
@Scheduled(fixedDelay = 1 * 1000)
public void init() {
System.out.println(new Date() + ": Annotation:is init run");
}

}


spring-mvc.xml

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd"> 
<!-- 定时器注解开关, 可以配置 scheduler参数 -->
<task:annotation-driven />
<!-- bean注解开关 -->
<context:annotation-config />
<!-- 自动扫描的包名 -->
<context:component-scan base-package="quartz" />

</beans>


SpringTaskAnnotationTest.java

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringTaskAnnotationTest{

public static void main(String[] args) throws BeansException {
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-mvc.xml");
}
}


执行结果:

Thu Aug 04 11:03:33 CST 2016 : Annotation:is print run

Thu Aug 04 11:03:33 CST 2016: Annotation:is init run

Thu Aug 04 11:03:34 CST 2016 : Annotation:is show run

Thu Aug 04 11:03:35 CST 2016 : Annotation:is show run

说明: fixedRate和fixedDelay的区别

fixedRate :每隔多少毫秒执行一次该方法, 以上一次执行开始时间计算

fixedDelay:当一次方法执行完毕之后,延迟多少毫秒再执行该方法

第二种:XML配置方式:

SpringTaskXml.java

import java.util.Date;

/**
* 基于xml的定时器
*/
public class SpringTaskXml {

public void show(){
System.out.println(new Date() + " : XMl is show run");
}

public void print(){
System.out.println(new Date() + " : XMl print run");
}
}


spring-mvc.xml

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd"> 
<bean id="task" class="quartz.SpringTaskXml"></bean>

<task:scheduled-tasks>
<!--  这里表示的是每隔五秒执行一次   -->
<task:scheduled ref="task" method="show" cron="*/5 * * * * ?" />
<task:scheduled ref="task" method="print" cron="*/10 * * * * ?"/>
</task:scheduled-tasks>

</beans>


SpringTaskXmlTest.java

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringTaskXmlTest{

public static void main(String[] args) throws BeansException {
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-mvc.xml");
}
}


执行结果:

Thu Aug 04 11:03:35 CST 2016 : Annotation:is print run

Thu Aug 04 11:03:36 CST 2016 : Annotation:is show run

Spring Quartz 示例

第一种,作业类继承自特定的基类:org.springframework.scheduling.quartz.QuartzJobBean

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;

public class Job1 extends QuartzJobBean {

private int timeout;
private static int i = 0;
//调度工厂实例化后,经过timeout时间开始执行调度
public void setTimeout(int timeout) {
this.timeout = timeout;
}

/**
* 要调度的具体任务
*/
@Override
protected void executeInternal(JobExecutionContext context)  throws JobExecutionException {
System.out.println("定时任务执行中…");
}
}


spring-mvc.xml

<bean name="job1" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="Job1" />
<property name="jobDataAsMap">
<map>
<entry key="timeout" value="0" />
</map>
</property>
</bean>

<!-- SimpleTriggerBean 触发器 -->
<bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
<property name="jobDetail" ref="job1" />
<property name="startDelay" value="0" /><!-- 调度工厂实例化后,经过0秒开始执行调度 -->
<property name="repeatInterval" value="2000" /><!-- 每2秒调度一次 -->
</bean>

<!-- CronTriggerBean触发器 -->
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobDetail" ref="job1" />
<!—每天12:00运行一次 -->
<property name="cronExpression" value="0 0 12 * * ?" />
</bean>

<!-- 调度器 -->
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="cronTrigger" />
<ref bean="simpleTrigger" />
</list>
</property>
</bean>


测试类, 同SpringTaskAnnotationTest.java

第二种,作业类不继承特定基类

Spring能够支持这种方式,归功于两个类:

org.springframework.scheduling.timer.MethodInvokingTimerTaskFactoryBean

org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean

这两个类分别对应spring支持的两种实现任务调度的方式,即java自带的timer task方式和Quartz方式。

Job2.java

public class Job2 {
public void doJob2() {
System.out.println("不继承QuartzJobBean方式-调度进行中...");
}
}


spring-mvc.xml

<bean id="job2"    class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject">
<bean class="Job2" />
</property>
<property name="targetMethod" value="doJob2" />
<property name="concurrent" value="false" /><!-- 作业不并发调度 -->
</bean>

<!-- SimpleTriggerBean 触发器 -->
<bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
<property name="jobDetail" ref="job1" />
<property name="startDelay" value="0" /><!-- 调度工厂实例化后,经过0秒开始执行调度 -->
<property name="repeatInterval" value="2000" /><!-- 每2秒调度一次 -->
</bean>

<!-- CronTriggerBean触发器 -->
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="job1" />
<!—每天12:00运行一次 -->
<property name="cronExpression" value="0 0 12 * * ?" />
</bean>

<!-- 调度器 -->
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="cronTrigger" />
<ref bean="simpleTrigger" />
</list>
</property>
</bean>


测试类, 同SpringTaskAnnotationTest.java

cronExpression配置说明

字段允许值允许的特殊字符
0-59, - * /
0-59, - * /
小时0-23, - * /
日期1-31, - * ? / L W C
月份1-12 或者 JAN-DEC, - * /
星期1-7 或者 SUN-SAT, - * ? / L C #
年(可选)留空, 1970-2099, - * /
特殊字符说明:

字符意义
*表示所有值;
?表示未说明的值,即不关心它为何值;
-表示一个指定的范围;
,表示附加一个可能值;
/符号前表示开始时间,符号后表示每次递增的值;
L(“last”)(“last”) “L” 用在day-of-month字段意思是
W(“weekday”)只能用在day-of-month字段。用来描叙最接近指定天的工作日(周一到周五)。例如:在day-of-month字段用“15W”指“最接近这个月第15天的工作日”,即如果这个月第15天是周六,那么触发器将会在这个月第14天即周五触发;如果这个月第15天是周日,那么触发器将会在这个月第16 天即周一触发;如果这个月第15天是周二,那么就在触发器这天触发。注意一点:这个用法只会在当前月计算值,不会越过当前月。“W”字符仅能在day- of-month指明一天,不能是一个范围或列表。也可以用“LW”来指定这个月的最后一个工作日。
#只能用在day-of-week字段。用来指定这个月的第几个周几。例:在day-of-week字段用”6#3”指这个月第3个周五(6指周五,3指第3个)。如果指定的日期不存在,触发器就不会触发。
C指和calendar联系后计算过的值。例:在day-of-month 字段用“5C”指在这个月第5天或之后包括calendar的第一天;在day-of-week字段用“1C”指在这周日或之后包括calendar的第一天。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息