一、实现定时任务
1. 创建项目
这里我们只需要引入web依赖即可。
修改配置文件,避免和本地其他项目端口冲突
2. 增加注解
启动类增加注解@EnableScheduling
package com.example.scheduledemo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.scheduling.annotation.EnableScheduling; @SpringBootApplication @EnableScheduling //添加注解 public class ScheduleDemoApplication { public static void main(String[] args) { SpringApplication.run(ScheduleDemoApplication.class, args); } }
还可以新增一个配置文件,把注解放在配置类上,同时也这个类也变成了配置类,推荐这么写,这会让启动类更简洁,找配置也更好找。
package com.example.scheduledemo.config; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableScheduling; @Configuration @EnableScheduling public class ScheduledConfig { }
3. 创建定时任务
我们创建一个包 job 里面存放一些定时任务类。
package com.example.scheduledemo.job; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import java.text.SimpleDateFormat; import java.util.Date; @Component public class TestJob1 { @Scheduled(cron = "0/5 * * * * *") //每五秒执行一次 public void test1(){ SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.out.print("定时任务在"+ simpleDateFormat.format(new Date()) +" 执行\r\n"); } }
执行结果如下
这样我们就实现了最简单的定时任务。
二、配置详解
我们可以通过IDE查看注解@Scheduled
的源码,根据源码我们可以看到其他参数
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by FernFlower decompiler) // package org.springframework.scheduling.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.util.concurrent.TimeUnit; @Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Repeatable(Schedules.class) public @interface Scheduled { String CRON_DISABLED = "-"; String cron() default ""; String zone() default ""; long fixedDelay() default -1L; String fixedDelayString() default ""; long fixedRate() default -1L; String fixedRateString() default ""; long initialDelay() default -1L; String initialDelayString() default ""; TimeUnit timeUnit() default TimeUnit.MILLISECONDS; }
- fixedDelay 上次任务结束后的延迟时间执行下次任务
- fixedRate 上次任务开始后的延迟时间执行下次任务
- initialDelay 第一次执行的延迟时间
- timeUnit 时间单位,默认为毫秒
这里注意的是,fixedDelay
、fixedRate
、cron
不能同时使用,initialDelay
不能和cron
同时使用。
三、定时任务cron表达式
这里不得不说下,源码的注释很完善,建议多读读源码,下面摘录的是源码注释的翻译。
将给定的 crontab 表达式字符串解析为 CronExpression。该字符串有六个以空格分隔的时间和日期字段:
┌────────────── 秒 (0-59)
│ ┌───────────── 分钟 (0 - 59)
│ │ ┌───────────── 小时 (0 - 23)
│ │ │ ┌───────────── 一个月中的某天 (1 - 31)
│ │ │ │ ┌───────────── 月(1-12)(或JAN-DEC)
│ │ │ │ │ ┌───────────── 星期几(0 - 7)
│ │ │ │ │ │ (0 或 7 为星期日,或 MON-SUN)
│ │ │ │ │ │
以下规则适用:
一个字段可以是一个星号 (*),它始终代表“first-last”。对于“月中的日”或“周中的日”字段,可以使用问号 (?) 代替星号。
数字范围由用连字符 (-) 分隔的两个数字表示。指定的范围包括在内。
在范围(或 *)之后,使用 /n 指定数字值在范围内的间隔。
英文名称也可用于“月”和“星期几”字段。使用特定日期或月份的前三个字母(不区分大小写)。
“day of month”和“day of week”字段可以包含一个 L 字符,代表“last”,并且在每个字段中具有不同的含义:
在“日期”字段中,L 代表“月份的最后一天”。如果后跟负偏移量(即 L-n),则表示“本月倒数第 n 天”。如果后跟 W(即 LW),则表示“本月的最后一个工作日”。
在“星期几”字段中,L 代表“星期的最后一天”。如果前缀为数字或三个字母的名称(即 dL 或 DDDL),则表示“当月 d 周(或 DDD)的最后一天”。
“day of month”字段可以是 nW,它表示“离该月 n 中最近的工作日”。如果 n 落在星期六,这将产生它之前的星期五。如果 n 落在星期日,这将产生之后的星期一,如果 n 为 1 并且落在星期六,也会发生这种情况(即 1W 代表“本月的第一个工作日”)。
“星期几”字段可以是d#n(或DDD#n),代表“该月第d周(或DDD)的第n天”。
示例表达式:
“0 0 * * * " = 每天每个小时的开头。
"/10 * * * * *” = 每十秒。“0 0 8-10 * * *” = 每天的 8 点、9 点和 10 点。
“0 0 6,19 * * *” = 每天早上 6:00 和晚上 7:00。
“0 0/30 8-10 * * *” = 每天 8:00、8:30、9:00、9:30、10:00 和 10:30。
“0 0 9-17 * * MON-FRI” = 工作日朝九晚五
“0 0 0 25 12 ?” = 每个圣诞节的午夜
“0 0 0 L * *” = 每月最后一天的午夜
“0 0 0 L-3 * *” = 倒数第三天午夜
“0 0 0 1W * *” = 每月第一个工作日的午夜
“0 0 0 LW * *” = 每月最后一个工作日的午夜
“0 0 0 * * 5L” = 每月最后一个星期五午夜
“0 0 0 * * THUL” = 每月最后一个星期四的午夜
“0 0 0 ? * 5#2” = 每月第二个星期五午夜
“0 0 0 ? * MON#1” = 每月第一个星期一的午夜
还支持以下宏:
“@yearly”(或“@annually”)每年运行一次,即“0 0 0 1 1 *”,
“@monthly”每月运行一次,即“0 0 0 1 * *”,
“@weekly”每周运行一次,即“0 0 0 * * 0”,
“@daily”(或“@midnight”)每天运行一次,即“0 0 0 * * *”,
“@hourly”每小时运行一次,即“0 0 * * * *”。