SpringBoot整合Quartz實現(xiàn)動態(tài)配置的代碼示例
Spring Boot整合Quartz
簡單說下Quartz的整合,做一下準備工作。
導入Quartz依賴
<!--Quartz定時任務--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-quartz</artifactId> </dependency>
配置文件中增加Quartz的支持
spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: xxx username: xxx password: xxx quartz: job-store-type: jdbc # 定時任務的數(shù)據(jù)保存到jdbc即數(shù)據(jù)庫中 jdbc: # embedded:默認 # always:啟動的時候初始化表,我們只在第一次啟動的時候用它來自動創(chuàng)建表,然后改回embedded即可,不然數(shù)據(jù)每次都會被清空 # never:啟動的時候不初始化表,也不知道和embedded有什么不同 initialize-schema: embedded
第一次啟動的時候請把上面的initialize-schema設置為always,這會在數(shù)據(jù)庫里面自動建表,然后第二次啟動時改回embedded即可。
如果不需要定時任務的持久化就可以不管。
寫一個測試用的任務類
import org.quartz.JobExecutionException; import org.springframework.scheduling.quartz.QuartzJobBean; import org.springframework.stereotype.Component; @Component public class QuartzTestJob extends QuartzJobBean { @Override protected void executeInternal(org.quartz.JobExecutionContext jobExecutionContext) throws JobExecutionException { System.out.println("Quartz Test Job"); } }
為這個任務類寫一個配置類
import org.quartz.*; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class QuartzTestJobConfig { @Bean public JobDetail quartzTestJobDetail() { return JobBuilder.newJob(QuartzTestJob.class) .withIdentity(QuartzTestJob.class.getSimpleName()) .storeDurably() .usingJobData("data", "test") .build(); } @Bean public Trigger quartzTestJobTrigger() { // 0/1 * * * * ? return TriggerBuilder.newTrigger() .forJob(QuartzTestJob.class.getSimpleName()) .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(1).repeatForever()) .build(); } }
結論
以上是使用Quartz寫一個定時任務的步驟,很簡單,問題是配置寫死了,沒有辦法動態(tài)調整,所以我們開始寫接口,把上面這個任務配置類去掉。
定時任務動態(tài)配置實現(xiàn)
我們還是用上面的任務類QuartzTestJob做測試,這里再說明一次,我們需要有一個任務類作為基礎,本文的目的只是去掉上面的QuartzTestJobConfig。
剩下的內容沒有什么需要多說明的,我直接貼代碼了。
業(yè)務層
public interface QuartzService { /** * 添加定時任務 */ void addJob(QuartzCreateParam param) throws SchedulerException; /** * 修改定時任務 */ void updateJob(QuartzUpdateParam param) throws SchedulerException; /** * 暫停定時任務 */ void pauseJob(QuartzDetailParam param) throws SchedulerException; /** * 恢復定時任務 */ void resumeJob(QuartzDetailParam param) throws SchedulerException; /** * 刪除定時任務 */ void deleteJob(QuartzDetailParam param) throws SchedulerException; /** * 定時任務列表 * @return */ List<QuartzJobDetailDto> jobList() throws SchedulerException; /** * 定時任務詳情 */ QuartzJobDetailDto jobDetail(QuartzDetailParam param) throws SchedulerException; }
業(yè)務層實現(xiàn)
@Service public class QuartzServiceImpl implements QuartzService { @Autowired private Scheduler scheduler; @Autowired private SchedulerFactoryBean schedulerFactoryBean; @Override public void addJob(QuartzCreateParam param) throws SchedulerException { String clazzName = param.getJobClazz(); String jobName = param.getJobName(); String jobGroup = param.getJobGroup(); String cron = param.getCron(); String description = param.getDescription(); JobKey jobKey = JobKey.jobKey(jobName, jobGroup); checkJobExist(jobKey); Class<? extends Job> jobClass = null; try { jobClass = (Class<? extends Job>) Class.forName(clazzName); } catch (ClassNotFoundException e) { throw new BaseException("找不到任務類:" + clazzName); } JobDataMap jobDataMap = new JobDataMap(); if (param.getJobDataMap() != null) { param.getJobDataMap().forEach(jobDataMap::put); } Scheduler scheduler = schedulerFactoryBean.getScheduler(); JobDetail jobDetail = JobBuilder.newJob(jobClass) .withIdentity(jobName, jobGroup) .usingJobData(jobDataMap) .build(); CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cron); String triggerId = jobKey.getGroup() + jobKey.getName(); Trigger trigger = TriggerBuilder.newTrigger() .withSchedule(scheduleBuilder) .withIdentity(triggerId) .withDescription(description) .build(); scheduler.scheduleJob(jobDetail, trigger); if (!scheduler.isShutdown()) { scheduler.start(); } } @Override public void updateJob(QuartzUpdateParam param) throws SchedulerException { String jobName = param.getJobName(); String jobGroup = param.getJobGroup(); String cron = param.getCron(); JobKey jobKey = JobKey.jobKey(jobName, jobGroup); String triggerId = jobKey.getGroup() + jobKey.getName(); checkJobExist(jobKey); TriggerKey triggerKey = TriggerKey.triggerKey(triggerId); CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cron); TriggerBuilder<?> triggerBuilder = TriggerBuilder.newTrigger() .withSchedule(scheduleBuilder) .withIdentity(triggerId); Trigger trigger = triggerBuilder.build(); scheduler.rescheduleJob(triggerKey, trigger); } @Override public void pauseJob(QuartzDetailParam param) throws SchedulerException { String jobName = param.getJobName(); String jobGroup = param.getJobGroup(); JobKey jobKey = JobKey.jobKey(jobName, jobGroup); checkJobExist(jobKey); scheduler.pauseJob(jobKey); } @Override public void resumeJob(QuartzDetailParam param) throws SchedulerException { String jobName = param.getJobName(); String jobGroup = param.getJobGroup(); JobKey jobKey = JobKey.jobKey(jobName, jobGroup); checkJobExist(jobKey); scheduler.resumeJob(jobKey); } @Override public void deleteJob(QuartzDetailParam param) throws SchedulerException { String jobName = param.getJobName(); String jobGroup = param.getJobGroup(); JobKey jobKey = JobKey.jobKey(jobName, jobGroup); checkJobExist(jobKey); // 先暫停再刪除 scheduler.pauseJob(jobKey); scheduler.deleteJob(jobKey); } @Override public List<QuartzJobDetailDto> jobList() throws SchedulerException { GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup(); List<QuartzJobDetailDto> jobDtoList = new ArrayList<>(); for (JobKey jobKey : scheduler.getJobKeys(matcher)) { QuartzJobDetailDto jobDto = getJobDtoByJobKey(jobKey); jobDtoList.add(jobDto); } return jobDtoList; } @Override public QuartzJobDetailDto jobDetail(QuartzDetailParam param) throws SchedulerException { String jobName = param.getJobName(); String jobGroup = param.getJobGroup(); JobKey jobKey = JobKey.jobKey(jobName, jobGroup); return getJobDtoByJobKey(jobKey); } /*************** 私有方法 ***************/ private void checkJobExist(JobKey jobKey) throws SchedulerException { if (!scheduler.checkExists(jobKey)) { throw new BaseException("該定時任務不存在:" + jobKey.getName()); } } public QuartzJobDetailDto getJobDtoByJobKey(JobKey jobKey) throws SchedulerException { JobDetail jobDetail = scheduler.getJobDetail(jobKey); List<Trigger> triggerList = (List<Trigger>) scheduler.getTriggersOfJob(jobKey); QuartzJobDetailDto jobDto = new QuartzJobDetailDto(); jobDto.setJobClazz(jobDetail.getJobClass().toString()); jobDto.setJobName(jobKey.getName()); jobDto.setJobGroup(jobKey.getGroup()); jobDto.setJobDataMap(jobDetail.getJobDataMap()); List<QuartzTriggerDetailDto> triggerDtoList = new ArrayList<>(); for (Trigger trigger : triggerList) { QuartzTriggerDetailDto triggerDto = new QuartzTriggerDetailDto(); triggerDto.setTriggerName(trigger.getKey().getName()); triggerDto.setTriggerGroup(trigger.getKey().getGroup()); triggerDto.setDescription(trigger.getDescription()); if (trigger instanceof CronTriggerImpl) { CronTriggerImpl cronTriggerImpl = (CronTriggerImpl) trigger; String cronExpression = cronTriggerImpl.getCronExpression(); triggerDto.setCron(cronExpression); // 最近10次的觸發(fā)時間 List<Date> dates = TriggerUtils.computeFireTimes(cronTriggerImpl, null, 10); triggerDto.setRecentFireTimeList(dates); } Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey()); triggerDto.setTriggerState(triggerState.toString()); triggerDtoList.add(triggerDto); } jobDto.setTriggerDetailDtoList(triggerDtoList); return jobDto; } }
接口層
@RestController public class QuartzController { @Autowired private QuartzServiceImpl quartzService; @PostMapping("/quartz/addJob") public void addJob(@RequestBody QuartzCreateParam param) throws SchedulerException { quartzService.addJob(param); } @PostMapping("/quartz/updateJob") public void updateJob(@RequestBody QuartzUpdateParam param) throws SchedulerException { quartzService.updateJob(param); } @PostMapping("/quartz/pauseJob") public void pauseJob(@RequestBody QuartzDetailParam param) throws SchedulerException { quartzService.pauseJob(param); } @PostMapping("/quartz/resumeJob") public void resumeJob(@RequestBody QuartzDetailParam param) throws SchedulerException { quartzService.resumeJob(param); } @PostMapping("/quartz/deleteJob") public void deleteJob(@RequestBody QuartzDetailParam param) throws SchedulerException { quartzService.deleteJob(param); } @PostMapping("/quartz/jobList") public List<QuartzJobDetailDto> jobList() throws SchedulerException { return quartzService.jobList(); } @PostMapping("/quartz/jobDetail") public QuartzJobDetailDto jobDetail(@RequestBody QuartzDetailParam param) throws SchedulerException { return quartzService.jobDetail(param); } }
接口請求參數(shù)
@ApiModel(value = "Quartz任務添加請求參數(shù)") public class QuartzCreateParam extends BaseParam { @NotBlank(message = "任務類不能為空") @ApiModelProperty(value = "任務類路徑", required = true) private String jobClazz; @NotBlank(message = "任務類名不能為空") @ApiModelProperty(value = "任務類名", required = true) private String jobName; /** * 組名+任務類key組成唯一標識,所以如果這個參數(shù)為空,那么默認以任務類key作為組名 */ @ApiModelProperty(value = "任務組名,命名空間") private String jobGroup; @ApiModelProperty(value = "任務數(shù)據(jù)") private Map<String, Object> jobDataMap; @ApiModelProperty(value = "cron表達式") private String cron; @ApiModelProperty(value = "描述") private String description; }
@ApiModel(value = "Quartz任務更新請求參數(shù)") public class QuartzUpdateParam extends BaseParam { @NotBlank(message = "任務類名不能為空") @ApiModelProperty(value = "任務類名", required = true) private String jobName; @ApiModelProperty(value = "任務組名,命名空間") private String jobGroup; @ApiModelProperty(value = "cron表達式") private String cron; }
@ApiModel(value = "Quartz任務詳情請求參數(shù)") public class QuartzDetailParam extends BaseParam { @NotBlank(message = "任務類名不能為空") @ApiModelProperty(value = "任務類名", required = true) private String jobName; @ApiModelProperty(value = "任務組名,命名空間") private String jobGroup; }
接口返回結果類
@ApiModel(value = "Quartz定時任務詳情類") public class QuartzJobDetailDto { @ApiModelProperty(value = "任務類路徑") private String jobClazz; @ApiModelProperty(value = "任務類名") private String jobName; @ApiModelProperty(value = "任務組名,命名空間") private String jobGroup; @ApiModelProperty(value = "任務數(shù)據(jù)") private Map<String, Object> jobDataMap; @ApiModelProperty(value = "觸發(fā)器列表") private List<QuartzTriggerDetailDto> triggerDetailDtoList; }
@ApiModel(value = "Quartz定時任務觸發(fā)器詳情類") public class QuartzTriggerDetailDto { private String triggerName; private String triggerGroup; private String cron; private String description; private String triggerState; @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private List<Date> recentFireTimeList; }
調用接口進行測試
寫完接口代碼后,我們來測試一下
添加任務接口:/quartz/addJob
{ "jobClazz": "com.cc.job.QuartzTestJob", "jobName": "QuartzTestJob", "cron": "1/2 * * * * ? ", "description": "測試定時任務", "jobDataMap": { "key": "value" } }
修改任務接口:/quartz/updateJob
{ "jobName": "QuartzTestJob", "cron": "0/2 * * * * ?" }
修改任務只能修改cron時間,如果想要修改其他內容,只能刪除任務后重新添加。
刪除任務接口:/quartz/updateJob
{ "jobName": "QuartzTestJob" }
暫停、恢復、詳情接口同刪除任務接口的請求參數(shù),就不贅述了。
任務列表:/quartz/jobList
{}
返回結果:
{ "code": 10000, "msg": "請求成功", "data": [ { "jobClazz": "class com.cc.job.QuartzTestJob", "jobName": "QuartzTestJob", "jobGroup": "DEFAULT", "jobDataMap": { "key": "value" }, "triggerDetailDtoList": [ { "triggerName": "DEFAULTQuartzTestJob", "triggerGroup": "DEFAULT", "cron": "0/2 * * * * ?", "description": null, "triggerState": "NORMAL", "recentFireTimeList": [ "2023-07-19 09:23:16", "2023-07-19 09:23:18", "2023-07-19 09:23:20", "2023-07-19 09:23:22", "2023-07-19 09:23:24", "2023-07-19 09:23:26", "2023-07-19 09:23:28", "2023-07-19 09:23:30", "2023-07-19 09:23:32", "2023-07-19 09:23:34" ] } ] } ], "traceId": null, "success": true }
以上就是SpringBoot整合Quartz實現(xiàn)動態(tài)配置的詳細內容,更多關于Spring Boot整合Quartz實現(xiàn)動態(tài)配置的資料請關注腳本之家其它相關文章!
相關文章
詳解java CountDownLatch和CyclicBarrier在內部實現(xiàn)和場景上的區(qū)別
這篇文章主要介紹了詳解java CountDownLatch和CyclicBarrier在內部實現(xiàn)和場景上的區(qū)別,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-05-05Java中get/post的https請求忽略ssl證書認證淺析
因為Java在安裝的時候,會默認導入某些根證書,所以有些網站不導入證書,也可以使用Java進行訪問,這篇文章主要給大家介紹了關于Java中get/post的https請求忽略ssl證書認證的相關資料,需要的朋友可以參考下2024-01-01Java 中的 NoSuchMethodException 異常及解決思路(最新推薦)
NoSuchMethodException異常是Java中使用反射機制時常見的錯誤,它通常由方法名或參數(shù)不匹配、訪問權限問題、方法簽名不匹配等原因引發(fā),解決方法包括核實方法名及其參數(shù)類型、確認方法訪問權限、檢查方法簽名和重載問題、確保方法存在于正確的類中,感興趣的朋友一起看看吧2025-01-01