前言
在做 SpringBoot 项目的过程中,有时客户会提出按照指定时间执行一次业务的需求。
如果客户需要改动业务的执行时间,即动态地调整定时任务的执行时间,那么可以采用SpringBoot 自带的 ScheduledTaskRegistrar 类作为解决方案来实现。
在单一使用 ScheduledTaskRegistrar 类解决定时任务问题的时候,可能会达不到预期的动态调整定时任务的效果。
如果灵活配合使用对应的工具类(ThreadPoolTaskScheduler 类),则可以方便地对动态调整定时任务进行管理。
本文会从问题出发,详细介绍 ScheduledTaskRegistrar 类是如何解决动态调整定时任务的思路,并给出关键的代码示例,帮助大家快速地上手学习。
一、问题背景
-
在指定的某一时刻执行业务
-
可以在前端手动地更改执行时间,更改后及时生效
-
项目没有引入 xxljob 或者 quartz 等框架
在实际项目中,定时任务一般可以满足在指定某一时间触发某个业务的场景,执行业务的时间是固定的,但想要实现动态地随着前端页面接口所传入的时间进行调整定时任务的效果,那可以参考一下本文的做法。
二、痛点所在
如果单一地使用 SpringBoot 自带的 ScheduledTaskRegistrar 或者 @Schedule 去实现,那么可能会有以下问题:
- 只能按照指定的时间去执行,更改执行时间需要重启服务;
- 无法删除该定时任务,或者删除后无法再启动该定时任务;
- 业务逻辑与触发器的代码耦合度太高,无法将业务代码从 ScheduledTaskRegistrar 类中抽离出去。
/**
* @author Created by BlogCodeMan on 2023/1/30 15:28
*/
@Slf4j
@Component
@EnableScheduling
public class ScheduleTaskDemo implements SchedulingConfigurer {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
//Runnable线程注册任务
Runnable taskOne = () -> {
//需要执行的业务逻辑,一般会在这里封装好
logger.info("----------业务执行结束----------");
};
//任务的触发时间,一般使用 cron 表达式
Trigger triggerOne = triggerContext -> {
Date nextExecTime = null;
try {
// 此处指定 cron 表达式
String cron = "0 00 12 ? * *";
if (StringUtils.isBlank(cron)) {
// 提示参数为空
logger.info("trigger定时器的 cron 参数为空!");
// 如果为空则赋默认值,每天中午12点
cron = "0 00 12 ? * *";
}
logger.info("---------->定时任务执行中<---------");
CronTrigger cronTrigger =