SpringBoot——Scheduled定时任务

Posted tang_seven

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringBoot——Scheduled定时任务相关的知识,希望对你有一定的参考价值。

目录

1.静态定时任务

2.动态定时任务


在一些业务场景中,我们需要定义一些任务在我们指定的时间或是每隔一个时间段就自动执行,来作为任务的前提,保证业务的执行。比如:我们需要一个定时任务,每天早上6点执行,对数据库中的某个日期字段进行修改,修改为当天时间。

1.静态定时任务

springboot中为我们提供了自带的定时任务。

首先,我们需要让项目能使用定时任务:

@EnableScheduling
@SpringBootApplication
public class CourtSeckillMain 
    public static void main(String[] args) 
        SpringApplication.run(CourtSeckillMain.class,args);
    

然后,我们需要在业务类中编写代码:

    @Override
    @Scheduled(cron = "0 0 6 * * ?")
    //秒 分 时 日 月 周 年(可选);*表所有可能的值,-指定范围值,/表示步长
    public void doScheduleTask()
        log.info("执行定时任务");
        //这里是你的业务逻辑
    

 上述代码称为静态定时任务,主要依靠 @Scheduled 标签实现,根据其参数cron表达式每隔时间间隔自动执行任务。

cron参数:cron表达式中可填6个值,分别对应 秒 分 时 日 月 周 年。* 表所有可能的值,- 指定范围值,/ 表示步长,?表示不指定值即该值不影响。

0 0 6 * * ?    表示每天6点执行任务
0/5 * * * * ?   表示每5秒执行一次任务
0 * 6 * * ?    表示每天的6点-7点之间的每一分钟都执行一次
0 * 6-8 * * ?  表示每天的6点-9点之间的每一分钟都执行一次
5 10 6 * * ?   表示每天的6:10:05执行一次
0 10,44 14 ? 3 WED  表示三月的每周三的14:10和14:44触发

静态定时任务通过 @Scheduled 标签指定好执行时间,从而执行定时任务,使用较为方便但不太灵活,指定好执行时间后则无法更改。

2.动态定时任务

如果我们需要动态修改定时任务的cron值,我们可以通过继承 SchedulingConfigurer 类来实现:

@Data
@Slf4j
@Component
@ConfigurationProperties(prefix = "scheduled.task")
public class ScheduleTask implements SchedulingConfigurer 

    private String cron;

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) 
        taskRegistrar.addTriggerTask(() -> 
            // 业务代码
            log.info("定时任务,currentTime:", LocalDateTime.now());

        , triggerContext -> 
            // 使用CronTrigger触发器,可动态修改cron表达式来操作循环规则
            CronTrigger cronTrigger = new CronTrigger(cron);
            return cronTrigger.nextExecutionTime(triggerContext);
        );
    

application.yml中存放初始的cron值:

scheduled:
  task:
    cron: "0/5 * * * * ?"    #每5秒执行一次

在controller中编写接口,动态修改cron值:

@RestController
@RequiredArgsConstructor
public class seckillController 

    private final ScheduleTask scheduleTask;

    @GetMapping("/test")
    public String test(@RequestParam("cron") String cron)
        scheduleTask.setCron(cron);
        log.info("修改cron为:",scheduleTask.getCron());
        return scheduleTask.getCron();
    

然后我们运行程序,并通过接口修改cron值:

可以看到,修改之前,每5秒执行一次定时任务;我们将cron修改为每天10点内的每分钟执行后,变成了每分钟才执行一次。

由此实现了自定义的定时任务,并由接口动态修改定时任务的执行时间。

需要注意的是:每次修改完定时任务执行时间之后,需要执行完上一次的定时任务才会让新定义的执行时间生效。

我们由 ScheduleTask.configureTasks() 方法中的上述代码 可以看到,指定下一次任务的执行间隔是由 cronTrigger.nextExecutionTime(triggerContext) 实现的,而该方法会在一次定时任务执行完结后才调用。

ScheduleTask.configureTasks() 方法中指定定时任务执行间隔)

所以,我们在上述运行结果中看到,在10:28:30秒执行完一次定时任务,然后在10:28:32我们对cron值进行了修改,定时任务任然按照 0/5 * * * * ? 这一cron值执行了一次,然后才配置了新的cron值。

换言之,如果我们定义了任务每天6点执行,然后某一天将其修改为12点执行,springboot会在第二天的6点执行完后再将cron值修改,然后12点再执行一次。

所以会一定程度上存在重复执行的问题,如果业务需要规避,请谨慎考虑。

SpringBoot学习18:springboot使用Scheduled 定时任务器

Scheduled 定时任务器:是 Spring3.0 以后自带的一个定时任务器。

1、在pom.xml文件中添加Scheduled依赖

        <!-- 添加spring定时任务 Scheduled 坐标 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
        </dependency>    

2、编写定时任务类

package com.bjsxt.task;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

/**
 * Created by Administrator on 2019/2/17.
 * 定时任务
 */
@Component
public class ScheduledDemo {

    /**
     * 定时任务方法
     * @Scheduled:设置定时任务
     * cron 属性:cron 表达式。定时任务触发是时间的一个字符串表达形式
     * 每两秒执行一次
     */
    @Scheduled(cron = "0/2 * * * * ?")
    public void demo(){
        System.out.print("哈哈");
    }
}

3、在启动类中开启定时任务

package com.bjsxt;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

/**
 * Created by Administrator on 2019/2/17.
 */
@SpringBootApplication
@EnableScheduling  //springboot默认是关闭定时任务的,需要在启动器里面打开
public class App {

    public static void main(String[] args){
        SpringApplication.run(App.class,args);
    }
}

4、cron 表达式讲解

Cron 表达式是一个字符串,分为 6 或 7 个域,每一个域代表一个含义
Cron 有如下两种语法格式:
(1) Seconds Minutes Hours Day Month Week Year
(2)Seconds Minutes Hours Day Month Week

一、结构
  corn 从左到右(用空格隔开):秒 分 小时 月份中的日期 月份 星期中的日期 年份
二、各字段的含义

Cron 表达式的时间字段除允许设置数值外,还可使用一些特殊的字符,提供列表、范围、通配符等功
能,细说如下:
●星号(*):可用在所有字段中,表示对应时间域的每一个时刻,例如,*在分钟字段时,表示“每分钟”;
●问号(?):该字符只在日期和星期字段中使用,它通常指定为“无意义的值”,相当于占位符;
●减号(-):表达一个范围,如在小时字段中使用“10-12”,则表示从 10 到 12 点,即 10,11,12;
●逗号(,):表达一个列表值,如在星期字段中使用“MON,WED,FRI”,则表示星期一,星期三和星期
五;
●斜杠(/):x/y 表达一个等步长序列,x 为起始值,y 为增量步长值。如在分钟字段中使用 0/15,则
表示为 0,15,30 和 45 秒,而 5/15 在分钟字段中表示 5,20,35,50,你也可以使用*/y,它等同于 0/y;
●L:该字符只在日期和星期字段中使用,代表“Last”的意思,但它在两个字段中意思不同。L 在日期
字段中,表示这个月份的最后一天,如一月的 31 号,非闰年二月的 28 号;如果 L 用在星期中,则表示星
期六,等同于 7。但是,如果 L 出现在星期字段里,而且在前面有一个数值 X,则表示“这个月的最后 X 天”,
例如,6L 表示该月的最后星期五;
●W:该字符只能出现在日期字段里,是对前导日期的修饰,表示离该日期最近的工作日。例如 15W
表示离该月 15 号最近的工作日,如果该月 15 号是星期六,则匹配 14 号星期五;如果 15 日是星期日,
则匹配 16 号星期一;如果 15 号是星期二,那结果就是 15 号星期二。但必须注意关联的匹配日期不能够
跨月,如你指定 1W,如果 1 号是星期六,结果匹配的是 3 号星期一,而非上个月最后的那天。W 字符串
只能指定单一日期,而不能指定日期范围;
●LW 组合:在日期字段可以组合使用 LW,它的意思是当月的最后一个工作日;
●井号(#):该字符只能在星期字段中使用,表示当月某个工作日。如 6#3 表示当月的第三个星期五(6
表示星期五,#3 表示当前的第三个),而 4#5 表示当月的第五个星期三,假设当月没有第五个星期三,
忽略不触发;
● C:该字符只在日期和星期字段中使用,代表“Calendar”的意思。它的意思是计划所关联的日期,
如果日期没有被关联,则相当于日历中所有日期。例如 5C 在日期字段中就相当于日历 5 日以后的第一天。
1C 在星期字段中相当于星期日后的第一天。
Cron 表达式对特殊字符的大小写不敏感,对代表星期的缩写英文大小写也不敏感。
例子:
@Scheduled(cron = "0 0 1 1 1 ?")//每年一月的一号的 1:00:00 执行一次
@Scheduled(cron = "0 0 1 1 1,6 ?") //一月和六月的一号的 1:00:00 执行一次
@Scheduled(cron = "0 0 1 1 1,4,7,10 ?") //每个季度的第一个月的一号的 1:00:00 执行一次
@Scheduled(cron = "0 0 1 1 * ?")//每月一号 1:00:00 执行一次
@Scheduled(cron="0 0 1 * * *") //每天凌晨 1 点执行一次

以上是关于SpringBoot——Scheduled定时任务的主要内容,如果未能解决你的问题,请参考以下文章

玩转SpringBoot之定时任务@Scheduled线程池配置-

springboot 基于@Scheduled注解 实现定时任务

springboot 定时任务@Scheduled注解

SpringBoot执行定时任务@Scheduled

SpringBoot之scheduled定时器

springboot跑定时任务