【SpringBoot】@Scheduled是静态配置,是我想改时间,但又不想引入其他组件,还有什么方案么?
·
TaskScheduler动态定时任务
定时任务的编写,在 Spring 里常见的两种方式:
-
@Scheduled注解 → 静态配置,启动时就确定了,不能动态改。 -
TaskScheduler→ 可以在运行时动态添加 / 修改 / 取消任务。
示例代码
任务可以存储在数据库,这里用map模拟。
import lombok.Data;
@Data
public class TaskRequest {
private String taskId;
private String cron;
private String beanName; // Bean 名称
private String methodName; // 方法名
}
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
@Configuration
public class SchedulerConfig {
@Bean
public ThreadPoolTaskScheduler taskScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(5);
scheduler.setThreadNamePrefix("dynamic-task-");
scheduler.initialize();
return scheduler;
}
}
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;
@Component
public class DynamicTaskManager {
private final TaskScheduler taskScheduler;
private final ApplicationContext applicationContext;
private final Map<String, ScheduledFuture<?>> taskMap = new ConcurrentHashMap<>();
public DynamicTaskManager(TaskScheduler taskScheduler, ApplicationContext applicationContext) {
this.taskScheduler = taskScheduler;
this.applicationContext = applicationContext;
}
// 添加任务
public void addTask(String taskId, String cron, String beanName, String methodName) {
if (taskMap.containsKey(taskId)) {
throw new IllegalArgumentException("任务已存在: " + taskId);
}
Runnable task = () -> {
try {
Object bean = applicationContext.getBean(beanName);
Method method = bean.getClass().getMethod(methodName);
method.invoke(bean);
} catch (Exception e) {
e.printStackTrace();
}
};
ScheduledFuture<?> future = taskScheduler.schedule(task, new CronTrigger(cron));
taskMap.put(taskId, future);
}
public void removeTask(String taskId) {
ScheduledFuture<?> future = taskMap.remove(taskId);
if (future != null) {
future.cancel(true);
}
}
public void updateTask(String taskId, String cron, String beanName, String methodName) {
removeTask(taskId);
addTask(taskId, cron, beanName, methodName);
}
public boolean hasTask(String taskId) {
return taskMap.containsKey(taskId);
}
public Map<String, Boolean> listTasks() {
Map<String, Boolean> result = new ConcurrentHashMap<>();
taskMap.forEach((id, f) -> result.put(id, !f.isCancelled()));
return result;
}
}
import org.springframework.stereotype.Component;
@Component("myTaskBean")
public class MyTaskMethods {
public void sendEmail() {
System.out.println("发送邮件任务执行了:" + new java.util.Date());
}
public void cleanCache() {
System.out.println("清理缓存任务执行了:" + new java.util.Date());
}
public void generateReport() {
System.out.println("生成报表任务执行了:" + new java.util.Date());
}
}
import org.springframework.web.bind.annotation.*;
import java.util.Map;
@RestController
@RequestMapping("/tasks")
public class TaskController {
private final DynamicTaskManager taskManager;
public TaskController(DynamicTaskManager taskManager) {
this.taskManager = taskManager;
}
@PostMapping("/add")
public String addTask(@RequestBody TaskRequest request) {
taskManager.addTask(request.getTaskId(), request.getCron(),
request.getBeanName(), request.getMethodName());
return "任务添加成功: " + request.getTaskId();
}
@PostMapping("/update")
public String updateTask(@RequestBody TaskRequest request) {
taskManager.updateTask(request.getTaskId(), request.getCron(),
request.getBeanName(), request.getMethodName());
return "任务更新成功: " + request.getTaskId();
}
@DeleteMapping("/remove/{taskId}")
public String removeTask(@PathVariable String taskId) {
taskManager.removeTask(taskId);
return "任务删除成功: " + taskId;
}
@GetMapping("/list")
public Map<String, Boolean> listTasks() {
return taskManager.listTasks();
}
}
调试示例代码
添加任务(调用 MyTaskMethods.sendEmail(),每 5 秒执行一次)
POST http://localhost:8080/tasks/add
Content-Type: application/json
{
"taskId": "emailTask",
"cron": "*/5 * * * * *",
"beanName": "myTaskBean",
"methodName": "sendEmail"
}
更新任务(改成调用 cleanCache(),每 10 秒执行一次)
POST http://localhost:8080/tasks/update
Content-Type: application/json
{
"taskId": "emailTask",
"cron": "*/10 * * * * *",
"beanName": "myTaskBean",
"methodName": "cleanCache"
}
删除任务
DELETE http://localhost:8080/tasks/remove/emailTask
更多推荐



所有评论(0)