侧边栏壁纸
博主头像
孔子说JAVA博主等级

成功只是一只沦落在鸡窝里的鹰,成功永远属于自信且有毅力的人!

  • 累计撰写 285 篇文章
  • 累计创建 125 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录

springboot之SchedulingConfigurer接口,实现动态定时任务

孔子说JAVA
2022-08-24 / 0 评论 / 0 点赞 / 63 阅读 / 4,608 字 / 正在检测是否收录...

在Spring Boot项目中,通过@EnableScheduling可启用Spring自带的定时任务支持,然后通过@Scheduled注解定义定时任务,但是通过该注解只能编写固定时间的定时任务,无法动态调整定时间隔。可以通过实现SchedulingConfigurer接口实现动态定时任务注册,在不重启项目的情况下,修改定时任务表达式,可以实时获取新的定时任务执行时间规则;修改定时任务执行状态,可以随时开关定时任务。

1、创建任务表

创建定时任务执行周期表,用来管理定时任务,主要存储定时任务的任务名称,cron(定时任务表达式),定时任务开关等。

DROP TABLE IF EXISTS `sys_cron`;
CREATE TABLE `sys_cron` (
  `id` int DEFAULT NULL,
  `name` varchar(20) DEFAULT NULL,
  `cron` varchar(30) DEFAULT NULL,
  `open` tinyint(1) DEFAULT NULL COMMENT '1开启, 其他为关闭'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
-- ----------------------------
-- Records of sys_cron
-- ----------------------------
INSERT INTO `sys_cron` VALUES (1, 'demo1', '0/5 * * * * ?', 1);
INSERT INTO `sys_cron` VALUES (2, 'demo2', '0/6 * * * * ?', 1);

2、实现代码

其实SchedulingConfigurer实现方法很简单,只需要实现 SchedulingConfigurer 并重写 configureTasks 方法,在启动类必须加上 @EnableScheduling 注解即可

2.1 创建springboot项目

  1. 创建spring boot项目,添加web、mybatis-plus、mysql相关依赖
<!--web-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--mybatis-plus-->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.3</version>
</dependency>
<!--MySql驱动-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>
  1. 在项目中的application.yml 添加数据源
spring:
  # 数据源
  datasource:
      url: jdbc:mysql://localhost:3306/db_test?&allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSl=false
      username: root
      password: root
      driver-class-name: com.mysql.jdbc.Driver

2.2 创建定时器

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

定时任务的执行周期需要从数据库中获取,所有首先配置sys_cron表的基本操作:

  1. 创建SysCron实体类
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serializable;

/**
 * @author qzz
 */
@Data
@TableName("sys_cron")
public class SysCron implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 主键id
     */
    @TableId(value="id",type = IdType.AUTO)
    private Integer id;

    /**
     * cron执行表达式
     */
    @TableField("cron")
    private String cron;
}


  1. 创建CronMapper
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.schedulingconfigurerdemo.entity.SysCron;
import org.springframework.stereotype.Repository;

@Repository
public interface CronMapper extends BaseMapper<SysCron> {
}
  1. 配置dao层包扫描

配置文件配置扫描mapper.xml的路径:

image-1661155775620

启动类上添加@MapperSacn注解:

package com.example.schedulingconfigurerdemo;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author qzz
 */
@SpringBootApplication
@MapperScan("com.example.schedulingconfigurerdemo.dao")
public class SchedulingConfigurerDemoApplication {

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

}
  1. 定时任务配置类:
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.example.schedulingconfigurerdemo.dao.CronMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import java.util.Date;

/**
 * 基于接口SchedulingConfigurer的定时任务
 * 注解EnableScheduling:用于开启定时任务
 */
@Configuration
@EnableScheduling
public class ConfigurerSchedulingConfig implements SchedulingConfigurer {

    @Autowired
    private CronMapper cronMapper;


    /**
     * 重写配置定时任务的方法
     * @param scheduledTaskRegistrar
     */
    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {

        scheduledTaskRegistrar.addTriggerTask(
                //1.添加任务内容(Runnable)
                ()->{System.out.println("执行动态定时任务:"+new Date(System.currentTimeMillis())); }
                //2.设置执行周期(Trigger)
                ,triggerContext -> {
                    //2.1从数据库中获取执行周期
                    String cron = cronMapper.selectOne(null).getCron();
                    //System.out.println("数据库中获取的执行周期是:"+cron);
                    //2.2 合法性校验
                    if(StringUtils.isBlank(cron)){
                        //为空,设置默认值
                        cron = "0/5 * * * * ?";
                    }
                    //返回执行周期(Date)
                    return new CronTrigger(cron).nextExecutionTime(triggerContext);
                }

        );

    }


}

3、启动项目测试

启动了springboot之后就会发现每次执行的时间差是数据库中设定的定时任务:

image-1661155967537

动态修改执行周期,如修改数据库中的执行时间由每5秒执行一次修改成每秒执行一次,查看控制台,发现执行周期已经改变,并且不需要我们重启应用,十分方便。

0

评论区