美文网首页springboot程序员Spring Boot 从入门到上瘾
SpringBoot 创建定时任务(配合数据库动态执行)

SpringBoot 创建定时任务(配合数据库动态执行)

作者: 一只袜子 | 来源:发表于2017-10-23 18:45 被阅读1321次

    序言:创建定时任务非常简单,主要有两种创建方式:一、基于注解(@Scheduled) 二、基于接口(SchedulingConfigurer). 前者相信大家都很熟悉,但是实际使用中我们往往想从数据库中读取指定时间来动态执行定时任务,这时候基于接口的定时任务就大派用场了。

    一、静态定时任务(基于注解)

    基于注解来创建定时任务非常简单,只需几行代码便可完成。

    @Scheduled 除了支持灵活的参数表达式cron之外,还支持简单的延时操作,例如 fixedDelay ,fixedRate 填写相应的毫秒数即可。

    @Configuration //1.主要用于标记配置类,兼备Component的效果。
    @EnableScheduling // 2.开启定时任务
    public class SimpleScheduleConfig {
        //3.添加定时任务
        @Scheduled(cron = "0/5 * * * * ?")
        private void configureTasks() {
            System.err.println("执行定时任务1: " + LocalDateTime.now());
        }
    }
    

    Cron表达式参数分别表示:
    秒(0~59) 例如0/5表示每5秒
    分(0~59)
    时(0~23)
    月的某天(0~31) 需计算
    月(0~11)
    周几( 可填1-7 或 SUN/MON/TUE/WED/THU/FRI/SAT)

    启动应用,可以看到控制台的信息如下:

    诚然,使用Scheduled 确实很方便,但缺点是当我们调整了执行周期的时候,需要重启应用才能生效,这多少有些不方便。为了达到实时生效的效果,可以使用接口来完成定时任务。

    二、动态定时任务(基于接口)

    为了演示效果,这里选用 Mysql数据库 和 Mybatis 来查询和调整定时任务的执行周期,然后观察定时任务的执行情况。

    1.引入依赖

        <!--依赖管理 -->
        <dependencies>
            <dependency><!--添加Web依赖 -->
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency><!--添加Mybatis依赖 -->
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>1.3.1</version>
            </dependency>
            <dependency><!--添加MySql依赖 -->
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <scope>runtime</scope>
            </dependency>
            <dependency><!--添加Test依赖 -->
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    

    2.添加数据库记录

    在Navicat 连接本地数据库,随便打开查询窗口,然后执行脚本内容,如下:

    DROP DATABASE IF EXISTS `socks`;
    CREATE DATABASE `socks`;
    USE `SOCKS`;
    DROP TABLE IF EXISTS `cron`;
    CREATE TABLE `cron`  (
      `cron_id` varchar(30),
      `cron` varchar(30) 
    );
    INSERT INTO `cron` VALUES ('1', '0/5 * * * * ?');
    

    然后在项目中的application.yml 添加数据源:

    #application.yml 配置如下:
    spring:
      datasource:
        url: jdbc:mysql://localhost:3306/socks?useSSL=false
        username: root
        password: root
    

    3.创建定时器

    数据库准备好数据之后,我们编写定时任务,注意这里添加的是TriggerTask,目的是循环读取我们在数据库设置好的执行周期,以及执行相关定时任务的内容。具体代码如下:

    @Configuration
    @EnableScheduling
    public class CompleteScheduleConfig implements SchedulingConfigurer {
    
        @Mapper
        public interface CronMapper {
            @Select("select cron from cron limit 1")
            String getCron();
        }
    
        @Autowired
        @SuppressWarnings("all")
        CronMapper cronMapper;
    
        /**
         * 执行定时任务.
         */
        @Override
        public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
            taskRegistrar.addTriggerTask(
                    //1.添加任务内容(Runnable)
                    () -> System.out.println("执行定时任务2: " + 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);
                    }
            );
        }
    
    }
    

    4. 动态修改执行周期

    启动应用后,查看控制台,打印时间是我们预期的每5秒一次:

    然后打开Navicat ,将执行周期修改为每1秒执行一次,如图:

    查看控制台,发现执行周期已经改变,并且不需要我们重启应用,十分方便。如图:

    源码下载:SpringBoot Schedule Task Sample

    专题阅读:《SpringBoot 布道系列》

    相关文章

      网友评论

      • 0cebb8489fdd:你好,按照你的方式做了配置及代码编写。在“动态修改执行周期”时的结果和你不一样呢。我修改了数据库的cron表达式,但是并没有生效,只有重启应用后才能生效呢
        一只袜子:https://github.com/yizhiwazi/springboot-socks/tree/master/springboot-schedule-task 下载源码运行 然后将SpringBoot版本修改为你项目的版本 看看是不是这个问题
      • ImFsx:这是单个任务,如果是多个任务怎么处理,谢谢
        知道2222:如果整合mongodb怎么写查询语句
        廿月廿日:关于第二个动态多任务.
        1.将动态定时任务的代码文件在项目中复制一份,改一下名
        2.在数据库插入多条数据,每个任务有一个查询数据库的sql语句,改为如下形式(根据id查询动态任务的cron语句)
        @Select("select cron from cron where cron_id= '1' limit 1")
        3.总结一下,就是在spring容器注册多个定时任务,每个定时任务的区别就是sql语句以及文件名,具体的任务任务代码不一样.
        PS:虽然知道老哥你不需要了,但是给后面需要的童鞋看看吧.

      本文标题:SpringBoot 创建定时任务(配合数据库动态执行)

      本文链接:https://www.haomeiwen.com/subject/zjwauxtx.html