Spring3.0以后自主开发的定时任务工具,spring task,可以将它比作一个轻量级的Quartz,而且使用起来很简单,除spring相关的包外不需要额外的包。
Spring初始化bean的两种方式:
- xml配置
- 注解
在讲解两种配置方式前首先要配置web.xml和依赖spring相关包
1、web.xml的配置(一定要配置监听器)
<?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_3_0.xsd"
version="3.0">
<display-name>Archetype Created Web Application</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-root.xml</param-value>
</context-param>
<!-- spring监听器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
2、pom.xml,两个依赖包就够了
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.3.14.RELEASE</version>
</dependency>
3、配置方式
3.1、注解方式
使用@Scheduled注解,配置在controller方法上,我们先看看Scheduled注解的源码
@Target({java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Scheduled {
public abstract String cron();
public abstract long fixedDelay();
public abstract long fixedRate();
}
编写实例Demo
package com.example.schedule;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Author:
* DateTime:2018-02-11 9:43
*/
@Component
public class MyScheduled {
// execute per 5 second
@Scheduled(cron="0/5 * * * * ? ")
public void taskJob() {
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd a hh:mm:ss");
String dateStr = sdf.format(date);
System.out.println("test Scheduled annotation style ... " + dateStr);
}
}
配置spring-root.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:task="http://www.springframework.org/schema/task"
xmlns:context="http://www.springframework.org/schema/context"
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-3.1.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-4.1.xsd">
<context:component-scan base-package="com.example.schedule"/>
<task:annotation-driven />
</beans>
使用cron表达式配置触发时间,灵活多变且丰富 ;除了使用cron表达式,还可以使用fixedRate = 1000 * 5,同样表示5秒;还有fixedDelay指定任务执行的间隔,单位都是毫秒;
// execute per 5 second
@Scheduled(fixedRate = 1000 * 5)
public void taskJob() {
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd a hh:mm:ss");
String dateStr = sdf.format(date);
System.out.println("test Scheduled annotation style ... " + dateStr);
}
3.2、xml配置方式
spring-root.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:task="http://www.springframework.org/schema/task"
xmlns:context="http://www.springframework.org/schema/context"
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-3.1.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-4.1.xsd">
<context:component-scan base-package="com.example.schedule"/>
<!--task:scheduler会注册一个ThreadPoolTaskScheduler定时器,它只有一个属性线程池大小。默认是1,我们需要根据任务的数量指定一个合适的大小。-->
<task:scheduler id="testTask" pool-size="3" />
<!-- task:executor会注册一个ThreadPoolTaskExecutor执行器,不配置此执行器任务也可以执行 -->
<task:executor id="threadPoolTaskExecutor" pool-size="10" queue-capacity="10"/>
<task:scheduled-tasks scheduler="testTask">
<task:scheduled ref="myScheduled" method="taskJob" cron="0/5 * * * * ?" />
</task:scheduled-tasks>
</beans>
MyScheduled.java
package com.example.schedule;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Author:
* DateTime:2018-02-11 9:43
*/
@Component
public class MyScheduled {
// execute per 5 second
public void taskJob() {
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd a hh:mm:ss");
String dateStr = sdf.format(date);
System.out.println("test Scheduled annotation style ... " + dateStr);
}
}
4、cronExpression的配置说明:
字段 允许值 允许的特殊字符
秒 0-59 , - * /
分 0-59 , - * /
小时 0-23 , - * /
日期 1-31 , - * ? / L W C
月份 1-12 或者 JAN-DEC , - * /
星期 1-7 或者 SUN-SAT , - * ? / L C #
年(可选) 留空, 1970-2099 , - * /
cron表达式实例:
CRON表达式 含义
"0 0 12 * * ?" 每天中午十二点触发
"0 15 10 ? * *" 每天早上10:15触发
"0 15 10 * * ?" 每天早上10:15触发
"0 15 10 * * ? *" 每天早上10:15触发
"0 15 10 * * ? 2005" 2005年的每天早上10:15触发
"0 * 14 * * ?" 每天从下午2点开始到2点59分每分钟一次触发
"0 0/5 14 * * ?" 每天从下午2点开始到2:55分结束每5分钟一次触发
"0 0/5 14,18 * * ?" 每天的下午2点至2:55和6点至6点55分两个时间段内每5分钟一次触发
"0 0-5 14 * * ?" 每天14:00至14:05每分钟一次触发
"0 10,44 14 ? 3 WED" 三月的每周三的14:10和14:44触发
"0 15 10 ? * MON-FRI" 每个周一、周二、周三、周四、周五的10:15触发
5、异步定时任务
如果任务执行时间比较长的话,我们可以考虑使用异步的任务。在Spring中标记异步方法很简单,直接在方法上使用@Async注解。如果需要指定异步方法使用的执行器,可以向注解传递执行器的名称。异步方法可以返回空值。
以注解的方式模拟一个执行时间大于定时时间的定时任务
// execute per 5 second
@Scheduled(fixedRate = 1000 * 5)
public void taskJob() {
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd a hh:mm:ss");
String dateStr = sdf.format(date);
System.out.println("test Async Scheduled annotation style ... " + dateStr);
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
结果:定时任务每10秒执行一次
只需要在@Scheduled上加个@Async,定时任务即可每5秒执行一次