SpringBoot中实现动态任务 2021-04-29 19:40 SpringBoot中实现动态任务 > 版本 spring-boot 2.4.5 利用`SchedulingConfigurer`接口可以实现动态决定任务的执行周期,cron配置在数据库中 [](https://imgtu.com/i/gkf88P) 核心代码如下: ```java package com.example.demo.schedule; import lombok.extern.slf4j.Slf4j; 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 org.springframework.util.StringUtils; /** * @author: HanXu * on 2021/4/28 * Class description: 动态任务抽象类 */ @Slf4j @Configuration @EnableScheduling public abstract class DynamicConfigureScheduling implements SchedulingConfigurer { /** * 动态配置cron * @param scheduledTaskRegistrar */ @Override public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) { scheduledTaskRegistrar.addTriggerTask( // 定时任务 () -> { detailTask(); }, // 触发器:在当前任务执行时,获取下一次任务的cron;所以修改cron后,会在下下次生效。 triggerContext -> { // 从数据库中获取,在页面动态修改 String dynamicCron = getDynamicCron(); if (StringUtils.isEmpty(dynamicCron)) { dynamicCron = getCron(); } return new CronTrigger(dynamicCron).nextExecutionTime(triggerContext); } ); } /** * 具体任务 * 子类实现具体逻辑 */ protected abstract void detailTask(); /** * 动态获取cron * @return */ protected abstract String getDynamicCron(); /** * 默认周期 * 返回cron表达式 * @return */ protected abstract String getCron(); } ``` 具体的动态子任务1: ```java package com.example.demo.schedule; import com.example.demo.mapper.DynamicTimTaskMapper; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import javax.annotation.Resource; /** * @author: HanXu * on 2021/4/29 * Class description: 具体任务1 */ @Slf4j @Component public class DynamicTaskDemo1 extends DynamicConfigureScheduling { @Resource private DynamicTimTaskMapper dynamicTimTaskMapper; @Override protected void detailTask() { log.info("{}执行任务1111111", Thread.currentThread().getName()); } @Override protected String getDynamicCron() { return dynamicTimTaskMapper.selectById(1).getCron(); } @Override protected String getCron() { return "0 0/2 * * * ?"; } } ``` 动态子任务2: ```java package com.example.demo.schedule; import com.example.demo.mapper.DynamicTimTaskMapper; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import javax.annotation.Resource; /** * @author: HanXu * on 2021/4/28 * Class description: 具体任务2 */ @Slf4j @Component public class DynamicTaskDemo2 extends DynamicConfigureScheduling { @Resource private DynamicTimTaskMapper dynamicTimTaskMapper; @Override protected void detailTask() { log.info("{}执行任务2222222", Thread.currentThread().getName()); } @Override protected String getDynamicCron() { return dynamicTimTaskMapper.selectById(2).getCron(); } @Override protected String getCron() { return "0 0/5 * * * ?"; } } ``` 效果: 首次执行: [](https://imgtu.com/i/gkfdEj) 动态任务1每个1分钟执行一次,动态任务2每隔两分钟执行一次。 当将数据库中的cron修改后: [](https://imgtu.com/i/gkfs2V) 效果: [](https://imgtu.com/i/gkfh5R) 此时,动态任务1变成了两分钟执行一次(19:30,19:32),动态任务2变成了1分钟执行一次。符合数据库中的配置。 总结: 在SpringBoot中可通过`SchedulingConfigurer`接口实现动态执行周期的任务,在每次执行任务时会决定下次cron的值,所以修改后的cron会在下下次生效。其中动态修改的媒介可以由MySQL换成各种东西。 番外: 配置多线程执行任务 ```java package com.example.demo.schedule; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Bean; 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 org.springframework.util.StringUtils; import java.util.concurrent.Executor; import java.util.concurrent.Executors; /** * @author: HanXu * on 2021/4/28 * Class description: 动态任务抽象类 */ @Slf4j @Configuration @EnableScheduling public abstract class DynamicConfigureScheduling implements SchedulingConfigurer { /** * 动态配置cron * @param scheduledTaskRegistrar */ @Override public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) { scheduledTaskRegistrar.setScheduler(taskScheduler()); scheduledTaskRegistrar.addTriggerTask( // 定时任务 () -> { detailTask(); }, // 触发器:在当前任务执行时,获取下一次任务的cron;所以修改cron后,会在下下次生效。 triggerContext -> { // 从数据库中获取,在页面动态修改 String dynamicCron = getDynamicCron(); if (StringUtils.isEmpty(dynamicCron)) { dynamicCron = getCron(); } return new CronTrigger(dynamicCron).nextExecutionTime(triggerContext); } ); } /** * 设置TaskScheduler用于注册计划任务 * * @return */ @Bean(destroyMethod = "shutdown") public Executor taskScheduler() { //创建线程池 return Executors.newScheduledThreadPool(5); } /** * 具体任务 * 子类实现具体逻辑 */ protected abstract void detailTask(); /** * 动态获取cron * @return */ protected abstract String getDynamicCron(); /** * 默认周期 * 返回cron表达式 * @return */ protected abstract String getCron(); } ``` 源码: https://github.com/hanhanhanxu/JustDemo/tree/main/DynamicTimTask (小技巧:在github二级域名添加1s可以在网站上以vscode的形式查看代码仓库。 例如:https://github1s.com/hanhanhanxu/JustDemo/tree/main/DynamicTimTask) --END--
发表评论