了解Spring Task之前,我们先了解一下什么是定时任务。
1. 定时任务
定时任务其实听见这个大家都知道什么意思,日常中大家经常的用到手机闹钟,这就是一个定时任务,还有一些其他的应用场景:
- 定时清除系统垃圾
- 定时发送节日祝贺信息
- 定时处理未支付订单
定时任务的应用场景是非常广泛的。定时任务就是系统在特定的时间执行一段代码。在java中,定时任务的主要实现方式有以下三种:
- Java自带的java.util.Timer类,这个类允许调度一个java.util.TimerTask任务。使用这种方式可以让程序按照某一个频度执行,但不能在指定时间运行。一般用的较少。
- SpringTask: spring自主研发的任务调度工具,并且存在于Spring体系中,可以按照约定的时间自动执行某个代码逻辑。不需要添加任何依赖。
- Quartz:这是一个功能比较强大的开源任务调度服务,几乎可以集成到任务Java应用程序中,可以让程序在指定时间执行,也可以按照某一个频度执行,配置起来稍显复杂。
2. cron表达式
这个表达式其实就是一个字符串,Spring Task就是依靠cron表达式定义任务触发的时间。熟悉Linux系统应该对此有所涉及,在linux设置定时任务时也是根据cron表达式来的。
构成规则:分为6或7个域,每一个域代表一个含义,由空格隔开。
每个域代表的含义分别为:秒、分钟、小时、日、月、周、年(可选)
即两种语法格式:
- Seconds Minutes Hours DayofMonth Month DayofWeek Year
- Seconds Minutes Hours DayofMonth Month DayofWeek
特数字符:
(1) * 表示匹配该域的任意值。假如在Minutes域使用 *,即表示每分钟都会触发事件。
(2) ? 表示未说明的值,即不关心它为何值;一般用在DayofMonth和DayofWeek两个域。因为DayofMonth和DayofWeek会相互影响。如想在每月的20日触发调度,不管20日到底是星期几,则只能使用如下写法:* * * 20 * ?,其中最后一位只能用?,而不能使用*,如果使用*表示不管星期几都会触发,实际上并不是这样。
(3) - 表示一个指定的范围;如在Minutes域使用5-20,表示从5分到20分钟每分钟触发一次
(4) , 表示列出枚举值。例如:在Minutes域使用5,20,则意味着在5和20分每分钟触发一次。
(5) / 表示起始时间开始触发,然后每隔固定时间触发一次,符号前表示开始时间,符号后表示每次递增的值。例如在Minutes域使用5/20,则意味着5分钟触发一次,而25,45等分别触发一次.
(6) L 表示最后,只能出现在DayofWeek和DayofMonth域。如果在DayofWeek域使用5L,意味着在最后的一个星期四触发。
(7) W 表示有效工作日(周一到周五),只能出现在DayofMonth域,系统将在离指定日期的最近的有效工作日触发事件。例如:在 DayofMonth使用5W,如果5日是星期六,则将在最近的工作日:星期五,即4日触发。如果5日是星期天,则在6日(周一)触发;如果5日在星期一到星期五中的一天,则就在5日触发。另外一点,W的最近寻找不会跨过月份 。
(8) LW 这两个字符可以连用,表示在某个月最后一个工作日,即最后一个星期五。
(9) # 用于确定每个月第几个星期几,#前面代表星期几,#后面代表一个月的第几周,只能出现在DayofMonth域。例如在4#2,表示某月的第二个星期三。(这里周天是第一周的开始,即周天是1)
cron表达式案例:
| */5 * * * * ? | 每隔5秒执行一次 |
|---|---|
| 0 */1 * * * ? | 每隔1分钟执行一次 |
| 0 0 5-15 * * ? | 每天5-15点整点触发 |
| 0 0/3 * * * ? | 每三分钟触发一次 |
| 0 0-5 14 * * ? | 在每天下午2点到下午2:05期间的每1分钟触发 |
| 0 0/5 14 * * ? | 在每天下午2点到下午2:55期间的每5分钟触发 |
| 0 0/5 14,18 * * ? | 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发 |
| 0 0/30 9-17 * * ? | 朝九晚五工作时间内每半小时 |
| 0 0 10,14,16 * * ? | 每天上午10点,下午2点,4点 |
若不熟悉该表达的使用也没有关系,这里推荐一个网站,可以根据相关设定生成cron表达式。
3. Spring Task案例
介绍完相关知识,还是需要案例来试试Spring Task的具体效果。这个是无需导入依赖的,Spring自身集成的
首先创建一个Spring Boot的项目,在启动类开启定时任务。 也就是在启动类上方添加@EnableScheduling注解即可开启定时任务,代码如下:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling // 开启定时任务
public class SpringTaskApplication {
public static void main(String[] args) {
SpringApplication.run(SpringTaskApplication.class, args);
}
}
然后编写一个定时任务类,一般来说,都习惯于新建一个task的包来管理定时任务。
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
// 必须将该类注入到Spring容器中
@Component
public class MyTask {
@Scheduled(cron = "* * * * * *") // 定时任务方法,每秒执行一次
public void task() {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
System.out.println(sdf.format(new Date()));
}
}
@Scheduled写在方法上方,指定该方法定时执行。常用参数如下:
- cron:cron表达式,定义方法执行的时间规则。
- fixedDelay:固定间隔时间,表示上一任务完成后间隔多少秒再执行。单位为毫秒
- fixedRate:表示每间隔多少秒执行一次任务,但是如果该事件内任务没有执行完,会在任务执行结束后,立即执行任务,然而不会任务没有结束前,就开始下次一任务。单位是毫秒。
- initialDelay: 固定等待时间,启动时间开始,项目启动后不马上执行定时器,根据initialDelay的值延时执行
后面三个参数大家可以自行尝试。