quartz任务调度框架与spring整合

时间:2021-09-29 00:54:02

Quartz是什么?

Quartz 是一种功能丰富的,开放源码的作业调度库,可以在几乎任何Java应用程序集成 - 从最小的独立的应用程序到规模最大电子商务系统。Quartz可以用来创建简单或复杂的日程安排执行几十,几百,甚至是十万的作业数 - 作业被定义为标准的Java组件,可以执行几乎任何东西,可以编程让它们执行。 Quartz调度包括许多企业级功能,如JTA事务和集群支持。

通过触发器结合cron表达式,可以实现丰富的执行策略满足生产需求.

maven引入quartz包

<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.2.1</version>
</dependency>

Job

为了更好的与spring框架整合,以下代码选择继承实现了Job接口的QuartzJobBean

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean; /**
*
* @author ***
* email:***@163.com
* @create 2018-04-20 10:33 AM
**/ public class HelloQuartzJob extends QuartzJobBean { protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
System.out.println("Hello Quartz !!!!");
}
}

executeInternal方法内部实现用户自定义业务逻辑.

与spring整合

job配置

    <bean id="helloQuartzJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="com.**.xtfx.quarz.**.job.HelloQuartzJob"/>
<!--任务名-->
<property name="name" value="helloQuartzJob"/>
<!--任务描述-->
<property name="description" value="任务描述"/>
<!--任务所属组-->
<property name="group" value="group"/>
<!--任务在没有触发器绑定时不消亡-->
<property name="durability" value="true"/>
</bean>

trigger配置

    <bean id="helloQuartzJobCronTrigger"
class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<!--任务bean-->
<property name="jobDetail" ref="helloQuartzJob"/>
<!--任务触发条件-->
<property name="cronExpression" value="0 0/30 10-18 * * ?"/>
</bean>

helloQuartzJob任务加入任务调度器

    <!--任务总调度器-->
<bean id="stdScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="transactionManager" ref="transactionManagerBusiness"/>
<property name="triggers">
<list>
<ref bean="helloQuartzJobCronTrigger"/>
</list>
</property> <property name="jobDetails">
<list>
<ref bean="helloQuartzJob"/>
</list>
</property>
</bean>

上述配置包含到spring的配置中后,任务将于每天10:00至19:00每30分钟触发一次.

quartz任务执行方式与参数传递

任务执行

上述job定以后,在quartz中是并发执行的.对于同一个job的多个实例,它们之间是独立运行,即当HelloQuartzJob的实例A还没有执行完毕,此时却到了HelloQuartzJob的下一次触发时间,则会另起一个实例B,也就无法满足当前时刻有且仅有一个任务实例在运行的情况.注解DisallowConcurrentExecution则可以满足这以需求,它能保证被其注解的类在任意时刻仅有一个实例在运行.

参数传递

对于有些需要像Job实例传入参数的情况,可以通过JobDetailFactoryBeanjobDataAsMap属性传入,然后Job在实例化的时候会通过各属性对应的set方法完成注入,如果没有在Job类中设置属性和属性方法则需要通过一下方式获取相关参数:

        //  获取运行参数
JobDataMap map = context.getJobDetail().getJobDataMap();

根据参数名从map中获取相应的变量.

如果想让同一个Job的下一个实例获取上一个实例的参数则需要完成以下步骤:

  • 类顶部加注解@PersistJobDataAfterExecution
  • 上一个任务完成前写入需要被下一个任务获取的变量以及对应的属性值
     //  获取运行参数
JobDataMap map = context.getJobDetail().getJobDataMap();
....
....
map.put("times", map.getInt("times") + 1);

整合

基于以上内容修改第一节的HelloQuartzJob,是的其对应实例任意时刻仅有一个在执行,切每次要输出此次是第几次在执行该任务.

job文件

import org.quartz.*;
import org.springframework.scheduling.quartz.QuartzJobBean; /**
*
* @author ***
* email:***@163.com
* @create 2018-04-20 10:33 AM
**/ @PersistJobDataAfterExecution // 数据保持
@DisallowConcurrentExecution // 多个任务不会同时执行
public class HelloQuartzJob extends QuartzJobBean { protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
// 获取运行参数
JobDataMap map = context.getJobDetail().getJobDataMap(); System.out.println("Hello Quartz 第 " + map.getInt("times") + " 执行 !!!");
map.put("times", map.getIntValue("times") + 1);
}
}

配置文件

  • job
    <bean id="helloQuartzJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="com.**.xtfx.quarz.**.job.HelloQuartzJob"/>
<!--任务名-->
<property name="name" value="helloQuartzJob"/>
<!--任务描述-->
<property name="description" value="任务描述"/>
<!--任务所属组-->
<property name="group" value="group"/>
<!--任务在没有触发器绑定时不消亡-->
<property name="durability" value="true"/> <!--输入属性值获取其他bean-->
<property name="jobDataAsMap">
<map>
<entry key="times" value="0"/>
</map>
</property>
</bean>
  • trigger
    <bean id="helloQuartzJobCronTrigger"
class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<!--任务bean-->
<property name="jobDetail" ref="helloQuartzJob"/>
<!--任务触发条件-->
<property name="cronExpression" value="0 0/1 10-18 * * ?"/>
</bean>
  • scheduler
    <!--任务总调度器-->
<bean id="stdScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="transactionManager" ref="transactionManagerBusiness"/>
<property name="triggers">
<list>
<ref bean="helloQuartzJobCronTrigger"/>
</list>
</property> <property name="jobDetails">
<list>
<ref bean="helloQuartzJob"/>
</list>
</property>
</bean>

输出结果

开始触发quartz任务!!!!
Hello Quartz 第 0 执行 !!!
Hello Quartz 第 1 执行 !!!
Hello Quartz 第 2 执行 !!!