Spring 集成quartz框架的两种方式
Java项目中常使用的定时器有JDK Timer、Quartz、Spring Task等三种。Quartz的功能强大,配置也比较复杂,适合大型、多定时任务的项目使用。Spring Task配置较为简单轻量,需要Spring框架支持。JDK自带的定时器Timer使用灵活,配置简单,适合中小型项目。这里记录下quartz方式
一、Quartz作业类的继承方式来讲,可以分为两类:
- 作业类需要继承自特定的作业类基类,如Quartz中需要继承自org.springframework.scheduling.quartz.QuartzJobBean;
- 作业类即普通的java类,不需要继承自任何基类。
使用QuartzJobBean,需要继承,而且在注入Spring容器中其他service时候需要在schedulerContextAsMap中注入,比较麻烦,否则不能成功(具体操作参考:https://blog.****.net/whaosy/article/details/6298686)。
使用MethodInvokeJobDetailFactoryBean则需要指定targetObject(任务实例)和targetMethod(实例中要执行的方法),可以方便注入Spring容器中其他的service。后者优点是无侵入,业务逻辑简单。所以我更推荐的第二种!
二、从任务调度的触发时机来分,这里主要是针对作业使用的触发器,主要有以下两种:
- 每隔指定时间则触发一次,在Quartz中对应的触发器为:org.springframework.scheduling.quartz.SimpleTriggerBean
- 每到指定时间则触发一次,在Quartz中对应的调度器为:org.springframework.scheduling.quartz.CronTriggerBean
三、下面针对两种分别讲解
1.作业类继承自特定的基类:org.springframework.scheduling.quartz.QuartzJobBean
package com.summer.job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Component;
import com.summer.opendoor.service.OpenDoorService;
//@Component
public class Job extends QuartzJobBean{
public Job() {
super();
System.out.println("JOB初始化");
}
@Autowired
private OpenDoorService openDoorService;
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
System.out.println("JOB任务执行了");
//如果没有在schedulerContextAsMap中注入openDoorService ,则这里是null
//openDoorService.open();
}
}
注意图片红框中的引用,分三步,先定义jobDetail,然后定义触发器,最后是调度工厂
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
<!--第一步:1.将自定义的job类(已经继承QuartzJobBean) 注入JobDetailFactoryBean -->
<bean id="jobDetail"
class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="com.summer.job.Job"></property>
<property name="durability" value="true"></property>
</bean>
<!--第二步:2. 定义触发器,并且将jobDetail注入 -->
<bean id="simpleTrigger"
class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
<property name="jobDetail" ref="jobDetail" />
<!-- 调度工厂实例化后,经过3秒开始执行调度 -->
<property name="startDelay" value="3000" />
<!-- 每隔2秒执行一次 -->
<property name="repeatInterval" value="2000" />
</bean>
<!-- 总管理类 如果将lazy-init='false'那么容器启动就会执行调度程序 -->
<!-- 第三步:配置调度工厂 -->
<bean id="startQuertz" lazy-init="false" autowire="no"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<!-- 管理trigger -->
<property name="triggers">
<list>
<ref bean="simpleTrigger" />
</list>
</property>
</bean>
</beans>
2.作业类不继承特定基类 强烈推荐这种
package com.summer.job;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.summer.opendoor.service.OpenDoorService;
@Component
public class JobMethodInvoke{
public JobMethodInvoke() {
super();
System.out.println("JobMethodInvoke初始化");
}
@Autowired
private OpenDoorService openDoorService;
protected void doSomething() {
System.out.println("JOB任务执行了");
openDoorService.open();
}
}
注意中间的引用关系,如下图
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
<!--第一步 要执行任务的作业类。 -->
<bean id="testQuartz" class="com.summer.job.JobMethodInvoke" />
<!-- 第二步 将需要执行的定时任务注入JOB中。 -->
<bean id="jobDetail"
class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="testQuartz"></property>
<!-- 任务类中需要执行的方法 -->
<property name="targetMethod" value="doSomething"></property>
<!-- 上一次未执行完成的,要等待有再执行。 -->
<property name="concurrent" value="false"></property>
</bean>
<!--第三步 基本的定时器,会绑定具体的任务。 -->
<!-- 第一种 SimpleTriggerBean,只支持按照一定频度调用任务,如每隔30分钟运行一次。配置方式如下: -->
<!-- <bean id="testTrigger"
class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
<property name="jobDetail" ref="jobDetail"></property>
<property name="startDelay" value="3000"></property>
<property name="repeatInterval" value="2000"></property>
</bean> -->
<!-- 第二种 CronTriggerBean,支持到指定时间运行一次,如每天12:00运行一次等。配置方式如下: -->
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail" ref="jobDetail" />
<!-- <!—每天12:00运行一次 —> -->
<property name="cronExpression" value="0 0 12 * * ?" />
</bean>
<!-- 第四步 配置调度工厂 -->
<bean id="schedulerFactoryBean" lazy-init="true"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<!-- <ref bean="testTrigger"></ref> -->
<ref bean="cronTrigger" />
</list>
</property>
</bean>
</beans>