package com.demo.autotask;
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();
}
}
package com.demo.autotask;
import cn.hutool.core.util.StrUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
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<String, CustomScheduledTask> scheduledTasks = new ConcurrentHashMap(16);
public void addTriggerTask(String key, Runnable task, Trigger trigger) {
if (task == null || trigger == null || StrUtil.isBlank(key)) {
log.error("任务key和任务线程以及触发器不能为空");
return;
}
CustomScheduledTask customScheduledTask1 = scheduledTasks.get(key);
if (customScheduledTask1 != null) {
log.error("{}---对应的任务已存在,请勿重复创建,如需重复创建,请先执行删除后在尝试新建任务", key);
return;
}
CustomScheduledTask customScheduledTask = scheduleTriggerTask(new TriggerTask(task, trigger));
customScheduledTask.future = this.taskScheduler.schedule(task, trigger);
scheduledTasks.put(key, customScheduledTask);
}
public void removeTriggerTask(String key) {
if (StrUtil.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();
}
}
}
package com.demo.autotask;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.springframework.scheduling.config.CronTask;
import org.springframework.scheduling.support.CronTrigger;
@Accessors(chain = true)
@Getter
@Setter
public class CustomTask extends CronTask {
private String taskName;
private int taskSchedule;
private int status;
private String taskFunc;
private String cron = "0/1 * * * * ?";
public CustomTask(Runnable runnable, String expression) {
super(runnable, expression);
}
public CustomTask(Runnable runnable, CronTrigger cronTrigger) {
super(runnable, cronTrigger);
}
}
package com.demo.autotask;
import lombok.Getter;
import lombok.Setter;
import org.springframework.stereotype.Component;
@Component
@Getter
@Setter
public class TaskAPI {
public void execTask1() {
System.out.println("exec task1");
}
public void execTask2() {
System.out.println("exec task2");
}
}
package com.demo.autotask;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
@Component
public class TaskAPIManager {
@Resource
private TaskAPI taskAPI;
@Resource
private CustomScheduledTaskRegistrar customScheduledTaskRegistrar;
public List<CustomTask> getTasks() {
Class clz = taskAPI.getClass();
List<CustomTask> customTasks = new ArrayList<>();
for (Method method : clz.getDeclaredMethods()) {
method.setAccessible(true);
customTasks.add(
new CustomTask(() -> {
try {
method.invoke(taskAPI);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}, "0/1 * * * * ?").setTaskName(method.getName()).setStatus(1)
.setTaskFunc(method.getName())
);
}
return customTasks;
}
public void add(CustomTask customTask) {
customScheduledTaskRegistrar.addTriggerTask(customTask.getTaskName(), customTask.getRunnable(), triggerContext -> {
return new CronTrigger(customTask.getCron()).nextExecutionTime(triggerContext);
});
}
public void remove(String taskName) {
customScheduledTaskRegistrar.removeTriggerTask(taskName);
}
}
package com.demo.autotask;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
@RequestMapping("/api")
@Slf4j
public class TaskController {
@Resource
private TaskAPIManager taskAPIManager;
@RequestMapping("/task/exec")
public String exec(String taskName) {
for (CustomTask customTask : taskAPIManager.getTasks()) {
if (taskName.equals(customTask.getTaskName())) {
taskAPIManager.add(customTask);
}
}
return "exec success";
}
@RequestMapping("/task/remove")
public String remove(String taskName) {
taskAPIManager.remove(taskName);
return "remove success";
}
}