背景
在使用@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 "设置成功";
}
}
启动项目,分别调用两个设置执行时间的接口。
测试结果
默认配置的执行截图:
动态设置后的执行结果:
可以公众号一键三连,谢谢