先说业务场景,根据用户输入的cron表达式进行定时调度,举个例子:如图
根据用户输入的参数,生成表达式,然后定时去执行相应的业务逻辑。
@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 + '\'' + '}'; } }
@Autowired private ScheduleService scheduleService; @PutMapping("/editItem") @ResponseBody public ResponseData editItem(Schedule schedule) { //ResponseData自己封装的响应结果 //param是你前端传的,包含你的数据,如cron表达式 this.scheduleService.update(schedule); return ResponseData.success(); }
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