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)調(diào)整,所以我們開始寫接口,把上面這個任務配置類去掉。
定時任務動態(tài)配置實現(xiàn)
我們還是用上面的任務類QuartzTestJob做測試,這里再說明一次,我們需要有一個任務類作為基礎,本文的目的只是去掉上面的QuartzTestJobConfig。
剩下的內(nèi)容沒有什么需要多說明的,我直接貼代碼了。
業(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;
}調(diào)用接口進行測試
寫完接口代碼后,我們來測試一下
添加任務接口:/quartz/addJob
{
"jobClazz": "com.cc.job.QuartzTestJob",
"jobName": "QuartzTestJob",
"cron": "1/2 * * * * ? ",
"description": "測試定時任務",
"jobDataMap": {
"key": "value"
}
}修改任務接口:/quartz/updateJob
{
"jobName": "QuartzTestJob",
"cron": "0/2 * * * * ?"
}修改任務只能修改cron時間,如果想要修改其他內(nèi)容,只能刪除任務后重新添加。
刪除任務接口:/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)配置的詳細內(nèi)容,更多關于Spring Boot整合Quartz實現(xiàn)動態(tài)配置的資料請關注腳本之家其它相關文章!
相關文章
Java數(shù)據(jù)結構及算法實例:漢諾塔問題 Hanoi
這篇文章主要介紹了Java數(shù)據(jù)結構及算法實例:漢諾塔問題 Hanoi,本文直接給出實現(xiàn)代碼,代碼中包含大量注釋,需要的朋友可以參考下2015-06-06
SpringBoot 整合Lock4j 分布式鎖深度使用案例講解
本文介紹SpringBoot分布式鎖框架Lock4j,支持Redis、Zookeeper等多種存儲實現(xiàn),通過注解和AOP簡化鎖管理,提供并發(fā)控制、防止重復提交等場景應用,并支持自定義執(zhí)行器和key生成策略,適用于高并發(fā)和異構系統(tǒng)需求,感興趣的朋友一起看看吧2025-07-07
使用BeanFactory實現(xiàn)創(chuàng)建對象
這篇文章主要為大家詳細介紹了使用BeanFactory實現(xiàn)創(chuàng)建對象,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-08-08
springboot中的springSession的存儲和獲取實現(xiàn)
這篇文章主要介紹了springboot中的springSession的存儲和獲取實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-09-09

