这个在网上都要解决方案了,我来梳理下我这边理解的, ,我简单的就实现了,当然可以动态加更多的内容;
定时任务对于大多数需求来说,@注解级别就可以了,,,但是有些需要提前用数据库配置的,,也可以通过实现 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;
/**
* @description: 自定义定时任务注册器
* 本类请参考 {@link ScheduledTaskRegistrar},通过该类进行自定义即可
* @program: datacenter
* @author: zhaoshouyun
* @create: 2022-05-14 16:45
*/
@Slf4j
@AllArgsConstructor
@Configuration
public class CustomScheduledTaskRegistrar implements DisposableBean {
private TaskScheduler taskScheduler;
private final Map<String,CustomScheduledTask> 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包内使用,我这边也重写了,,只是改了名字
/*
* Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.springframework.lang.Nullable;
import org.springframework.scheduling.config.*;
import java.util.concurrent.ScheduledFuture;
/**
* A representation of a scheduled task at runtime,
* used as a return value for scheduling methods.
*
* @author Juergen Hoeller
* @since 4.3
* @see ScheduledTaskRegistrar#scheduleCronTask(CronTask)
* @see ScheduledTaskRegistrar#scheduleFixedRateTask(FixedRateTask)
* @see ScheduledTaskRegistrar#scheduleFixedDelayTask(FixedDelayTask)
* @see ScheduledFuture
*/
public final class CustomScheduledTask {
private final Task task;
@Nullable
volatile ScheduledFuture<?> future;
CustomScheduledTask(Task task) {
this.task = task;
}
/**
* Return the underlying task (typically a {@link CronTask},
* {@link FixedRateTask} or {@link FixedDelayTask}).
* @since 5.0.2
*/
public Task getTask() {
return this.task;
}
/**
* Trigger cancellation of this scheduled task.
* <p>This variant will force interruption of the task if still running.
* @see #cancel(boolean)
*/
public void cancel() {
cancel(true);
}
/**
* Trigger cancellation of this scheduled task.
* @param mayInterruptIfRunning whether to force interruption of the task
* if still running (specify {@code false} to allow the task to complete)
* @since 5.3.18
* @see ScheduledFuture#cancel(boolean)
*/
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,结束
|