关于使用quartz动态增删改定时任务
1. 首先, 还是喜闻乐见的导包
1 <dependency> 2 <groupId>org.springframework.boot</groupId> 3 <artifactId>spring-boot-starter-quartz</artifactId> 4 </dependency>
2. 处理schedule工具
1 package com.hoolink.schedule.util; 2 3 import com.hoolink.sdk.bo.device.ScreenPlayScheduleBO; 4 import com.hoolink.sdk.utils.JSONUtils; 5 import lombok.extern.slf4j.Slf4j; 6 import org.apache.commons.collections.CollectionUtils; 7 import org.quartz.*; 8 9 import java.time.LocalDate; 10 import java.util.List; 11 12 /** 13 * @author <a herf="mailto:yanwu0527@163.com">XuBaofeng</a> 14 * @date 2019-05-31 17:29. 15 * <p> 16 * description: 17 * DisallowConcurrentExecution: 不允许并发执行 18 */ 19 @Slf4j 20 @DisallowConcurrentExecution 21 public class ScreenPlayUtil { 22 23 /** 24 * 批量创建定时任务 25 * 26 * @param scheduler 27 * @param screens 28 */ 29 public static void createAll(Scheduler scheduler, List<ScreenPlayScheduleBO> screens) { 30 if (CollectionUtils.isEmpty(screens)) { 31 return; 32 } 33 screens.forEach(screen -> { 34 createJob(scheduler, screen); 35 }); 36 } 37 38 /** 39 * 添加一个定时任务 40 * 41 * @param scheduler 调度器 42 * @param screen 任务 43 */ 44 public static void createJob(Scheduler scheduler, ScreenPlayScheduleBO screen) { 45 try { 46 log.info("create job, time: {}, screen: {}", LocalDate.now(), screen); 47 Class<? extends Job> clazz = (Class<? extends Job>) Class.forName(screen.getClassName()); 48 JobDataMap jobDataMap = new JobDataMap(JSONUtils.stringToMap(JSONUtils.toJSONString(screen))); 49 // 任务名,任务组,任务执行类 50 JobDetail jobDetail = JobBuilder.newJob(clazz).withIdentity(screen.getJobName(), screen.getJobGroup()) 51 .withDescription("定时任务").setJobData(jobDataMap).build(); 52 // 触发器名,触发器组 53 CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(screen.getCronExpression()) 54 .withMisfireHandlingInstructionDoNothing(); 55 CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(screen.getTriggerName(), screen.getTriggerGroup()) 56 .withDescription(screen.getDescription()).withSchedule(scheduleBuilder).startNow().build(); 57 // 触发器时间设定 58 scheduler.scheduleJob(jobDetail, trigger); 59 // 启动 60 if (!scheduler.isShutdown()) { 61 startJobs(scheduler); 62 } 63 } catch (Exception e) { 64 log.error("create schedule job error", e); 65 } 66 } 67 68 /** 69 * 批量更新定时任务 70 * 71 * @param scheduler 72 * @param screens 73 */ 74 public static void updateAll(Scheduler scheduler, List<ScreenPlayScheduleBO> screens) { 75 if (CollectionUtils.isEmpty(screens)) { 76 return; 77 } 78 screens.forEach(screen -> { 79 updateJob(scheduler, screen); 80 }); 81 } 82 83 /** 84 * 修改一个任务的触发时间 85 * 86 * @param scheduler 87 * @param screen 88 */ 89 public static void updateJob(Scheduler scheduler, ScreenPlayScheduleBO screen) { 90 try { 91 log.info("update job, time: {}, screen:{}", LocalDate.now(), screen); 92 TriggerKey triggerKey = new TriggerKey(screen.getTriggerName(), screen.getTriggerGroup()); 93 CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey); 94 if (trigger == null) { 95 createJob(scheduler, screen); 96 return; 97 } 98 String cron = trigger.getCronExpression(); 99 if (!cron.equalsIgnoreCase(screen.getCronExpression())) { 100 removeJob(scheduler, screen); 101 createJob(scheduler, screen); 102 } 103 } catch (Exception e) { 104 log.error("update schedule job error", e); 105 } 106 } 107 108 /** 109 * 清除所有的定时任务 110 * 111 * @param scheduler 112 */ 113 public static void removeAll(Scheduler scheduler) { 114 try { 115 log.info("remove all schedule job, time: {}", LocalDate.now()); 116 scheduler.clear(); 117 } catch (Exception e) { 118 log.error("remove all schedule job error.", e); 119 } 120 } 121 122 /** 123 * 批量清除指定的定时任务 124 * 125 * @param scheduler 126 */ 127 public static void removeAll(Scheduler scheduler, List<ScreenPlayScheduleBO> screens) { 128 if (CollectionUtils.isEmpty(screens)) { 129 return; 130 } 131 screens.forEach(screen -> { 132 removeJob(scheduler, screen); 133 }); 134 } 135 136 /** 137 * 移除一个任务 138 * 139 * @param scheduler 140 * @param screen 141 */ 142 public static void removeJob(Scheduler scheduler, ScreenPlayScheduleBO screen) { 143 try { 144 log.info("remove job, time: {}, screen:{}", LocalDate.now(), screen); 145 JobKey jobKey = new JobKey(screen.getJobName(), screen.getJobGroup()); 146 TriggerKey triggerKey = new TriggerKey(screen.getTriggerName(), screen.getTriggerGroup()); 147 // 停止触发器 148 scheduler.pauseTrigger(triggerKey); 149 // 移除触发器 150 scheduler.unscheduleJob(triggerKey); 151 // 删除任务 152 scheduler.deleteJob(jobKey); 153 } catch (Exception e) { 154 log.error("remove schedule job error", e); 155 } 156 } 157 158 /** 159 * 启动所有定时任务 160 * 161 * @param scheduler 调度器 162 */ 163 public static void startJobs(Scheduler scheduler) { 164 try { 165 log.info("start schedule job, time: {}", LocalDate.now()); 166 scheduler.start(); 167 } catch (Exception e) { 168 log.error("start schedule job error", e); 169 } 170 } 171 172 /** 173 * 关闭所有定时任务 174 * 175 * @param scheduler 调度器 176 */ 177 public static void shutdownJobs(Scheduler scheduler) { 178 try { 179 log.info("shutdown schedule job, time: {}", LocalDate.now()); 180 if (!scheduler.isShutdown()) { 181 scheduler.shutdown(); 182 } 183 } catch (Exception e) { 184 log.error("shutdown schedule job error", e); 185 } 186 } 187 188 }
3. BO
1 package com.hoolink.sdk.bo.device; 2 3 import lombok.Data; 4 5 import java.io.Serializable; 6 7 /** 8 * @author <a herf="mailto:yanwu0527@163.com">XuBaofeng</a> 9 * @date 2019-05-31 17:31. 10 * <p> 11 * description: 12 */ 13 @Data 14 public class ScreenPlayScheduleBO implements Serializable { 15 private static final long serialVersionUID = 4226193119686522141L; 16 17 private Long configId; 18 19 /*** 执行任务的类名称 */ 20 private String className; 21 22 /*** 定时任务表达式 */ 23 private String cronExpression; 24 25 /*** 任务名称 */ 26 private String jobName; 27 28 /*** 任务分组 */ 29 private String jobGroup; 30 31 /*** 触发器名称 */ 32 private String triggerName; 33 34 /*** 触发器分组 */ 35 private String triggerGroup; 36 37 /*** 任务描述 */ 38 private String description; 39 40 /*** 创建时间 */ 41 private Long createTime; 42 43 /*** 定时任务任务ID */ 44 private Long playId; 45 46 /*** 开启\关闭(0:关闭;1:开启) */ 47 private Boolean playStatus; 48 }
5. 处理定时任务
1 package com.hoolink.schedule.job; 2 3 import com.hoolink.schedule.consumer.ScreenClient; 4 import com.hoolink.sdk.bo.device.ScreenPlayScheduleBO; 5 import com.hoolink.sdk.utils.JSONUtils; 6 import lombok.extern.slf4j.Slf4j; 7 import org.apache.servicecomb.foundation.common.utils.BeanUtils; 8 import org.quartz.Job; 9 import org.quartz.JobDataMap; 10 import org.quartz.JobExecutionContext; 11 import org.quartz.JobExecutionException; 12 13 import java.time.LocalDateTime; 14 15 /** 16 * @author <a herf="mailto:yanwu0527@163.com">XuBaofeng</a> 17 * @date 2019-05-31 17:29. 18 * <p> 19 * description: 20 * DisallowConcurrentExecution: 不允许并发执行 21 */ 22 @Slf4j 23 @DisallowConcurrentExecution 24 public class ScreenPlayJob implements Job { 25 26 @Override 27 public void execute(JobExecutionContext context) throws JobExecutionException { 28 JobDataMap jobDataMap = context.getMergedJobDataMap(); 29 ScreenPlayScheduleBO mediaTaskBO = JSONUtils.parse(JSONUtils.toJSONString(jobDataMap), ScreenPlayScheduleBO.class); 30 log.info("screen play control job start, time: {} param: {}", LocalDateTime.now(), mediaTaskBO); 31 ScreenClient screenClient = BeanUtils.getContext().getBean(ScreenClient.class); 32 screenClient.playControl(mediaTaskBO); 33 } 34 35 }
6. 调用schedule工具
1 package com.hoolink.schedule.controller; 2 3 import com.hoolink.schedule.util.ScreenPlayUtil; 4 import com.hoolink.sdk.annotation.LogAndParam; 5 import com.hoolink.sdk.bo.BackBO; 6 import com.hoolink.sdk.bo.device.ScreenPlayScheduleBO; 7 import com.hoolink.sdk.utils.BackBOUtil; 8 import io.swagger.annotations.ApiOperation; 9 import org.apache.servicecomb.provider.rest.common.RestSchema; 10 import org.quartz.Scheduler; 11 import org.springframework.beans.factory.annotation.Autowired; 12 import org.springframework.web.bind.annotation.PostMapping; 13 import org.springframework.web.bind.annotation.RequestBody; 14 import org.springframework.web.bind.annotation.RequestMapping; 15 import org.springframework.web.bind.annotation.RestController; 16 17 import java.util.List; 18 19 /** 20 * @author <a herf="mailto:yanwu0527@163.com">XuBaofeng</a> 21 * @date 2019-06-01 14:59. 22 * <p> 23 * description: 24 */ 25 @RestController 26 @RequestMapping("/screen/play/") 27 @RestSchema(schemaId = "screenPlayController") 28 public class ScreenPlayController { 29 @Autowired 30 private Scheduler scheduler; 31 32 @PostMapping(value = "create") 33 @ApiOperation(value = "创建定时任务") 34 @LogAndParam(value = "创建定时任务失败") 35 public BackBO<Void> create(@RequestBody ScreenPlayScheduleBO screen) { 36 ScreenPlayUtil.createJob(scheduler, screen); 37 return BackBOUtil.defaultBackBO(); 38 } 39 40 @PostMapping(value = "createAll") 41 @ApiOperation(value = "批量创建定时任务") 42 @LogAndParam(value = "批量定时任务失败") 43 public BackBO<Void> createAll(@RequestBody List<ScreenPlayScheduleBO> screens) { 44 ScreenPlayUtil.createAll(scheduler, screens); 45 return BackBOUtil.defaultBackBO(); 46 } 47 48 @PostMapping(value = "update") 49 @ApiOperation(value = "更新定时任务") 50 @LogAndParam(value = "更新定时任务失败") 51 public BackBO<Void> update(@RequestBody ScreenPlayScheduleBO screen) { 52 ScreenPlayUtil.updateJob(scheduler, screen); 53 return BackBOUtil.defaultBackBO(); 54 } 55 56 @PostMapping(value = "updateAll") 57 @ApiOperation(value = "更新定时任务") 58 @LogAndParam(value = "更新定时任务失败") 59 public BackBO<Void> updateAll(@RequestBody List<ScreenPlayScheduleBO> screens) { 60 ScreenPlayUtil.updateAll(scheduler, screens); 61 return BackBOUtil.defaultBackBO(); 62 } 63 64 @PostMapping(value = "remove") 65 @ApiOperation(value = "删除定时任务") 66 @LogAndParam(value = "删除定时任务失败") 67 public BackBO<Void> remove(@RequestBody ScreenPlayScheduleBO screen) { 68 ScreenPlayUtil.removeJob(scheduler, screen); 69 return BackBOUtil.defaultBackBO(); 70 } 71 72 @PostMapping(value = "deleteAll") 73 @ApiOperation(value = "清除所有的定时任务") 74 @LogAndParam(value = "清除所有的定时任务失败") 75 public BackBO<Void> deleteAll() { 76 ScreenPlayUtil.removeAll(scheduler); 77 return BackBOUtil.defaultBackBO(); 78 } 79 80 @PostMapping(value = "removeAll") 81 @ApiOperation(value = "清除所有的定时任务") 82 @LogAndParam(value = "清除所有的定时任务失败") 83 public BackBO<Void> removeAll(@RequestBody List<ScreenPlayScheduleBO> screens) { 84 ScreenPlayUtil.removeAll(scheduler, screens); 85 return BackBOUtil.defaultBackBO(); 86 } 87 88 }