Springboot定时任务实现动态设置

569 阅读2分钟

Springboot定时任务实现动态设置

背景

在使用@Scheduled注解配置定时任务时,cron表达式一般写死在配置文件和代码中,不能根据业务或者环境的变化,进行灵活的变更,局限性很大。

本文围绕动态设置展开。

实现

配置文件

server:
  port: 8090

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

这里配置一个默认的cron执行周期。

定时任务配置类

第一种实现

使用CronTrigger触发器,可动态修改cron表达式来操作循环规则

package com.lyu.scheduledtask.task;
​
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;
​
import java.time.LocalDateTime;
​
/**
 * @Author: Lyu
 * @Description: 使用CronTrigger触发器,可动态修改cron表达式来操作循环规则
 * @Date: Created in 15:36 2022/11/14
 * @Modified By:
 */
@Component
public class ScheduledTaskCronTrigger implements SchedulingConfigurer {
    Logger LOGGER = LoggerFactory.getLogger(ScheduledTaskCronTrigger.class);
​
    @Value("${task.cron}")
    private String cron;
​
    public void setCron(String cron) {
        this.cron = cron;
    }
​
    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.addTriggerTask(() -> {
            // 业务代码
            LOGGER.info("CronTrigger定时任务,currentTime:{},cron:{}", LocalDateTime.now().toString(), cron);
        }, triggerContext -> {
            // 使用CronTrigger触发器,可动态修改cron表达式来操作循环规则
            CronTrigger cronTrigger = new CronTrigger(cron);
            return cronTrigger.nextExecutionTime(triggerContext);
        });
    }
}
​
第二种实现

使用PeriodicTrigger触发器,可动态修改Timer来操作循环规则, 若周期时分秒执行,且数值大于进制,比如每71秒或65分或27小时执行,此时只能使用PeriodicTrigger。

package com.lyu.scheduledtask.task;
​
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.scheduling.support.PeriodicTrigger;
import org.springframework.stereotype.Component;
​
import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;
​
/**
 * @Author: Lyu
 * @Description: 使用PeriodicTrigger触发器,可动态修改cron表达式来操作循环规则:若周期时分秒执行,且数值大于进制,比如每71秒或65分或27小时执行
 * @Date: Created in 15:36 2022/11/14
 * @Modified By:
 */
@Component
public class ScheduledTaskPeriodicTrigger implements SchedulingConfigurer {
    Logger LOGGER = LoggerFactory.getLogger(ScheduledTaskPeriodicTrigger.class);
​
    private Long timer = 10000L;
​
    public void setTimer(Long timer) {
        this.timer = timer;
    }
​
    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.addTriggerTask(() -> {
            // 业务代码
            LOGGER.info("PeriodicTrigger定时任务,currentTime:{},timer:{}", LocalDateTime.now().toString(), timer);
        }, triggerContext -> {
            // 使用不同的触发器,为设置循环时间的关键,区别于CronTrigger触发器,该触发器可随意设置循环间隔时间,单位为毫秒
            PeriodicTrigger periodicTrigger = new PeriodicTrigger(timer, TimeUnit.MILLISECONDS);
            return periodicTrigger.nextExecutionTime(triggerContext);
        });
    }
}
​

测试

再编写一个测试的接口

package com.lyu.scheduledtask.controller;
​
import com.lyu.scheduledtask.task.ScheduledTaskCronTrigger;
import com.lyu.scheduledtask.task.ScheduledTaskPeriodicTrigger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
​
/**
 * @Author: Lyu
 * @Description:
 * @Date: Created in 15:53 2022/11/14
 * @Modified By:
 */
@RestController
@RequestMapping("/test")
public class ScheduledTaskController {
​
    @Autowired
    private ScheduledTaskCronTrigger scheduledTaskCronTrigger;
​
    @Autowired
    private ScheduledTaskPeriodicTrigger scheduledTaskPeriodicTrigger;
​
​
    @GetMapping(name = "设置定时时间", value = {"/updateCron"})
    public Object cron(@RequestParam("cron") String cron) {
        scheduledTaskCronTrigger.setCron(cron);
​
        return "设置成功";
    }
​
    @GetMapping(name = "设置定时时间", value = {"/updateTimer"})
    public Object timer(@RequestParam("timer") Long timer) {
        scheduledTaskPeriodicTrigger.setTimer(timer);
        return "设置成功";
    }
​
​
}
​

启动项目,分别调用两个设置执行时间的接口。

测试结果

默认配置的执行截图:

image.png

动态设置后的执行结果:

image.png

一键三连!

可以关注公众号:程序员一二。