SpringBoot外部化配置定时任务cron表达式

Posted loveletters

tags:

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

SpringBoot外部化配置定时任务cron表达式

背景

在日常开发中我们经常会使用到定时任务的情况,SpringBoot为我们很方便的集成了定时任务。我们只需要简单的几部就可以配置好一个定时任务。

@Component
public class LocationTask 

    @Scheduled(cron = "0/10 * * * * ?")
    public void runTask() 
        System.out.println("hello");
    


@SpringBootApplication
@EnableScheduling
public class DynamicScheduledDemoApplication 

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



我们只需要定义一个Task将它交给Spring管理,然后再在需要执行的任务上添加上具体的cron表达式即可。但是这种硬编码的方式其实不太合适,不方便我们后面修改。所以我们可以更改一下,将corn表达式改成外部化配置。

配置文件

最简单的一种就是直接将cron表达式的值配置在配置文件中来注入

@Component
public class LocationTask 

    @Scheduled(cron = "$my.task.cron")
    public void runTask() 
        System.out.println("hello");
    

然后再在配置文件中配置一下:

my:
  task:
    cron: 0/10 * * * * ?

MySQL配置

我们同样可以将cron配置在数据库中

我们在数据库中创建一张这样的表来存放配置文件

CREATE TABLE `scheduled_task` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `cron_expression` varchar(255) NOT NULL,
  `enabled` bit(1) NOT NULL,
  `task_name` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
  • ScheduledTask 为我们的Entity对象
  • ScheduledTask1、ScheduledTask2为我们具体执行定时任务的类
  • TaskSchedulerConfig用来配置定时任务执行的线程池
  • ScheduledTaskManager中通过查询所有的task配置,然后通过taskName从spring容器中找到具体的对象,将他们注入线程池中执行。
@Entity
@Table(name = "scheduled_task")
@Data
public class ScheduledTask 
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "cron_expression", nullable = false)
    private String cronExpression;

    @Column(name = "task_name", nullable = false)
    private String taskName;

    @Column(name = "enabled", nullable = false)
    private Boolean enabled;



public interface ScheduledTaskRepository extends JpaRepository<ScheduledTask, Long> 
    List<ScheduledTask> findAllByEnabledTrue();



@Component
public class ScheduledTask1 implements Runnable 
    @Override
    public void run() 
        // 定时任务1的执行逻辑
        System.out.println("task1");
    


@Component
public class ScheduledTask2 implements Runnable 
    @Override
    public void run() 
        // 定时任务2的执行逻辑
        System.out.println("task2");
    


@Configuration
public class TaskSchedulerConfig 
    @Bean
    public TaskScheduler taskScheduler() 
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setPoolSize(10);
        scheduler.setThreadNamePrefix("TaskScheduler-");
        scheduler.initialize();
        return scheduler;
    


@Component
@RequiredArgsConstructor
public class ScheduledTaskManager 
    private final TaskScheduler taskScheduler;
    private final ScheduledTaskRepository taskRepository;
    private final ApplicationContext applicationContext;


    @PostConstruct
    public void registerTasks() 
        List<ScheduledTask> tasks = taskRepository.findAllByEnabledTrue();
        tasks.forEach(task -> 
            try 
                Runnable taskInstance = (Runnable) applicationContext.getBean(task.getTaskName());

                taskScheduler.schedule(taskInstance, new CronTrigger(task.getCronExpression()));
             catch (Exception e) 
                // handle exception
            
        );
    


SpringBoot动态定时任务

SpringBoot动态定时任务

前言

之前在SpringBoot项目中简单使用定时任务,不过由于要借助cron表达式且都提前定义好放在配置文件里,不能在项目运行中动态修改任务执行时间,实在不太灵活。现在我们就来实现可以动态修改cron表达式的定时任务。

配置文件

application-task.yml,其余的配置 application.yml 等就按照springBoot正常配置即可

task:
  cron: 0/10 * * * * ?
  timer: 10

定时任务核心类

import cn.hutool.core.date.DateUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
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.PeriodicTrigger;

import java.util.Date;


@Data
@Slf4j
@Configuration
@EnableScheduling
@ConfigurationProperties(prefix = "task")
public class WorkScheduleTask  implements SchedulingConfigurer 

    private String cron;

    private Long timer;


    @Override

    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) 
        // 动态使用cron表达式设置循环间隔
        taskRegistrar.addTriggerTask(() -> 
            String dateTime = DateUtil.formatDateTime(new Date());
            String threadName = Thread.currentThread().getName();
            log.info("定时任务开始[configureTasks] :,线程:", dateTime, threadName);
        , triggerContext -> 
            // 使用CronTrigger触发器,可动态修改cron表达式来操作循环规则
            // 只能定义小于等于间隔59秒
//          CronTrigger cronTrigger = new CronTrigger(cron);
//          return cronTrigger.nextExecutionTime(triggerContext);

            // 能定义大于等于间隔59秒
            // 使用不同的触发器,为设置循环时间的关键,区别于CronTrigger触发器,
            // 该触发器可随意设置循环间隔时间,单位为毫秒
            long seconds = timer * 1000;  // 毫秒转秒
            PeriodicTrigger periodicTrigger = new PeriodicTrigger(seconds);
            return periodicTrigger.nextExecutionTime(triggerContext);
        );
    

提供修改cron表达式的controller

@Slf4j
@CrossOrigin
@RestController
@RequestMapping("/updateTask")
public class UpdateTaskController 

    @Resource
    private WorkScheduleTask workScheduleTask;

    @PostMapping("/updateCron")
    public String updateCron(String cron) 
        log.info("new cron :", cron);
        workScheduleTask.setCron(cron);
        return "ok";
    

    @PostMapping("/updateTimer")
    public String updateTimer(Long timer) 
        log.info("new timer :", timer);
        workScheduleTask.setTimer(timer);
        return "ok";
    


一开始定时任务的执行时机和周期都是配置文件指定的,但是我们如果对于执行的周期不满意,我们可以调用接口进行修改定时任务,但是需要注意的是,这种外暴露的接最好做一下安全校验,不是谁都可以调用,否则被别人扫描到这个接口,然后随意修改,会影响我们正常的业务流程,严重可能会造成严重损失。

以上是关于SpringBoot外部化配置定时任务cron表达式的主要内容,如果未能解决你的问题,请参考以下文章

Spring 定时任务 @Scheduled cron表达式

springboot定时任务配置结束时间

SpringBoot的定时任务

SpringBoot的定时任务

SpringBoot的定时任务

springboot定时任务cron表达式详解