SpringBoot整合Quartz实现动态配置的代码示例
作者:失败的面
这篇文章将介绍如何把Quartz定时任务做成接口,实现以下功能的动态配置添加任务,修改任务,暂停任务,恢复任务,删除任务,任务列表,任务详情,文章通过代码示例介绍的非常详细,需要的朋友可以参考下
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 # 定时任务的数据保存到jdbc即数据库中 jdbc: # embedded:默认 # always:启动的时候初始化表,我们只在第一次启动的时候用它来自动创建表,然后改回embedded即可,不然数据每次都会被清空 # never:启动的时候不初始化表,也不知道和embedded有什么不同 initialize-schema: embedded
第一次启动的时候请把上面的initialize-schema设置为always,这会在数据库里面自动建表,然后第二次启动时改回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写一个定时任务的步骤,很简单,问题是配置写死了,没有办法动态调整,所以我们开始写接口,把上面这个任务配置类去掉。
定时任务动态配置实现
我们还是用上面的任务类QuartzTestJob做测试,这里再说明一次,我们需要有一个任务类作为基础,本文的目的只是去掉上面的QuartzTestJobConfig。
剩下的内容没有什么需要多说明的,我直接贴代码了。
业务层
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; }
业务层实现
@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次的触发时间 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); } }
接口请求参数
@ApiModel(value = "Quartz任务添加请求参数") public class QuartzCreateParam extends BaseParam { @NotBlank(message = "任务类不能为空") @ApiModelProperty(value = "任务类路径", required = true) private String jobClazz; @NotBlank(message = "任务类名不能为空") @ApiModelProperty(value = "任务类名", required = true) private String jobName; /** * 组名+任务类key组成唯一标识,所以如果这个参数为空,那么默认以任务类key作为组名 */ @ApiModelProperty(value = "任务组名,命名空间") private String jobGroup; @ApiModelProperty(value = "任务数据") private Map<String, Object> jobDataMap; @ApiModelProperty(value = "cron表达式") private String cron; @ApiModelProperty(value = "描述") private String description; }
@ApiModel(value = "Quartz任务更新请求参数") 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任务详情请求参数") 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 = "任务数据") private Map<String, Object> jobDataMap; @ApiModelProperty(value = "触发器列表") private List<QuartzTriggerDetailDto> triggerDetailDtoList; }
@ApiModel(value = "Quartz定时任务触发器详情类") 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" }
暂停、恢复、详情接口同删除任务接口的请求参数,就不赘述了。
任务列表:/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实现动态配置的详细内容,更多关于Spring Boot整合Quartz实现动态配置的资料请关注脚本之家其它相关文章!