方案一
1.实现SchedulingConfigurer 接口
import cn.hutool.core.date.LocalDateTimeUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
@Data
@Slf4j
@Component
@EnableScheduling
public class ScheduleTask implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
// 动态使用cron表达式设置循环间隔
//添加多个直接for循环即可
taskRegistrar.addTriggerTask(() -> {
//调用自己的定时任务
log.info("Current time: {}", LocalDateTimeUtil.formatNormal(LocalDateTime.now()));
}, (triggerContext) -> {
// 使用CronTrigger触发器,可动态修改cron表达式来操作循环规则
return new CronTrigger(Demo.cronMap.get("cron")).nextExecutionTime(triggerContext);
});
}
}
2.测试controller
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.HashMap;
import java.util.Map;
@Slf4j
@RequestMapping("/cpic/qwe")
@Controller
public class Demo implements InitializingBean{
public static Map<String,String> cronMap = new HashMap<>();
@Autowired
private ScheduleTask scheduleTask;
@GetMapping("updateTask")
public void start(){
System.out.println("修改定时任务表达式");
cronMap.put("cron","0/5 * * * * ?");
}
@Override
public void afterPropertiesSet() throws Exception {
//假设这部分是从mysql数据库读取
cronMap.put("cron","0/2 * * * * ?");
}
}
方案2
第一步继承ThreadPoolTaskScheduler
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.ScheduledMethodRunnable;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;
@Component
public class CustomTaskScheduler extends ThreadPoolTaskScheduler {
private Map<Object, ScheduledFuture<?>> scheduledTasks = new IdentityHashMap<>();
@Override
public ScheduledFuture<?> schedule(Runnable task, Trigger trigger) {
ScheduledFuture<?> future = super.schedule(task, trigger);
this.putScheduledTasks(task, future);
return future;
}
@Override
public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, long period) {
ScheduledFuture<?> future = super.scheduleAtFixedRate(task, period);
this.putScheduledTasks(task, future);
return future;
}
@Override
public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, Date startTime, long period) {
ScheduledFuture<?> future = super.scheduleAtFixedRate(task, startTime, period);
this.putScheduledTasks(task, future);
return future;
}
private void putScheduledTasks(Runnable task, ScheduledFuture<?> future) {
ScheduledMethodRunnable runnable = (ScheduledMethodRunnable) task;
scheduledTasks.put(runnable.getTarget(), future);
}
public Map<Object, ScheduledFuture<?>> getScheduledTasks() {
return scheduledTasks;
}
}
第二步
import cn.hutool.core.date.LocalDateTimeUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.scheduling.support.ScheduledMethodRunnable;
import org.springframework.stereotype.Controller;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import java.time.LocalDateTime;
@Slf4j
@RequestMapping("/cpic/qwe")
@Controller
public class Demo{
@Autowired
private CustomTaskScheduler customTaskScheduler;
@Autowired
private Demo demo;
@RequestMapping("close")
public void close(){
customTaskScheduler.getScheduledTasks().get(demo).cancel(true);
}
@RequestMapping("open")
public void open(){
ScheduledMethodRunnable runnable = new ScheduledMethodRunnable(demo, ReflectionUtils.findMethod(demo.getClass(), "taskTest"));
customTaskScheduler.schedule(runnable, new CronTrigger("*/5 * * * * *"));
}
@RequestMapping("open1")
public void open1(){
ScheduledMethodRunnable runnable = new ScheduledMethodRunnable(demo, ReflectionUtils.findMethod(demo.getClass(), "taskTest"));
customTaskScheduler.schedule(runnable, new CronTrigger("*/7 * * * * *"));
}
public void taskTest(){
System.out.println("测试定时任务:{}"+ LocalDateTimeUtil.formatNormal(LocalDateTime.now()));
}
public void taskTest1(){
System.out.println("测试定时任务1:{}"+ LocalDateTimeUtil.formatNormal(LocalDateTime.now()));
}
}
描述:方案二的缺点:暂时不支持一个类中存在多个定时任务,如果存在多个,去触发取消的时候
只能取消掉最后一个定时任务