spring 不停止服务 动态修改定时任务schedul

包含两种方式

一、方法一 ,复杂一点,但是可以保证设置完实时生效

/**
 * 向springIOC中注入一个定时任务线程池备用
 * @author WXM
 * @date 2022/07/19
 */

@Configuration
public class ScheduledConfig {
    @Bean
    public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
        ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
        threadPoolTaskScheduler.setPoolSize(3);
        threadPoolTaskScheduler.setRemoveOnCancelPolicy(true);
        return threadPoolTaskScheduler;
    }
}
/**
 * 自定义一个实体类方便存储任务参数
 * @author WXM
 * @date 2022/07/19
 */

public class ScheduledFutureHolder {
   private ScheduledFuture<?> scheduledFuture;

    private Runnable task;

    private String corn;

    public ScheduledFuture<?> getScheduledFuture() {
        return scheduledFuture;
    }

    public void setScheduledFuture(ScheduledFuture<?> scheduledFuture) {
        this.scheduledFuture = scheduledFuture;
    }

    public String getCorn() {
        return corn;
    }

    public void setCorn(String corn) {
        this.corn = corn;
    }

    public Runnable getTask() {
        return task;
    }

    public void setTask(Runnable task) {
        this.task = task;
    }

    @Override
    public String toString() {
        return "ScheduledFutureHolder{" +
                "scheduledFuture=" + scheduledFuture +
                ", task=" + task +
                ", corn='" + corn + '\'' +
                '}';
    }
}
/**
 * 具体任务执行代码,可以根据业务场景定义多个
 * @author WXM
 * @date 2022/07/19
 */

public class DatabaseBackupTask implements Runnable {

    @Override
    public void run() {
        System.out.println(new Date()+"定时任务执行............");
    }
}


@Component
public class ScheduleUtil {
    @Autowired
    private ThreadPoolTaskScheduler threadPoolTaskScheduler;

    //存储任务执行的包装类
    private HashMap<String, ScheduledFutureHolder> scheduleMap = new HashMap<>();

    /**
     *启动任务 
     * 如果不想手动触发任务可以使用 @PostConstruct注解来启动
     */
   public void startTask(Runnable task, String cron) {
        String taskName = task.getClass().getName();
        try {
            // 判断当前任务是否已经在计划列表,在的话不再重复加载
            if (scheduleMap.containsKey(taskName)) {
                logger.info("当前任务已存在,不再重复加载。如需修改任务执行间隔,请调用restart接口");
                return;
            }
            // 将任务交给任务调度器执行
            ScheduledFuture<?> schedule = threadPoolTaskScheduler.schedule(task, new CronTrigger(cron));
            // 将任务包装成ScheduledFutureHolder
            ScheduledFutureHolder scheduledFutureHolder = new ScheduledFutureHolder();
            scheduledFutureHolder.setScheduledFuture(schedule);
            scheduledFutureHolder.setTask(task);
            scheduledFutureHolder.setCorn(cron);
            scheduleMap.put(scheduledFutureHolder.getTask().getClass().getName(), scheduledFutureHolder);
            logger.info("定时任务启动成功,任务名:[{}],cron:[{}]", taskName, cron);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 查询所有的任务
     */
    @RequestMapping("/queryTask")
    public void queryTask(){
        scheduleMap.forEach((k,v)->{
            System.out.println(k+"  "+v);
        });
    }

    /**
     * 停止任务
     * @param className
     */
    @RequestMapping("/stop/{className}")
    public void stopTask(@PathVariable  String className){
        if(scheduleMap.containsKey(className)){//如果包含这个任务
            ScheduledFuture<?> scheduledFuture = scheduleMap.get(className).getScheduledFuture();
            if(scheduledFuture!=null){
                scheduledFuture.cancel(true);
            }
        }
    }


    /**
     * 重启任务,修改任务的触发时间
     * @param className
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
   public void restartTask(String taskName, String cron) {
        if (scheduleMap.containsKey(taskName)) {//如果包含这个任务
            ScheduledFutureHolder scheduledFutureHolder = scheduleMap.get(taskName);
            ScheduledFuture<?> scheduledFuture = scheduledFutureHolder.getScheduledFuture();
            if (scheduledFuture != null) {
                // 先停掉任务
                scheduledFuture.cancel(true);
                // 修改触发时间重新启动任务
                Runnable runnable = scheduledFutureHolder.getTask();
                ScheduledFuture<?> schedule = threadPoolTaskScheduler.schedule(runnable, new CronTrigger(cron));
                scheduledFutureHolder.setScheduledFuture(schedule);
                scheduledFutureHolder.setCorn(cron);
                scheduleMap.put(scheduledFutureHolder.getTask().getClass().getName(), scheduledFutureHolder);
                logger.info("定时任务重新配置成功成功,任务名:[{}],cron:[{}]", taskName, cron);
            }
        }
    }
}

二、方法二 ,代码相对简单,但是设置的cron只有在下次定时任务执行时才会触发(不能设置完实时触发)

/**
 * @author WXM
 * @date 2022/07/19
 */

@Lazy(false)
@Component
@EnableScheduling
public class SpringDynamicCornTask implements SchedulingConfigurer {
    private static final Logger logger = LoggerFactory.getLogger(SpringDynamicCornTask.class);
    private static String cron = "* * * 31 2 ?";
    public SpringDynamicCornTask() {
    }

    public void setCron(String cron) {
        this.cron = cron;
    }

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.addTriggerTask(new Runnable() {

            @Override
            public void run() {
                // 任务逻辑
                logger.info("定时任务进行中...");
            }
        }, new Trigger() {

            @Override
            public Date nextExecutionTime(TriggerContext triggerContext) {
                // 任务触发,可修改任务的执行周期
                CronTrigger trigger = new CronTrigger(cron);
                Date nextExecutionTime = trigger.nextExecutionTime(triggerContext);
                return nextExecutionTime;
            }
        });
    }
}
// controller层


@GetMapping ("changeScheduled")
    public String changeScheduled(String cron){
        springDynamicCornTask.setCron(cron);
        return "suc";
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值