勿以恶小而为之,勿以善小而不为--------------------------刘备

劝诸君,多行善事积福报,莫作恶

上一章简单介绍了 Quartz的监听器(六),如果没有看过,​​请观看上一章​​

一. Spring 整合Quartz前的准备

Quartz 定时任务框架的基本知识都讲解了,现在把这个定时框架 Quartz 整合到 Spring 项目里面。

Spring 整合 Quartz定时,就是将 Quartz框架的那三个元素, JobDetail,Trigger 和Scheduler 通过 配置文件的方式配置出来。

需要在 spring的配置文件里面, 分别对 JobDetail,Trigger,Scheduler 进行配置。

通俗点说, 就是 把创建 JobDetail,Trigger,Scheduler 的代码 变成配置文件。

在整合之前,需要 通过 Maven 创建一个 Spring 的项目。(关于Spring 项目的创建,老蝴蝶前面讲解了好多,这儿就不详细讲解了。)

一.一 配置 pom.xml 文件 ,添加依赖

不要忘记 spring-context-support 和 spring-jdbc 这两个依赖。

<dependencies>
<!-- 添加webmvc的依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<!-- 第三方支持的jar包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<!-- spring 测试的包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<!--数据库的依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<!-- tomcat中的 servlet-api和 jsp-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- jstl 与 standard -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- 日志 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.22</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency>
<!-- jackson 依赖,用于处理json -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.2.3</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.11</version>
</dependency>

</dependencies>

</project>

一.二 配置 web.xml 文件

<!-- UTF-8 编码过滤器 -->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- spring mvc前端控制器 -->
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 防 XSS -->
<context-param>
<param-name>defaultHtmlEscape</param-name>
<param-value>true</param-value>
</context-param>

一.三 配置 springmvc的配置文件

配置 springmvc.xml 文件,放置在 src/main/resource 文件夹下。

<!-- bean组件扫描 -->    
<context:component-scan base-package="com.yjl.action.quartz" />

<mvc:annotation-driven>
<mvc:message-converters>
<bean
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>application/json;charset=UTF-8</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>

<!-- 静态资源 -->
<mvc:resources location="/static/" mapping="/static/**" />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/" />
<property name="suffix" value=".jsp" />
</bean>

一.四 运行服务器

运行服务器,是正常的, Spring 项目搭建成功。

二. 将 Quartz 框架整合到 Spring 项目里面

二.一 在 pom.xml 中添加 关于 quartz的依赖

<!-- quartz的 jar包 -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.3.2</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.2</version>
</dependency>

二.二 编写作业任务 MyJob.java

MyJob.java

package com.yjl.job;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

/**
*
* @author 两个蝴蝶飞
*
*Quartz框架方式 创建任务
*/
public class MyJob implements Job{
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
//要做的事,是打印当前的时间
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//格式化时间
String dateString=sdf.format(new Date());
System.out.println("普通Job 备份数据库的时间是:"+dateString);
}
}

二.三 简单触发器 SimpleTrigger 触发

二.三. 一 在resource 目录下 创建 quartz 的配置文件 spring-quartz2.xml

(用的是2,而不是1, 是因为老蝴蝶测试时先测试的Cron表达式,后面才添加的简单触发器形式。)

spring-quartz2.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
">

<!-- 定义 JobDetail, 所用的bean 为 JobDetailFactoryBean -->
<bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<!-- 任务名 -->
<property name="name" value="job1"></property>
<!-- 组名 -->
<property name="group" value="group1"></property>
<!-- 关联任务 -->
<property name="jobClass" value="com.yjl.job.MyJob"></property>
<!-- 必须是true, 如果是false的话,当这个jobDetail没有被Trigger关联时,会删除 -->
<property name="durability" value="true"></property>
<!-- 还有一个重要的 applicationContextJobDataKey 属性,这一章节先不讲解-->

</bean>

<!-- 配置一个简单的触发器 -->
<bean id="trigger1" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
<!-- 触发器名称 -->
<property name="name" value="name1"></property>
<!-- 组名称 -->
<property name="group" value="group1"></property>
<!-- 开启的延迟时间,如果为0 就是 startNow() -->
<property name="startDelay" value="0"></property>
<!-- 运行次数 -->
<property name="repeatCount" value="3"></property>
<!-- 运行间隔,毫秒为单位 -->
<property name="repeatInterval" value="3000"></property>
<!-- 关联哪一个 任务, 直接放置到触发器里面 -->
<property name="jobDetail" ref="jobDetail"></property>
</bean>

<!-- 配置 scheduler 调度器 -->
<bean id="scheduler1" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<!-- 是集合,可以配置多个 触发器。 触发器里面为jobDetail,在Scheduler里面就不配置了-->
<ref bean="trigger1"/>
</list>

</property>
</bean>
</beans>

二.三.二 把 quartz配置文件放置到 springmvc.xml 中引用

在springmvc.xml 中,引入 spring-quartz2.xml 文件

<!-- bean组件扫描 -->    
<context:component-scan base-package="com.yjl.action.quartz" />
<!-- 引入包含 quartz.xml -->
<import resource="classpath*:spring_quartz2.xml"/>

二.三.三 重启服务器,进行测试

Spring整合Quartz(七)_整合Quartz有代码

当服务器一启动时,就自动执行任务。 共执行四次(刚开始一次+设置的3次, 共4次)

二.三.四 测试类进行测试查看

创建一个测试类 JobTest2 进行测试

package com.yjl.test;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
//引入配置文件
@ContextConfiguration("classpath*:spring_quartz2.xml")
public class JobTest2 {
@Test
public void test2(){
System.out.println("SimpleTrigger 是否运行任务呢?");
//需要休眠10s后,再关闭。 不然启动测试后直接关闭,看不出效果。
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}

Spring整合Quartz(七)_普通java对象Quartz_02

正常运行4次,与服务器启动时效果一致。

(接下来均用 测试类进行测试,不用服务器启动测试)

二.四 Cron 触发器 CronTrigger 触发

关于 cron 触发器的强大之处和简单触发器的不足,前面已经比较过了,老蝴蝶这儿就不再写了。

依赖和 作业任务 MyJob.java 均不变。

二.四.一 配置 cron 触发器的配置文件 spring-quartz.xml

<!-- 定义 JobDetail, 所用的bean 为 JobDetailFactoryBean -->
<bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<!-- 任务名 -->
<property name="name" value="job1"></property>
<!-- 组名 -->
<property name="group" value="group1"></property>
<!-- 关联任务 -->
<property name="jobClass" value="com.yjl.job.MyJob"></property>
<!-- 必须是true, 如果是false的话,当这个jobDetail没有被Trigger关联时,会删除 -->
<property name="durability" value="true"></property>
<!-- 还有一个重要的 applicationContextJobDataKey 属性,这一章节先不讲解-->
</bean>
<!-- 定义 cron 触发器 -->
<bean id="trigger1" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<!-- 配置触发器的名称 -->
<property name="name" value="trigger1"></property>
<!-- 配置触发器的组名 -->
<property name="group" value="group1"></property>
<!-- 配置关联的 JobDetail -->
<property name="jobDetail" ref="jobDetail"></property>
<!-- 配置 cron 表达式 ,每2秒触发一次-->
<property name="cronExpression" value="0/2 * * * * ?"></property>
</bean>

<!-- 配置 scheduler 调度器 -->
<bean id="scheduler1" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="trigger1"/>
</list>

</property>
</bean>

二.四.二 测试类进行测试查看

创建一个测试类 JobTest 进行测试

package com.yjl.test;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
//引入配置文件
@ContextConfiguration("classpath*:spring_quartz.xml")
public class JobTest {
@Test
public void test(){
System.out.println("CronTrigger 是否运行任务呢?");
//需要休眠10s后,再关闭。 不然启动测试后直接关闭,看不出效果。
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}

运行程序,控制台打印输出

Spring整合Quartz(七)_QuartzJobBean_03

cron 表达式配置成功。

上面的任务调度 MyJob, 需要实现 Job 接口, 准确地来说,还是 Quartz 框架自己创建的, 能不能让 Spring 创建呢?

三. Spring 创建任务Bean 实现整合 Quartz 框架

Spring 可以通过两种方式,来创建 任务Bean

  1. 继承 QuartzJobBean 类,用JobDetailFactoryBean 进行生成
  2. 创建普通java 对象和任务方法,用 MethodInvokingJobDetailFactoryBean 进行生成

下面,分别对这两种方式进行演示。

三.一 继承 QuartzJobBean 类

三.一.一 创建任务

/**
*
* @author 两个蝴蝶飞
*
* 通过继承 QuartzJobBean 来创建作业任务Bean
*
*/
public class MyJob3 extends QuartzJobBean{
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
//要做的事,是打印当前的时间
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//格式化时间
String dateString=sdf.format(new Date());
System.out.println("QuartzJobBean 备份数据库的时间是:"+dateString);

//可以通过 context 对象来获取一些重要信息
}
}

其实 QuartzJobBean 内部 自己实现了 Job 接口, 然后 通过重写 executeInternal()方法来代替以前的 execute()方法。

Spring整合Quartz(七)_Spring整合Quartz_04

三.一.二 编写配置文件 spring-quartz3.xml

<!-- 定义 JobDetail, 所用的bean 为 JobDetailFactoryBean -->
<bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">

<!-- 任务名 -->
<property name="name" value="job1"></property>
<!-- 组名 -->
<property name="group" value="group1"></property>
<!-- 关联任务 -->
<property name="jobClass" value="com.yjl.job.MyJob3"></property>
<!-- 必须是true, 如果是false的话,当这个jobDetail没有被Trigger关联时,会删除 -->
<property name="durability" value="true"></property>
<!-- 还有一个重要的 applicationContextJobDataKey 属性,这一章节先不讲解-->
</bean>
<!-- 定义 cron 触发器 -->
<bean id="trigger1" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<!-- 配置触发器的名称 -->
<property name="name" value="trigger1"></property>
<!-- 配置触发器的组名 -->
<property name="group" value="group1"></property>
<!-- 配置关联的 JobDetail -->
<property name="jobDetail" ref="jobDetail"></property>
<!-- 配置 cron 表达式 ,每2秒触发一次-->
<property name="cronExpression" value="0/2 * * * * ?"></property>
</bean>

<!-- 配置 scheduler 调度器 -->
<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="trigger1"/>
</list>

</property>
</bean>

与 二.四.一 部分的配置文件内容一样。

三.一.三 测试类进行测试查看

编写 JobTest3 测试类

package com.yjl.test;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath*:spring_quartz3.xml")
public class JobTest3 {
@Test
public void test3(){
System.out.println("继承QuartzJobBean 是否运行任务呢?");
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}

运行,控制台打印输出:

Spring整合Quartz(七)_整合Quartz有代码_05

三.二 普通Java 对象和任务方法

三.二.一 创建任务

/**
*
* @author 两个蝴蝶飞
* 普通的Java 类,普通的方法
*/
public class MyJob4 {
public void myExecute(){
//要做的事,是打印当前的时间
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//格式化时间
String dateString=sdf.format(new Date());
System.out.println("MethodInvoking 备份数据库的时间是:"+dateString);

//如果要传递数据的话,需要自己在生成jobDetail时进行配置

}
}

三.二.二 配置文件 spring-quartz4.xml

用 MethodInvokingJobDetailFactoryBean 来创建相应的JobDetail.

用 targetObject 和 targetMethod 属性来指定 哪一个类的哪一个方法。

<!-- 定义 JobDetail, 所用的bean 为 MethodInvokingJobDetailFactoryBean -->
<bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">

<!-- 任务名 -->
<property name="name" value="job1"></property>
<!-- 组名 -->
<property name="group" value="group1"></property>
<!--是否同步-->
<property name="concurrent" value="true"></property>
<!-- 哪一个任务 -->
<property name="targetObject">
<bean class="com.yjl.job.MyJob4"></bean>
</property>
<!-- 哪一个方法 -->
<property name="targetMethod" value="myExecute"></property>

</bean>
<!-- 定义 cron 触发器 -->
<bean id="trigger1" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<!-- 配置触发器的名称 -->
<property name="name" value="trigger1"></property>
<!-- 配置触发器的组名 -->
<property name="group" value="group1"></property>
<!-- 配置关联的 JobDetail -->
<property name="jobDetail" ref="jobDetail"></property>
<!-- 配置 cron 表达式 ,每2秒触发一次-->
<property name="cronExpression" value="0/2 * * * * ?"></property>
</bean>

<!-- 配置 scheduler 调度器 -->
<bean id="scheduler1" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="trigger1"/>
</list>

</property>
</bean>

三.二.三 测试文件测试

编写 JobTest4.java 测试类

package com.yjl.test;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath*:spring_quartz4.xml")
public class JobTest4 {
@Test
public void test4(){
System.out.println("自定义类和方法是否运行任务呢?");
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}

Spring整合Quartz(七)_实现Job接口整合Quartz_06

注意,此时是先输出语句,再运行6次。

这就是 Spring 整合 Quartz框架的几种方式,老蝴蝶强烈建议使用第3种,继承 QuartzJobBean的方式。



本章节代码链接为:

链接:https://pan.baidu.com/s/1ykh3eZFlJNFjgvnVj61emw 
提取码:a56w



谢谢您的观看!!!