首先提供一个接口作为 开启关闭定时任务 因本地数据库嫌麻烦用redis暂时存一下模仿动态编辑执行时间
package com.dj.task;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
import java.util.concurrent.ScheduledFuture;
/**
* 定时任务自动/手动
*
* @author suliaodaidai
* @Date 2023/08/13 16:24
*/
@RestController
@RequestMapping("/daiDai/task")
@Slf4j
public class Test {
//官方提供接口 内涵可关闭的方法
private ScheduledFuture<?> future;
//注入Bean 用于调度定时任务 按照提供的schedule方法自定义
@Autowired
private ThreadPoolTaskScheduler threadPoolTaskScheduler;
//容器内需要有一个名为它的组件
@Bean
public ThreadPoolTaskScheduler threadPoolTaskScheduler(){
return new ThreadPoolTaskScheduler();
}
@Autowired
private StringRedisTemplate redisTemplate;
@RequestMapping("/open")
public String openTask(){
String s = "0/5 * * * * *";
String s1 = redisTemplate.opsForValue().get("corn");
future= threadPoolTaskScheduler.schedule(new MyTask(), new Trigger() {
@Override
public Date nextExecutionTime(TriggerContext triggerContext) {
return new CronTrigger(s1 == null ? s :s1).nextExecutionTime(triggerContext);
}
});
log.info("定时任务开启++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
if (s1!=null){
log.info("定时任务开启并且执行策略已更新最新效果++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
}
log.info("定时任务开启成功 正在等待运行定时任务 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
return "定时任务开始成功";
}
@RequestMapping("/close")
public String close(){
log.info("定时任务正在关闭中++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
if (future != null){
//fratrue 提供的方法 如应该终端则为 true 无定时任务是 应该不会执行此方法,但是不影响调用
future.cancel(true);
}else {
log.info("定时任务关闭失败++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
}
log.info("定时任务正在关闭成功++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
return "定时任务关闭成功";
}
@RequestMapping("/redisSet")
public String redisSetCorn(String corn){
//后续可使用正则验证
//或者存如数据库取出
redisTemplate.opsForValue().set("corn",corn);
if (future != null){
//修改了执行时间 ,正在重启定时任务服务
log.info("修改了执行时间,正在重启定时任务服务++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
future.cancel(true);
}
try {
openTask();
log.info("重启定时任务服务成功++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
}catch (Exception e){
return "服务异常请重试";
}
return "已修改缓存中的corn值 下一次开启定时任务时策略生效";
}
}
写了一个简单的打印 模拟要执行的任务 这里实现了Runnable接口不受Spring容器管理,需要手动注入bean找了一个第三方应用上下文工具类(实现了Runnable,用@Autowired 注入了redis为null导致空指针异常)
package com.dj.task;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @author suliaodaidai
*/
@Component
public class MyTask implements Runnable{
private StringRedisTemplate redisTemplate;
@Override
public void run() {
redisTemplate = SpringContextUtils.getApplicationContext().getBean(StringRedisTemplate.class);
String s = redisTemplate.opsForValue().get("corn");
// String s = (String)redisTemplate.opsForValue().get("corn");
String substring = s.substring(s.indexOf("/"), s.indexOf(" "));
// String substring = s == null ? "" : s.substring(2, 3);
System.out.println(substring +"秒执行一次" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
}
}
@Component
class SpringContextUtils implements ApplicationContextAware {
/**
* 应用上下文
*/
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringContextUtils.applicationContext = applicationContext;
}
public static ApplicationContext getApplicationContext(){
return applicationContext;
}
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) throws BeansException {
return (T)applicationContext.getBean(name);
}
public static <T> T getBean(Class<T> clz) throws BeansException {
return (T)applicationContext.getBean(clz);
}
}