1.  Spring Task简介

在实际开发中, 根据业务需求, 我们经常需要处理一些定时任务, 例如:每天凌晨备份一下数据, 每月清空一次日志, 页面广告一周之后过期, 每三个月清空一下cookie等等。目前最常见的实现定时任务的方式有三种:

1. Java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务。使用这种方式可以让程序按照某一个频度或间隔运行,但不能在指定时间运行, 一般用的较少。

2. 使用Quartz,这是一个功能比较强大的的开源工具,可以让程序在指定时间运行,也可以按照某一个频度或间隔运行,配置起来稍显复杂。

3. Spring 3.0以后自带task调度工具,可以将它看成一个轻量级的Quartz,而且使用起来比Quartz更加简单方便, 我们这里重点讲解这种方式。

2 开发环境准备

2.1 创建项目并导入jar包

创建一个Java Web项目SpringTaskTest1, 然后导入jar包, 如果你是Maven项目, 就在pom文件中引入spring-context和spring-web的坐标即可, 如下所示:



<artifactId>Task</artifactId>

<packaging>war</packaging>

<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.2.8.RELEASE</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
<showWarnings>true</showWarnings>
</configuration>
</plugin>
<!-- 运行tomcat7方法:tomcat7:run -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<!-- 指定端口 -->
<port>8080</port>
<!-- 请求路径 -->
<path>/</path>
</configuration>
</plugin>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.4.12.v20180830</version>
<!-- <configuration> <webApp> jetty默认contextPath为/,为了和tomcat保持一致,采用如下配置
<contextPath>/${project.artifactId}</contextPath> </webApp> </configuration> -->
</plugin>

</plugins>
</build>


2.2 配置文件

要使用spring进行开发需要在web.xml中进行spring监听器的配置, 如下所示:



<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">

<!-- spring配置文件位置 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!-- spring核心监听器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

</web-app>


3 如何使用Spring Task

3.1 纯XML配置方式

3.1.1 简单定时任务

定时任务中的业务功能我们按照常规的处理方式放到业务层实现, 所以首先编写一个业务层接口TaskService, 如下图所示:



package com.topcheer.task;

public interface TaskService {
void firstTask(); //第一个定时任务
void secondTask(); //第二个定时任务
}


接下来编写该接口的实现类TaskServiceImpl, 在该类中实现两个定时任务, 业务功能上做了简化处理, 只是往控制台输出一句话, 如下图所示:



package com.topcheer.task;

import java.util.Date;


public class TaskServiceImpl implements TaskService{

@Override
public void firstTask() {
System.out.println(new Date() +": 这是第1个定时任务");
}

@Override
public void secondTask() {
System.out.println(new Date() +": 这是第2个定时任务");
}

}


 XML配置



<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:task="http://www.springframework.org/schema/task"
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="taskService" class="com.topcheer.task.TaskServiceImpl">
</bean>

<!-- 配置定时规则 -->
<task:scheduled-tasks>
<!-- 可以配置多个定时任务 -->
<!-- <task:scheduled ref="taskService" method="firstTask"
initial-delay="1000" fixed-delay="1000" />
<task:scheduled ref="taskService" method="secondTask"
initial-delay="2000" fixed-delay="3000" /> -->

<task:scheduled ref="taskService" method="firstTask"
cron="*/5 * * * * ?"/>

<task:scheduled ref="taskService" method="secondTask"
cron="0 45 14 * * ?"/>

</task:scheduled-tasks>

</beans>


日志:



[INFO] Started o.e.j.m.p.JettyWebAppContext@7a5b769b{/,file:///E:/IdeaSpace/demo/Task/src/main/webapp/,AVAILABLE}{file:///E:/IdeaSpace/demo/Task/src/main/webapp/}
[INFO] Started ServerConnector@285c6918{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}
[INFO] Started @10338ms
[INFO] Started Jetty Server
Tue Mar 17 18:16:30 CST 2020: 这是第1个定时任务
Tue Mar 17 18:16:35 CST 2020: 这是第1个定时任务
Tue Mar 17 18:16:40 CST 2020: 这是第1个定时任务
Tue Mar 17 18:16:45 CST 2020: 这是第1个定时任务


3.2 全注解方式

除了采用XML配置的方式可以实现定时任务之外, spring也支持全注解的方式来实现定时任务。 为了跟上面的例子区分开, 接下来我们单独再创建一个项目SpringTaskTest2来演示。 创建项目并导入Jar包, 以及配置web.xml的过程跟上面的例子一模一样, 这里不再演示。

我们可以直接在业务层的实现类中使用@Service注解, 该注解用到类上表示该类的对象由spring负责创建和管理, 等价于applicationContext.xml中的<bean>配置, @Scheduled注解用到方法上用于设置定时规则, 等价于applicationContext.xml中的<task:scheduled>配置, 具体代码如下图所示:



@Service
public class TaskServiceImpl implements TaskService{

@Override
@Scheduled(cron ="*/5 * * * * ?")
public void firstTask() {
System.out.println(new Date() +": 这是第1个定时任务");
}

@Override
@Scheduled(cron ="*/6 * * * * ?")
public void secondTask() {
System.out.println(new Date() +": 这是第2个定时任务");
}

}


xml配置



<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:task="http://www.springframework.org/schema/task"
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">

<context:component-scan base-package="com.topcheer.task"></context:component-scan>

<task:annotation-driven></task:annotation-driven>

</beans>


日志:



[INFO] Started ServerConnector@65afeb6d{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}
[INFO] Started @14663ms
[INFO] Started Jetty Server
Tue Mar 17 18:31:20 CST 2020: 这是第1个定时任务
Tue Mar 17 18:31:24 CST 2020: 这是第2个定时任务
Tue Mar 17 18:31:25 CST 2020: 这是第1个定时任务
Tue Mar 17 18:31:30 CST 2020: 这是第2个定时任务
Tue Mar 17 18:31:30 CST 2020: 这是第1个定时任务
Tue Mar 17 18:31:35 CST 2020: 这是第1个定时任务
Tue Mar 17 18:31:36 CST 2020: 这是第2个定时任务
Tue Mar 17 18:31:40 CST 2020: 这是第1个定时任务
Tue Mar 17 18:31:42 CST 2020: 这是第2个定时任务