定时任务_SpringBoot之定时任务

本文详细介绍了如何在SpringBoot中创建定时任务,包括基于注解的单线程和多线程实现,以及如何通过实现SchedulingConfigurer接口动态从数据库读取cron表达式来执行定时任务。示例代码清晰地展示了各种方法的使用,并提供了cron表达式的解释和使用示例。
摘要由CSDN通过智能技术生成
在日常的项目开发中,往往会涉及到一些需要做到定时执行的代码,例如 整点推送 ,自动将超过24小时的未付款的单改为取消状态,自动将超过14天客户未签收的订单改为已签收状态等等,那么为了在Spring Boot中实现此类需求,我们要怎么做呢?

    使用SpringBoot创建定时任务非常简单,目前主要有以下三种创建方式:

一、基于注解(@Scheduled)

二、基于注解设定多线程定时任务

三、基于接口(SchedulingConfigurer)

实际使用中我们往往想从数据库中读取指定时间来动态执行定时任务,这时候基于接口的定时任务就派上用场了。 一.静态 基于注解 基于注解@Scheduled默认为单线程,开启多个任务时,任务的执行时机会受上一个任务执行时间的影响。 1.创建定时器
@Component@EnableSchedulingpublic class Demo {@Scheduled(cron = "0/5 * * * * ?")//或直接指定时间间隔,例如:5秒//@Scheduled(fixedRate=5000)private void configureTasks() {        System.out.println("执行静态定时任务时间: " + LocalDateTime.now().toLocalTime());    }}
2.启动测试

9f2497eb0ba1a5555c7974e5bb8ebcb8.png

3.@Scheduled注解中的参数     3.1  cron

        学过linux对它应该比较熟悉,没学过那就先看看吧。Cron表达式是一个字符串,字符串以5或6个空格隔开,分为6或7个域,每一个域代表一个含义,Cron有如下两种语法格式:

(1) Seconds Minutes Hours DayofMonth Month DayofWeek Year

(2) Seconds Minutes Hours DayofMonth Month DayofWeek

eac6b3512ee84dea5ce94c1f5937dd82.png

在线cron表达式生成:http://qqe2.com/cron/index

但还可以出现如下特殊字符,它们的含义是:

(1)*:表示匹配该域的任意值。假如在Minutes域使用*, 即表示每分钟都会触发事件。

(2)?:只能用在DayofMonth和DayofWeek两个域。它也匹配域的任意值,但是有种情况例外。如写法:13 13 15 20 * ?, 其中最后一位只能用?,而不能使用*,如果使用*表示不管星期几都会触发。

(3)-:表示范围。例如在Minutes域使用5-20,表示从5分到20分钟每分钟触发一次 。

(4)/:表示起始时间开始触发,然后每隔固定时间触发一次。例如在Minutes域使用5/20,则意味着5分钟触发一次,而25,45等分别触发一次.

(5),:表示列出枚举值。例如:在Minutes域使用5,20,则意味着在5和20分每分钟触发一次。

(6)L:表示最后,只能出现在DayofWeek和DayofMonth域。如果在DayofWeek域使用5L,意味着在最后的一个星期四触发。

(7)W:表示有效工作日(周一到周五),只能出现在DayofMonth域,系统将在离指定日期的最近的有效工作日触发事件。例如:在 DayofMonth使用5W,如果5日是星期六,则将在最近的工作日:星期五,即4日触发。如果5日是星期天,则在6日(周一)触发;如果5日在星期一到星期五中的一天,则就在5日触发。另外一点,W的最近寻找不会跨过月份 。

(8)LW:这两个字符可以连用,表示在某个月最后一个工作日,即最后一个星期五。

(9)#:用于确定每个月第几个星期几,只能出现在DayofMonth域。例如在4#2,表示某月的第二个星期三。

    3.2  其他参数

(1)initialDelay:启动后多久开始执行,单位时毫秒

(2)fixedRate:下次执行时间,任务开始运行的时候就计时。

(3)fixedDelay:下次执行时间,fixedDelay等任务进行完了才开始计时

第一种形式使用的比较多,一般表示循环使用,但是也要看自己实现什么业务。定时任务实现起来非常的简单。

二. 多线程定时任务

     为了使第一个定时任务和第二个定时任务互不影响,开启多线程,同时第一个任务的执行时间也不受其本身执行时间的限制。

@Component@EnableScheduling@EnableAsyncpublic class Demo {    @Async    @Scheduled(fixedDelay = 2000)  //间隔2秒    public void first() {        System.out.println("第一个定时任务开始 : " +                LocalDateTime.now().toLocalTime() + "\r\n线程 : " +                Thread.currentThread().getName());    }    @Async    @Scheduled(fixedDelay = 5000)    public void second() {        System.out.println("第二个定时任务开始 : " +                LocalDateTime.now().toLocalTime() + "\r\n线程 : " +                Thread.currentThread().getName());    }}
    执行结果

ef5987acad7a461747bd4d92cf6e0c6e.png三.动态  基于接口

    从数据库中读取指定时间来动态执行定时任务

pom文件

  <dependencies>        <dependency>            <groupId>org.springframework.bootgroupId>            <artifactId>spring-boot-starter-webartifactId>        dependency>        <dependency>            <groupId>mysqlgroupId>            <artifactId>mysql-connector-javaartifactId>        dependency>        <dependency>            <groupId>org.mybatis.spring.bootgroupId>            <artifactId>mybatis-spring-boot-starterartifactId>            <version>1.3.2version>        dependency>        <dependency>            <groupId>org.mybatisgroupId>            <artifactId>mybatisartifactId>            <version>3.5.4version>        dependency>    dependencies>

yml配置

spring:  datasource:    url: jdbc:mysql://127.0.0.1:3306/shop?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&serverTimezone=Asia/Shanghai    username: root    password: root888

创建数据库

CREATE TABLE `cron` (  `cron_id` varchar(30) NOT NULL,  `cron` varchar(30) NOT NULL,  PRIMARY KEY (`cron_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;INSERT INTO `cron` VALUES ('1', '0/5 * * * * ?');

创建mapper接口

@Mapperpublic interface CronMapper {    @Select("select cron from cron limit 1")    public String getCron();}

实现类

@Configuration@EnableSchedulingpublic class Demo implements SchedulingConfigurer {    @Autowired      //注入mapper    private CronMapper cronMapper;    /**     * 执行定时任务.     */    @Override    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {        taskRegistrar.addTriggerTask(                //1.添加任务内容(Runnable)                () -> System.out.println("执行动态定时任务: " + LocalDateTime.now().toLocalTime()),                //2.设置执行周期(Trigger)                triggerContext -> {                    //2.1 从数据库获取执行周期                    String cron = cronMapper.getCron();                    //2.2 合法性校验.                    if (StringUtils.isEmpty(cron)) {                        // Omitted Code ..                    }                    //2.3 返回执行周期(Date)                    return new CronTrigger(cron).nextExecutionTime(triggerContext);                }        );    }}

执行结果

88600841b74616b1997115e23feca2d3.png

        这种方式我们就可以写一个controller接口,前端界面访问controller接口,通过修改cron表达式来动态的修改定时任务,还可以增加status字段,来动态的控制该任务的关闭开启状态。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值