SpringBoot-动态定时任务调度

一、业务场景

先说业务场景,根据用户输入的cron表达式进行定时调度,举个例子:如图

SpringBoot-动态定时任务调度

根据用户输入的参数,生成表达式,然后定时去执行相应的业务逻辑。

二、Controller层(不是重点)

domain类

@TableName("sys_schedule") @Data public class Schedule {      private static final long serialVersionUID = 1L;      /**      * 主键ID      */     @TableId(value = "id", type = IdType.AUTO)     private Long id;      /**      * 类型: 时间, 周, 日      */     @TableField("type")     private Integer type;      /**      * time 时间      */     @TableField("day_time")     private String dayTime;      /**      * time 周      */     @TableField("weekday")     private String weekday;      /**      * time 日      */     @TableField("monthday")     private String monthday;      /**      * 选中状态      */     @TableField("status")     private Integer status;      @TableField("cron")     private String cron;      @Override     public String toString() {         return "Schedule{" +                 "id=" + id +                 ", type=" + type +                 ", dayTime='" + dayTime + '\'' +                 ", weekday='" + weekday + '\'' +                 ", monthday='" + monthday + '\'' +                 ", status=" + status +                 ", cron='" + cron + '\'' +                 '}';     } } 

controller方法

	 	@Autowired     private ScheduleService scheduleService; 	  	@PutMapping("/editItem")     @ResponseBody     public ResponseData editItem(Schedule schedule) {         //ResponseData自己封装的响应结果         //param是你前端传的,包含你的数据,如cron表达式         this.scheduleService.update(schedule);         return ResponseData.success();     } 

三、Service层

接口层

public interface ScheduleService {      /**      * 更新      * @Date 2020-12-25      */     void update(Schedule param);      /**      * 业务处理      * @Date 2020-12-25      */     void work();  } 

实现层

@Service public class ScheduleServiceImpl implements ScheduleService {      	@Override     public void update(Schedule param) { 		//这里简化了我自己的业务逻辑代码,根据公司自己需要来写即可         //业务逻辑代码                  //思路就是:更新数据库的cron,类型等值,然后交给下面的定时工具类走定时方法         this.scheduleMapper.updateById(param);         String cron = param.getCron();         //this就是你的业务执行service, 这里就是scheduleService         ScheduleUtil.reset(new ScheduleTask(param.getId().toString(), this, null), cron);     }          @Override     public void work() {         //抓取数据的代码         System.out.println("业务代码执行。。。");     }       } 	 

四、定时工具类

import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.scheduling.support.CronTrigger;  import java.util.HashMap; import java.util.Map; import java.util.concurrent.ScheduledFuture;  public class ScheduleUtil {      private static ThreadPoolTaskScheduler threadPoolTaskScheduler = new 			ThreadPoolTaskScheduler();     private static Map<String, ScheduledFuture<?>> scheduledFutureMap = new HashMap<>();      static {         threadPoolTaskScheduler.initialize();         System.out.println("定时任务线程池启动");     }      /**      * 启动      *      * @param scheduleTask 定时任务      * @param corn         执行时间表达式      */     public static boolean start(ScheduleTask scheduleTask, String corn) {         System.out.println("启动定时任务线程 taskId " + scheduleTask.getId());         ScheduledFuture<?> scheduledFuture = threadPoolTaskScheduler                 .schedule(scheduleTask, new CronTrigger(corn));         scheduledFutureMap.put(scheduleTask.getId(), scheduledFuture);         return true;     }      /**      * 取消      *      * @param scheduleTask 定时任务      */     public static boolean cancel(ScheduleTask scheduleTask) {         System.out.println("关闭定时任务线程 taskId " + scheduleTask.getId());         ScheduledFuture<?> scheduledFuture = 			 	 scheduledFutureMap.get(scheduleTask.getId());         if (scheduledFuture != null && !scheduledFuture.isCancelled()) {             scheduledFuture.cancel(false);         }         scheduledFutureMap.remove(scheduleTask.getId());         return true;     }      /**      * 修改      *      * @param scheduleTask 定时任务      * @param corn         执行时间表达式      */     public static boolean reset(ScheduleTask scheduleTask, String corn) {         //先取消定时任务         cancel(scheduleTask);         //然后启动新的定时任务         start(scheduleTask, corn);         return true;     } } 

五、工作线程

 public class ScheduleTask implements Runnable {      private static final int TIMEOUT = 30000;      private String id;     private ScheduleService service;      public String getId() {         return id;     }      /**      * @param id      任务ID      * @param service 业务类      * @param keyword 关键字参数      */     public ScheduleTask(String id, ScheduleService service) {         this.id = id;         this.service = service;     }      @Override     public void run() {         //你自己的业务逻辑         service.work();     } } 

到这里结束了,这里主要是根据前台传的时间,进行生成cron,入库,执行定时任务。但是有一个问题,就是如果项目重启了的话,那么定时类那是无法加载到cron表达式的。那么接下来,加一个项目启动时,把数据库里的cron表达式重新灌入到定时类就可以。代码如下:

import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component;  /**  * 项目启动时,加载  * @Date: 2020/12/25:16:00  **/ @Component @Order(1) public class initLineRunner implements CommandLineRunner {      @Autowired     private ScheduleService scheduleService;      @Override     public void run(String... args) throws Exception {         System.out.println("init ........... ");         //这里就是获取你数据库里的那个cron表达式         Schedule param = scheduleService.get();         String cron = param.getCron();         ScheduleUtil.reset(new ScheduleTask(param.getId().toString(), scheduleService, null), cron);     } } 

参考文章:https://blog.csdn.net/qq_37334435/article/details/107996095