这个在网上都要解决方案了,我来梳理下我这边理解的, ,我简单的就实现了,当然可以动态加更多的内容;
定时任务对于大多数需求来说,@注解级别就可以了,,,但是有些需要提前用数据库配置的,,也可以通过实现 SchedulingConfigurer 这个也是可以的,配置好后重启即可;还有一些情况是需要根据业务增删改查来动态生成的,这块就是今天来分享;首先如果你的业务比较大,定时任务比较多,建议分开,可以使用XXL-JOB;由于我这边业务简单,任务也不多,,就自定义了;说说我的思路,我这边一开始是使用的实现SchedulingConfigurer,但是发现每次配置一个都要重启服务,有点接受不了;然后梳理下逻辑SchedulingConfigurer,原因是这个SchedulingConfigurer接口的方法参数ScheduledTaskRegistrar 实现了任务的新增,删除等操作,原本以为已经注入到spirng IOC了,但是发现,没有注册,是通过ScheduledAnnotationBeanPostProcessor 这个类进行加载的,既然没有注册,我们就自己写一个不就行了 吗;我几乎没改什么,,就是按照ScheduledTaskRegistrar这个里面的代码进行实现的,请看代码:
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.config.TriggerTask;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Slf4j
@AllArgsConstructor
@Configuration
public class CustomScheduledTaskRegistrar implements DisposableBean {
private TaskScheduler taskScheduler;
private final Map scheduledTasks = new ConcurrentHashMap(16);
public void addTriggerTask(String key,Runnable task, Trigger trigger) {
if (task == null || trigger == null || StringUtils.isBlank(key)){
log.error("任务key和任务线程以及触发器不能为空");
return;
}
CustomScheduledTask customScheduledTask1 = scheduledTasks.get(key);
if (customScheduledTask1 != null){
log.error("{}---对应的任务已存在,请勿重复创建,如需重复创建,请先执行删除后在尝试新建任务",key);
return;
}
// addTriggerTask(new TriggerTask(task, trigger));
CustomScheduledTask customScheduledTask = scheduleTriggerTask(new TriggerTask(task, trigger));
customScheduledTask.future = this.taskScheduler.schedule(task, trigger);
scheduledTasks.put(key,customScheduledTask);
}
public void removeTriggerTask(String key) {
if (StringUtils.isBlank(key)){
log.error("key不能为空");
return;
}
CustomScheduledTask scheduledTask = scheduledTasks.get(key);
if (scheduledTask == null){
log.error("{}对应的任务不存在,请勿重复删除",key);
}else {
scheduledTask.cancel();
scheduledTasks.remove(key);
}
}
private CustomScheduledTask scheduleTriggerTask(TriggerTask task) {
return new CustomScheduledTask(task);
}
@Override
public void destroy() throws Exception {
for (CustomScheduledTask task : this.scheduledTasks.values()) {
task.cancel();
}
}
}
就这几行代码,就可以了,目前满足我这边的业务了,,
在开发过程中,发现一个类只能在spring包内使用,我这边也重写了,,只是改了名字
import org.springframework.lang.Nullable;
import org.springframework.scheduling.config.*;
import java.util.concurrent.ScheduledFuture;
public final class CustomScheduledTask {
private final Task task;
@Nullable
volatile ScheduledFuture> future;
CustomScheduledTask(Task task) {
this.task = task;
}
public Task getTask() {
return this.task;
}
public void cancel() {
cancel(true);
}
public void cancel(boolean mayInterruptIfRunning) {
ScheduledFuture> future = this.future;
if (future != null) {
future.cancel(mayInterruptIfRunning);
}
}
@Override
public String toString() {
return this.task.toString();
}
}
以上就实现了,动态添加任务和删除任务,如果 private TaskScheduler taskScheduler; spring找不到,需要自己暴露下
这样就可以和spring 共用这个定时任务线程池了
测试代码比较简单:
@ApiOperation("测试动态创建定时任务")
@GetMapping("startJob")
public Result createJob(String cron,String key){
if (StringUtils.isBlank(cron)){
//默认一秒执行一次
cron = "*/1 * * * * ?";
}
String tempCron = cron;
customScheduledTaskRegistrar.addTriggerTask(
key
,
()->log.info("key:{},开始执行定时任务---{}",key,tempCron),
triggerContext -> new CronTrigger(tempCron).nextExecutionTime(triggerContext));
return Result.success(tempCron);
}
@ApiOperation("测试动态删除定时任务")
@GetMapping("removeJob")
public Result removeJob(String key){
customScheduledTaskRegistrar.removeTriggerTask(key);
return Result.success();
}
ok,结束



