springboot动态添加定时任务
springboot动态添加定时任务
引用(感谢)
https://blog.csdn.net/iT_MaNongking/article/details/145305954?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-4-145305954-blog-125277410.235^v43^pc_blog_bottom_relevance_base2&spm=1001.2101.3001.4242.3&utm_relevant_index=6
感谢原博主
本文共展示两种方式
- 延迟任务,只执行一次的任务
- 需要动态扩展,执行多次的任务
一、延迟执行,只执行一次的任务
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
@Resource
ThreadPoolTaskScheduler syncScheduler;
/**
* batch: 业务数据
*/
public void addSchedule(Batch batch) {
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.MINUTE, batch.getUpgradeTime());
// schedule :调度给定的Runnable ,在指定的执行时间调用它。
//一旦调度程序关闭或返回的ScheduledFuture被取消,执行将结束。
//参数:
//任务 – 触发器触发时执行的 Runnable
//startTime – 任务所需的执行时间(如果这是过去,则任务将立即执行,即尽快执行)
Date startTime = calendar.getTime();
ScheduledFuture<?> schedule = syncScheduler.schedule(
getRunnable(batch.getBatchId()), calendar.getTime());
}
/**
* batchId: 业务数据
*/
public Runnable getRunnable(Long batchId) {
return () -> {
// 实现业务逻辑
stop(batchId);
};
}
二、需要动态执行的任务
随时新增、删除;
修改时间:我这里的逻辑就是删除旧的任务,再新增新的任务
配置类,固定信息不用改
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.config.CronTask;
import org.springframework.stereotype.Component;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;
/**
* @description: 添加定时任务注册类,用来增加、删除定时任务。
**/
@Component
public class CronTaskRegistrar implements DisposableBean {
public static final Map<Runnable, ScheduledFuture<?>> scheduledTasks = new ConcurrentHashMap<>();
public static final Map<Long, Runnable> runnableMap = new ConcurrentHashMap<>();
@Autowired
private TaskScheduler taskScheduler;
public TaskScheduler getScheduler() {
return this.taskScheduler;
}
/**
* 新增定时任务
* @param task
* @param cronExpression
*/
public void addCronTask(Runnable task, String cronExpression) {
addCronTask(new CronTask(task, cronExpression));
}
public void addCronTask(CronTask cronTask) {
if (cronTask != null) {
Runnable task = cronTask.getRunnable();
if (scheduledTasks.containsKey(task)) {
removeCronTask(task);
}
scheduledTasks.put(task, scheduleCronTask(cronTask));
}
}
/**
* @description: 移除定时任务
*/
public void removeCronTask(Runnable task) {
ScheduledFuture<?> scheduledTask = scheduledTasks.get(task);
if (scheduledTask != null) {
scheduledTask.cancel(true);
scheduledTasks.remove(task);
}
}
public ScheduledFuture<?> scheduleCronTask(CronTask cronTask) {
return this.taskScheduler.schedule(cronTask.getRunnable(), cronTask.getTrigger());
}
/**
* @description: 定时任务销毁
*/
@Override
public void destroy() {
for (ScheduledFuture<?> task : scheduledTasks.values()) {
task.cancel(true);
}
scheduledTasks.clear();
}
}
固定信息不用改
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ConcurrentTaskScheduler;
@Configuration
public class SchedulerConfig {
@Bean()
public TaskScheduler taskScheduler() {
return new ConcurrentTaskScheduler();
}
}
获取bean的,固定信息不用改
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class SpringContextUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
applicationContext = context;
}
public static <T> T getBean(Class<T> clazz) {
return applicationContext.getBean(clazz);
}
public static Object getBean(String name) {
return applicationContext.getBean(name);
}
}
业务实现类,需要改
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Method;
@Slf4j
public class SchedulingRunnable implements Runnable {
// TODO 对象需要改,也就是定时任务需要处理的东西
private TTagPO tag;
public SchedulingRunnable(TTagPO tag) {
this.tag = tag;
}
@Override
public void run() {
try {
// 通过反射调用需要执行业务的方法,参数也可以放在当前类的构造方法中,写死也可以
Object target = SpringContextUtil.getBean("类名");
// 方法的参数多的话,就是用 ... 这个东西
Method method = target.getClass().getDeclaredMethod("方法名", 方法的参数.class);
ReflectionUtils.makeAccessible(method);
method.invoke(target, tag);
} catch (Exception ex) {
log.error("定时任务执行失败,tag_id:{}", tag.getId(), ex);
}
}
}
业务实现类需要改
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ylzinfo.brt.constant.GlobalConstant;
import com.ylzinfo.brt.entity.TTagPO;
import com.ylzinfo.brt.service.impl.TTagServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.List;
/**
* 项目启动后加载动态定时任务
*/
@Slf4j
@Component
public class JobsLoader implements ApplicationRunner {
@Autowired
private CronTaskRegistrar cronTaskRegistrar;
@Resource
private TTagServiceImpl tagService;
// 第一个 %s 为分钟;第二个为小时;第三个为天
// 假如一二三参数分别为:15、17、3;就表示:每个月从一号开始算每3天的17点15分执行一次任务
// 具体的执行日期看个人需求
public static final String CRON = "0 %s %s 1/%s * ?";
// 业务方法,获取定时任务执行的时间的
public static String getCron(String cycleTime, Integer cycleDay){
String[] split = cycleTime.split(":");
return String.format(CRON, split[1], split[0], cycleDay.toString());
}
/**
* 项目启动后加载动态定时任务
* @param args
* @throws Exception
*/
@Override
public void run(ApplicationArguments args) throws Exception {
ttsTaskLoader();
}
/**
* @description: 加载定时发送任务
* @create: 2025/01/10 15:50
* @param:
* @return:
*/
public void ttsTaskLoader() {
// 项目启动时,初始化定时器
// 业务方法,获取需要加载到定时任务的
List<TTagPO> list = tagService.list();
for (TTagPO tag : list) {
SchedulingRunnable task = new SchedulingRunnable(tag);
cronTaskRegistrar.addCronTask(task, getCron(tag.getCycleTime(), tag.getCycleDay()));
CronTaskRegistrar.runnableMap.put(tag.getId(), task);
}
}
}
新增定时任务、删除定时任务
@Resource
private CronTaskRegistrar cronTaskRegistrar;
/**
* 新增动态定时任务
* @param tag
* @param cycleTime
* @param cycleDay
*/
public void addSchedule(TTagPO tag, String cycleTime, Integer cycleDay){
SchedulingRunnable task = new SchedulingRunnable(tag);
cronTaskRegistrar.addCronTask(task, JobsLoader.getCron(cycleTime, cycleDay));
CronTaskRegistrar.runnableMap.put(tag.getId(), task);
}
/**
* 删除定时任务
* @param id
*/
public void removeSchedule(Long id){
cronTaskRegistrar.removeCronTask(CronTaskRegistrar.runnableMap.get(id));
CronTaskRegistrar.runnableMap.remove(id);
}