当前位置: 首页 > news >正文

定时任务:Quartz

Quartz简介

Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用。

quartz是开源且具有丰富特性的"任务调度库",能够集成于任何的java应用,小到独立的应用,大至电子商业系统。quartz能够创建亦简单亦复杂的调度,以执行上十、上百,甚至上万的任务。任务job被定义为标准的java组件,能够执行任何你想要实现的功能。quartz调度框架包含许多企业级的特性,如JTA事务、集群的支持。

简而言之,quartz就是基于java实现的任务调度框架,用于执行你想要执行的任何任务。

官网:http://www.quartz-scheduler.org/


Quartz体系结构

jobdetail和trigger的关系是1对n


Quartz常用API

以下是Quartz编程API几个重要接口,也是Quartz的重要组件

  • Scheduler:用于与调度程序交互的主程序接口。通过Scheduler来绑定jobdetail和trigger。只有安排进执行计划的任务Job(通过scheduler.scheduleJob方法安排进执行计划),当它预先定义的执行时间到了的时候(任务触发trigger),该任务才会执行。
  • Job:预先定义的任务逻辑。
  • JobDetail:定时任务的实例,JobDetail实例是通过JobBuilder类创建的,Scheduler真正调度的是JobDetail而不是job。
  • JobDataMap:可以包含不限量的(序列化的)数据对象,可以看作JobDetail内业务逻辑运行时的需要的一系列参数。
  • Trigger :触发器,Trigger对象是用来触发执行Job的。当调度一个job时,我们实例一个触发器然后调整它的属性来满足job执行的条件。表明任务在什么时候会执行。定义了一个已经被安排的任务将会在什么时候执行的时间条件,比如每2秒就执行一次。
  • JobBuilder :用于声明一个任务实例,也可以定义关于该任务的详情比如任务名、组名等,这个声明的实例将会作为一个实际执行的任务。
  • TriggerBuilder :用于声明触发器trigger实例。
  • JobListener、TriggerListener、SchedulerListener:监听器,用于对组件的监听。
  • ......

两个重要注解

@DisallowConcurrentExecution

作用:禁止同一任务定义的多个实例并发执行,确保任务在前一次执行完成后才会触发下一次执行。

解释:一个定时任务5秒钟触发一次,执行一次需要10分钟。打上这个注解后,在打上这个注解后,在上一个任务执行结束前,即使已经到了它的执行时间,也要等待上一个任务执行结束。

@PersistJobDataAfterExecution

作用:在执行完成后持久化JobDataMap中的数据,使任务状态可以在多次执行间保持。

解释:在任务中修改JobDataMap中的数据,此番修改是永久有效的。


案例

入门案例

新建一个springboot项目,导入quartz依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-quartz</artifactId>
</dependency>

写一个HelloJob任务类实现Job接口,重写execute方法

public class HelloJob implements Job {@Overridepublic void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {// 定义时间Date date = new Date();SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");String dateString = dateFormat.format(date);System.out.println("进行数据库备份操作。当前任务执行的时间:" + dateString);}
}

声明JobDetail指定HelloJob,声明Trigger,绑定它俩交给Scheduler调度

public class HelloSchedulerDemo {public static void main(String[] args) throws Exception {// 1:从工厂中获取任务调度的实例Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();// 2:定义一个任务调度实例,将该实例与HelloJob绑定,任务类需要实现Job接口JobDetail job = JobBuilder.newJob(HelloJob.class).withIdentity("job1", "group1") // 定义该实例唯一标识.build();// 3:定义触发器 ,马上执行, 然后每5秒重复执行一次Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1") // 定义该实例唯一标识.startNow()  // 马上执行.withSchedule(SimpleScheduleBuilder.simpleSchedule().repeatSecondlyForever(5)) // 简单间隔触发,每5秒执行一次.build();// 4:使用触发器调度任务的执行scheduler.scheduleJob(job, trigger);// 5:开启scheduler.start();// 关闭// scheduler.shutdown();}
}

使用JobDataMap

当Scheduler调用一个Job,就会将JobExecutionContext传递给Job的execute()方法。Job能通过JobExecutionContext对象访问到Quartz运行时候的环境以及Job本身的明细数据。当然,JobDataMap也在JobExecutionContext里面。

JobDataMap里面的值的获取方式

(1)使用Map获取。

  • 在进行任务调度时,JobDataMap存储在JobExecutionContext中 ,非常方便获取。
  • JobDataMap可以用来装载任何可序列化的数据对象,当job实例对象被执行时这些参数对象会传递给它。
  • JobDataMap实现了JDK的Map接口,并且添加了非常方便的方法用来存取基本数据类型。

(2)Job实现类中添加setter方法对应JobDataMap的键值,Quartz框架默认的JobFactory实现类在初始化job实例对象时会自动地调用这些setter方法。

@PersistJobDataAfterExecution
public class HelloJob implements Job {private String name;@Overridepublic void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {System.out.println("Hello, " + name + "!");setName("I have changed my name");}public void setName(String name) {this.name = name;}public String getName() {return name;}
}

public class HelloJob implements Job {@Overridepublic void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {// 定义时间Date date = new Date();SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");String dateString = dateFormat.format(date);// 定义工作任务内容System.out.println("进行数据库备份操作。当前任务执行的时间:" + dateString);System.out.println("name from job detail:"+jobExecutionContext.getJobDetail().getJobDataMap().get("name"));System.out.println("name from trigger:" + jobExecutionContext.getTrigger().getJobDataMap().get("name"));System.out.println("name from merge:" + jobExecutionContext.getMergedJobDataMap().get("name"));System.out.println("age:"+jobExecutionContext.getJobDetail().getJobDataMap().get("age"));}
}
public class HelloSchedulerDemo {public static void main(String[] args) throws Exception {// 1:从工厂中获取任务调度的实例Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();// 2:定义一个任务调度实例,将该实例与HelloJob绑定,任务类需要实现Job接口JobDetail job = JobBuilder.newJob(HelloJob.class).withIdentity("job1", "group1") // 定义该实例唯一标识.usingJobData("name","cjj").usingJobData("age",18).build();// 3:定义触发器 ,马上执行, 然后每5秒重复执行一次Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1") // 定义该实例唯一标识.startNow()  // 马上执行.withSchedule(SimpleScheduleBuilder.simpleSchedule().repeatSecondlyForever(5)) // 简单间隔触发,每5秒执行一次.usingJobData("name","hlyy").build();// 4:使用触发器调度任务的执行scheduler.scheduleJob(job, trigger);// 5:开启scheduler.start();// 关闭// scheduler.shutdown();}
}

输出如下

进行数据库备份操作。当前任务执行的时间:2025-04-25 14:46:39
name from job detail:cjj
name from trigger:hlyy
name from merge:hlyy
age:18

这里注意:如果遇到同名的key,Trigger的优先级更高


有状态的Job

@PersistJobDataAfterExecution
public class HelloJob implements Job {private int count;@Overridepublic void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {// 定义时间Date date = new Date();SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");String dateString = dateFormat.format(date);// 定义工作任务内容System.out.println("进行数据库备份操作。当前任务执行的时间:" + dateString + " 执行第 " + (++count) + " 次");// 保存到JobDataMap中jobExecutionContext.getJobDetail().getJobDataMap().put("count", count);}public void setCount(int count) {this.count = count;}
}

注意加上@PersistJobDataAfterExecution注解,才会每次保存count的状态,否则每次该JobDetail被调度时,都会将count初始化为0

public class HelloSchedulerDemo {public static void main(String[] args) throws Exception {// 1:从工厂中获取任务调度的实例Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();// 2:定义一个任务调度实例,将该实例与HelloJob绑定,任务类需要实现Job接口JobDetail job = JobBuilder.newJob(HelloJob.class).withIdentity("job1", "group1") // 定义该实例唯一标识.usingJobData("count",0).build();// 3:定义触发器 ,马上执行, 然后每5秒重复执行一次Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1") // 定义该实例唯一标识.startNow()  // 马上执行.withSchedule(SimpleScheduleBuilder.simpleSchedule().repeatSecondlyForever(5)) // 简单间隔触发,每5秒执行一次.build();// 4:使用触发器调度任务的执行scheduler.scheduleJob(job, trigger);// 5:开启scheduler.start();// 关闭// scheduler.shutdown();}
}
4:54:32.523 [DefaultQuartzScheduler_Worker-1] DEBUG org.quartz.core.JobRunShell - Calling execute on job group1.job1
进行数据库备份操作。当前任务执行的时间:2025-04-25 14:54:32 执行第 1 次
14:54:37.524 [DefaultQuartzScheduler_QuartzSchedulerThread] DEBUG org.quartz.simpl.PropertySettingJobFactory - Producing instance of Job 'group1.job1', class=org.daolong.job.HelloJob
14:54:37.525 [DefaultQuartzScheduler_QuartzSchedulerThread] DEBUG org.quartz.core.QuartzSchedulerThread - batch acquisition of 1 triggers
14:54:37.525 [DefaultQuartzScheduler_Worker-2] DEBUG org.quartz.core.JobRunShell - Calling execute on job group1.job1
进行数据库备份操作。当前任务执行的时间:2025-04-25 14:54:37 执行第 2 次
14:54:42.517 [DefaultQuartzScheduler_QuartzSchedulerThread] DEBUG org.quartz.simpl.PropertySettingJobFactory - Producing instance of Job 'group1.job1', class=org.daolong.job.HelloJob
14:54:42.518 [DefaultQuartzScheduler_QuartzSchedulerThread] DEBUG org.quartz.core.QuartzSchedulerThread - batch acquisition of 1 triggers
14:54:42.518 [DefaultQuartzScheduler_Worker-3] DEBUG org.quartz.core.JobRunShell - Calling execute on job group1.job1
进行数据库备份操作。当前任务执行的时间:2025-04-25 14:54:42 执行第 3 次

Cron触发器

public class HelloSchedulerDemoCronTrigger {public static void main(String[] args) throws Exception {// 1:从工厂中获取任务调度的实例Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();// 2:定义一个任务调度实例,将该实例与HelloJob绑定,任务类需要实现Job接口JobDetail job = JobBuilder.newJob(HelloJob.class).withIdentity("job1", "group1") // 定义该实例唯一标识.build();// 3:定义触发器 ,马上执行, 然后每5秒重复执行一次Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1") // 定义该实例唯一标识.withSchedule(CronScheduleBuilder.cronSchedule("*/5 * * * * ?")) // 每5秒执行一次.build();// 4:使用触发器调度任务的执行scheduler.scheduleJob(job, trigger);// 5:开启scheduler.start();// 关闭// scheduler.shutdown();}
}

监听器(以SchedulerListener为例)

自定义一个MySchedulerListener实现SchedulerListener接口

public class MySchedulerListener implements SchedulerListener {@Overridepublic void jobScheduled(Trigger trigger) {String jobName = trigger.getJobKey().getName();System.out.println(jobName + " 完成部署");}@Overridepublic void jobUnscheduled(TriggerKey triggerKey) {System.out.println(triggerKey + " 完成卸载");}@Overridepublic void triggerFinalized(Trigger trigger) {System.out.println("触发器被移除 " + trigger.getJobKey().getName());}@Overridepublic void triggerPaused(TriggerKey triggerKey) {System.out.println(triggerKey + " 正在被暂停");}@Overridepublic void triggersPaused(String triggerGroup) {System.out.println("触发器组 "+triggerGroup + " 正在被暂停");}@Overridepublic void triggerResumed(TriggerKey triggerKey) {System.out.println(triggerKey + " 正在从暂停中恢复");}@Overridepublic void triggersResumed(String triggerGroup) {System.out.println("触发器组 "+triggerGroup + " 正在从暂停中恢复");}@Overridepublic void jobAdded(JobDetail jobDetail) {System.out.println(jobDetail.getKey()+" 添加工作任务");}@Overridepublic void jobDeleted(JobKey jobKey) {System.out.println(jobKey+" 删除工作任务");}@Overridepublic void jobPaused(JobKey jobKey) {System.out.println(jobKey+" 工作任务正在被暂停");}@Overridepublic void jobsPaused(String jobGroup) {System.out.println("工作任务组 "+jobGroup+" 正在被暂停");}@Overridepublic void jobResumed(JobKey jobKey) {System.out.println(jobKey+" 正在从暂停中恢复");}@Overridepublic void jobsResumed(String jobGroup) {System.out.println("工作任务组 "+jobGroup+" 正在从暂停中恢复");}@Overridepublic void schedulerError(String msg, SchedulerException cause) {System.out.println("产生严重错误时调用:   "+msg+"  "+cause.getUnderlyingException());}@Overridepublic void schedulerInStandbyMode() {System.out.println("调度器在挂起模式下调用");}@Overridepublic void schedulerStarted() {System.out.println("调度器 开启时调用");}@Overridepublic void schedulerStarting() {System.out.println("调度器 正在开启时调用");}@Overridepublic void schedulerShutdown() {System.out.println("调度器 已经被关闭 时调用");}@Overridepublic void schedulerShuttingdown() {System.out.println("调度器 正在被关闭 时调用");}@Overridepublic void schedulingDataCleared() {System.out.println("调度器的数据被清除时调用");}
}
public class HelloSchedulerDemoSchedulerListener {public static void main(String[] args) throws Exception {// 1:从工厂中获取任务调度的实例Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();// 2:定义一个任务调度实例,将该实例与HelloJob绑定,任务类需要实现Job接口JobDetail job = JobBuilder.newJob(HelloJob.class).withIdentity("job1", "group1") // 定义该实例唯一标识.build();// 3:定义触发器 ,马上执行, 然后每5秒重复执行一次Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1") // 定义该实例唯一标识.startNow()  // 马上执行.withSchedule(SimpleScheduleBuilder.simpleSchedule().repeatSecondlyForever(5)) // 每5秒执行一次.build();// 4:使用触发器调度任务的执行scheduler.scheduleJob(job, trigger);// 创建SchedulerListenerscheduler.getListenerManager().addSchedulerListener(new MySchedulerListener());// 移除对应的SchedulerListener// scheduler.getListenerManager().removeSchedulerListener(new MySchedulerListener());// 5:开启scheduler.start();// 延迟7秒后关闭Thread.sleep(7000);// 关闭scheduler.shutdown();}
}


SpringBoot整合Quartz,实现一个Quartz任务调度中心

参考文章:Spring Boot整合Quartz实现动态配置

完整代码

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-quartz</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><!-- 兼容 Spring Boot 2.6.x 的版本 --><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.9.2</version></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>2.9.2</version></dependency><!--        美化ui--><dependency><groupId>com.github.xiaoymin</groupId><artifactId>swagger-bootstrap-ui</artifactId><version>1.9.6</version></dependency><!--        校验框架--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency></dependencies>
# MySQL 数据源配置
spring.datasource.url=jdbc:mysql://localhost:3306/quartz_db?serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver# Quartz 持久化配置
spring.quartz.job-store-type=jdbc
# 启动时不初始化数据库,我们自己手动初始化过了
spring.quartz.jdbc.initialize-schema=embedded# Quartz 集群配置
#spring.quartz.properties.org.quartz.jobStore.isClustered: true
#spring.quartz.properties.org.quartz.jobStore.tablePrefix: QRTZ_
#spring.quartz.properties.org.quartz.jobStore.driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate

在maven的依赖包下找到Quartz 调度器所需的表结构的 SQL 脚本文件,到数据库中手动执行。

E:\apache-maven-3.8.6\repository\org\quartz-scheduler\quartz\2.3.2\quartz-2.3.2.jar!\org\quartz\impl\jdbcjobstore\tables_mysql_innodb.sql



@Configuration
public class QuartzConfig {@Beanpublic Scheduler myScheduler(SchedulerFactoryBean schedulerFactoryBean) throws Exception {Scheduler scheduler = schedulerFactoryBean.getScheduler();scheduler.start();scheduler.getListenerManager().addJobListener(new MyJobListener());return scheduler;}
}

@Component
public class QuartzTestJob extends QuartzJobBean {@Overrideprotected void executeInternal(org.quartz.JobExecutionContext jobExecutionContext) throws JobExecutionException {System.out.println("Quartz Test Job");}
}

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 {@Resource(name = "myScheduler")private Scheduler scheduler;@Overridepublic void addJob(QuartzCreateParam param) throws SchedulerException {String clazzName = param.getJobClazz();String jobName = param.getJobName();String jobGroup = param.getJobGroup();String triggerName = param.getTriggerName();String triggerGroup = param.getTriggerGroup();String cron = param.getCron();String description = param.getDescription();JobKey jobKey = JobKey.jobKey(jobName, jobGroup);if (checkExist(jobKey)) {throw new BaseException("要添加的任务已经存在:" + 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) {jobDataMap.putAll(param.getJobDataMap());}JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroup).usingJobData(jobDataMap).build();CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cron);Trigger trigger = TriggerBuilder.newTrigger().withSchedule(scheduleBuilder).withIdentity(TriggerKey.triggerKey(triggerGroup, triggerName)).withDescription(description).build();scheduler.scheduleJob(jobDetail, trigger);if (!scheduler.isShutdown()) {scheduler.start();}}/*** 可能出现的情况* 1.修改该任务现指定的触发器的cron表达式 (给出triggerName、triggerGroup、cron)* 2.为该任务绑定一个新的(新增)触发器 (给出triggerName、triggerGroup、cron)* 3.为该任务绑定一个已有触发器 (给出triggerName、triggerGroup)*/@Overridepublic void updateJob(QuartzUpdateParam param) throws SchedulerException {String jobName = param.getJobName();String jobGroup = param.getJobGroup();String triggerName = param.getTriggerName();String triggerGroup = param.getTriggerGroup();String cron = param.getCron();JobKey jobKey = JobKey.jobKey(jobName, jobGroup);TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroup);if (!checkExist(jobKey)) {throw new BaseException("要修改的任务不存在:" + jobKey);}// 情况3if (cron.isEmpty()) {if (!checkExist(triggerKey)) {throw new BaseException("要绑定的任务触发器不存在:" + triggerKey);}scheduler.scheduleJob(scheduler.getTrigger(triggerKey));return;}// 情况1if (checkExist(triggerKey)) {// 获取原触发器的状态Trigger.TriggerState triggerState = scheduler.getTriggerState(triggerKey);CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cron);Trigger trigger = TriggerBuilder.newTrigger().withSchedule(scheduleBuilder).withIdentity(triggerKey).build();/** 更新触发器* 停止旧触发器的调度计划。* 将新触发器绑定到原任务(JobDetail)。* 根据新触发器的配置(如 Cron 表达式、开始/结束时间)生成下一次触发时间。* 根据原触发器的状态选择是否继续调度。*/scheduler.rescheduleJob(triggerKey, trigger);if (triggerState == Trigger.TriggerState.PAUSED) {scheduler.pauseTrigger(triggerKey);}return;}// 情况2CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cron);Trigger trigger = TriggerBuilder.newTrigger().withSchedule(scheduleBuilder).withIdentity(triggerKey).build();scheduler.scheduleJob(trigger);}@Overridepublic void pauseJob(QuartzDetailParam param) throws SchedulerException {String jobName = param.getJobName();String jobGroup = param.getJobGroup();JobKey jobKey = JobKey.jobKey(jobName, jobGroup);if (checkExist(jobKey)) {scheduler.pauseJob(jobKey);} else {throw new BaseException("要暂停的任务不存在:" + jobKey);}}@Overridepublic void resumeJob(QuartzDetailParam param) throws SchedulerException {String jobName = param.getJobName();String jobGroup = param.getJobGroup();JobKey jobKey = JobKey.jobKey(jobName, jobGroup);if (checkExist(jobKey)) {if (!scheduler.isShutdown()) {scheduler.resumeJob(jobKey);return;}}throw new BaseException("要恢复的任务不存在:" + jobKey);}@Overridepublic void deleteJob(QuartzDetailParam param) throws SchedulerException {String jobName = param.getJobName();String jobGroup = param.getJobGroup();JobKey jobKey = JobKey.jobKey(jobName, jobGroup);if (!checkExist(jobKey)) {throw new BaseException("要删除的任务不存在:" + jobKey);}// 先暂停再删除scheduler.pauseJob(jobKey);scheduler.deleteJob(jobKey);}@Overridepublic List<QuartzJobDetailDto> jobList() throws SchedulerException {// 获取匹配所有任务的matcherGroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();List<QuartzJobDetailDto> jobDtoList = new ArrayList<>();Set<JobKey> jobKeySet = scheduler.getJobKeys(matcher);for (JobKey jobKey : jobKeySet) {QuartzJobDetailDto jobDto = getJobDtoByJobKey(jobKey);jobDtoList.add(jobDto);}return jobDtoList;}@Overridepublic QuartzJobDetailDto jobDetail(QuartzDetailParam param) throws SchedulerException {String jobName = param.getJobName();String jobGroup = param.getJobGroup();JobKey jobKey = JobKey.jobKey(jobName, jobGroup);return getJobDtoByJobKey(jobKey);}// 检查任务是否存在, 如果存在返回trueprivate Boolean checkExist(JobKey jobKey) throws SchedulerException {return scheduler.checkExists(jobKey);}// 检查触发器是否存在, 如果存在返回trueprivate Boolean checkExist(TriggerKey triggerKey) throws SchedulerException {return scheduler.checkExists(triggerKey);}// 根据jobKey获取任务详情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;}}

相关文章:

  • Windows同步技术-使用命名对象
  • MySQL引擎分类与选择、SQL更新底层实现、分库分表、读写分离、主从复制 - 面试实战
  • 明远智睿SD2351核心板:以48元撬动AI视觉产业革命的“硬核引擎”
  • 队列基础和例题
  • 保障海外业务发展,U-Mail邮件中继提供高效安全的解决方案
  • [Mybatis-plus]
  • 数据结构------C语言经典题目(6)
  • protothread协程库实现非阻塞延时(无操作系统)
  • LangChain 中主流的 RAG 实现方式
  • 第5.5章:ModelScope-Agent:支持多种API无缝集成的开源框架
  • Golang | 自行实现并发安全的Map
  • 运维打铁:Mysql 分区监控以及管理
  • 分享Matlab成功安装Support Package硬件支持包的方法
  • 通过音频的pcm数据格式利用canvas绘制音频波形图
  • GStreamer 简明教程(十一):插件开发,以一个音频生成(Audio Source)插件为例
  • Centos7.2安装Xmap
  • 司法考试模拟考试系统
  • LLM Graph Rag(基于LLM的事件图谱RAG)
  • 红黑树——如何靠控制色彩实现平衡的?
  • 记录搭建自己应用中心
  • 最近这75年,谁建造了上海?
  • 早睡1小时,变化有多惊人?第一个就没想到
  • 新希望去年归母净利润4.74亿同比增逾九成,营收降27%
  • 一季度煤价持续下探,多家煤炭巨头营收下滑、净利润降约两成
  • 两部门:推动“青年驿站”为毕业生跨地区求职提供住宿优惠便利
  • 男子称喝中药治肺结节三个月后反变大增多,自贡卫健委回应