SpringBoot-动态定时任务调度

2023年2月8日13:26:39

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

  • 作者:如约而至的重逢
  • 原文链接:https://blog.csdn.net/bbscz007/article/details/111695289
    更新时间:2023年2月8日13:26:39 ,共 4176 字。