您的位置:首页 > 科技 > IT业 > 系统的超级宗门_在线画图工具_营销网站建设免费_邹平县seo网页优化外包

系统的超级宗门_在线画图工具_营销网站建设免费_邹平县seo网页优化外包

2024/12/22 18:57:47 来源:https://blog.csdn.net/weixin_46619605/article/details/144577004  浏览:    关键词:系统的超级宗门_在线画图工具_营销网站建设免费_邹平县seo网页优化外包
系统的超级宗门_在线画图工具_营销网站建设免费_邹平县seo网页优化外包

一、摘要

  • Quartz 架构介绍
  • SpringBoot Quartz 应用整合

二、关于 Quartz
Quartz 是 OpenSymphony 开源组织在 Job scheduling 领域开源的一个作业调度框架项目,完全由 Java 编写,主要是为了实现在 Java 应用程序中进行作业调度并提供了简单却强大的机制!

Quartz 不仅可以单独使用,还可以与 J2EE 与 J2SE 应用程序相结合使用!

同时,Quartz 允许程序开发人员根据时间的间隔来调度作业!

与 JDK 中调度器不同的是,Quartz 实现了作业和触发器的多对多的关系,还能把多个作业与不同的触发器关联,一次可以调度几十个、上百个甚至上几万个复杂的程序!

三、Quartz 架构图
在详细介绍 Quartz 应用之前,我们先来看看它具体的架构图!

在这里插入图片描述

从图中可以看出,Quartz 框架主要包括如下几个部分:

  • SchedulerFactory:任务调度工厂,主要负责管理任务调度器
  • Scheduler:任务调度控制器,主要是负责任务调度
  • Job:任务接口,即被调度的任务
  • JobDetail:Job 的任务描述类,job 执行时会依据此对象的信息反射实例化出 Job 的具体执行对象。
  • Trigger:任务触发器,主要存放 Job 执行的时间策略。例如多久执行一次,什么时候执行,以什么频率执行等等
  • Calendar:Trigger 扩展对象,可以排除或者包含某个指定的时间点(如排除法定节假日)
  • JobStore:存储作业和任务调度期间的状态

我们先来看一个简单的例子,示例代码如下:

/*** 实现 Job 任务接口*/
public class QuartzTest implements Job {@Overridepublic void execute(JobExecutionContext context) throws JobExecutionException {System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));}public static void main(String[] args) throws SchedulerException {// 创建一个SchedulerScheduler scheduler = StdSchedulerFactory.getDefaultScheduler();// 启动Schedulerscheduler.start();// 新建一个Job, 指定执行类是QuartzTest, 指定一个K/V类型的数据, 指定job的name和groupJobDetail job = JobBuilder.newJob(QuartzTest.class).usingJobData("jobData", "test").withIdentity("myJob", "myJobGroup").build();// 新建一个Trigger, 表示JobDetail的调度计划, 这里的cron表达式是 每1秒执行一次Trigger trigger = TriggerBuilder.newTrigger().withIdentity("myTrigger", "myTriggerGroup").startNow().withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?")).build();// 让scheduler开始调度这个job, 按trigger指定的计划scheduler.scheduleJob(job, trigger);}
}

运行结果如下:

2024-11-09 21:38:40
2024-11-09 21:38:45
2024-11-09 21:38:50
2024-11-09 21:38:55
2024-11-09 21:39:00
2024-11-09 21:39:05
2024-11-09 21:39:10

下面,我们就一起从源码层面来看看具体怎么使用!

3.1、Job
打开Job源码,里面其实就是一个包含执行方法void execute(JobExecutionContext context)的接口,开发者只需实现接口来定义具体任务即可!

public interface Job {void execute(JobExecutionContext context) throws JobExecutionException;
}

JobExecutionContext 类封装了获取上下文的各种信息,Job运行时的信息也保存在 JobDataMap 实例中!

例如,我想要获取在上文初始化时使用到的usingJobData(“jobData”, “test”)参数,可以通过如下方式进行获取!

@Override
public void execute(JobExecutionContext context) throws JobExecutionException {//从context中获取instName,groupName以及dataMapString jobName = context.getJobDetail().getKey().getName();String groupName = context.getJobDetail().getKey().getGroup();JobDataMap dataMap = context.getJobDetail().getJobDataMap();//从dataMap中获取myDescription,myValue以及myArrayString value = dataMap.getString("jobData");System.out.println("jobName:" + jobName + ",groupName:" + groupName + ",jobData:" + value);
}

输出结果:

jobName:myJob,groupName:myJobGroup,jobData:test
3.2、Trigger
Trigger主要用于描述Job执行的时间触发规则,最常用的有SimpleTrigger和CronTrigger两个实现类型。

  • SimpleTrigger:主要处理一些简单的调度规则,例如触发一次或者以固定时间间隔周期执行
  • CronTrigger:调度处理更加灵活,可以通过Cron表达式定义出各种复杂时间规则的调度方案,例如每早晨9:00执行,周一、周三、周五下午5:00执行等;

3.2.1、SimpleTrigger
用SimpleTrigger实现每2秒钟执行一次任务为例,代码如下:

public static void main(String[] args) throws SchedulerException {//构建一个JobDetail实例...// 构建一个Trigger,指定Trigger名称和组,规定该Job立即执行,且两秒钟重复执行一次SimpleTrigger trigger = TriggerBuilder.newTrigger().startNow() // 执行的时机,立即执行.withIdentity("myTrigger", "myTriggerGroup") // 不是必须的.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(2).repeatForever()).build();// 让scheduler开始调度这个job, 按trigger指定的计划scheduler.scheduleJob(job, trigger);
}

运行结果:

2024-12-03 16:55:53
2024-12-03 16:55:55
2024-12-03 16:55:57

其中最关键的就是withSchedule()这个方法,通过SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(2).repeatForever()来构建了一个简单的SimpleTrigger类型的任务调度规则,从而实现任务调度!

3.2.2、CronTrigger
如开始介绍的例子一样,里面使用正是CronTrigger类型的调度规则!

public static void main(String[] args) throws SchedulerException {//构建一个JobDetail实例...// 新建一个Trigger, 表示JobDetail的调度计划, 这里的cron表达式是 每5秒执行一次Trigger trigger = TriggerBuilder.newTrigger().withIdentity("myTrigger", "myTriggerGroup").startNow() // 立即执行.withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?")).build();// 让scheduler开始调度这个job, 按trigger指定的计划scheduler.scheduleJob(job, trigger);
}

运行结果:

2024-12-03 17:09:10
2024-12-03 17:09:15
2024-12-03 17:09:20

CronTrigger相比SimpleTrigger,在配置调度规则方面,使用cron表达式更加灵活!

3.2.3、Cron 表达式详解
Quartz 的 Cron 表达式,具体配置规则可以参考如下:

.---------------------- seconds(0 - 59)
|  .------------------- minute (0 - 59)
|  |  .---------------- hour (0 - 23)
|  |  |  .------------- day of month (1 - 31)
|  |  |  |  .---------- month (1 - 12)
|  |  |  |  |  .------- Day-of-Week (1 - 7) 
|  |  |  |  |  |  .---- year (1970 - 2099) ...
|  |  |  |  |  |  |
*  *  *  *  *  ?  *

具体样例如下:

在这里插入图片描述

在 cron 表达式中不区分大小写,更多配置和使用操作可以参考这里。

还可以在线解析cron表达式进行测试。

在这里插入图片描述

3.3、监听器(选用)
quartz 除了提供能正常调度任务的功能之外,还提供了监听器功能!

所谓监听器,其实你可以把它理解为类似Spring Aop的功能,可以对全局或者局部实现监听!

监听器应用,在实际项目中并不常用,但是在某些业务场景下,可以发挥一定的作用,例如:你想在任务处理完成之后,去发送邮件或者发短信进行通知,但是你又不想改以前的代码,这个时候就可以在监听器里面完成改项任务!

quartz 监听器主要分三大类:

  • SchedulerListener:任务调度监听器
  • TriggerListener:任务触发监听器
  • JobListener:任务执行监听器

3.3.1、SchedulerListener
SchedulerListener监听器,主要对任务调度Scheduler生命周期中关键节点进行监听,它只能全局进行监听,简单示例如下:

public class SimpleSchedulerListener implements SchedulerListener {@Overridepublic void jobScheduled(Trigger trigger) {System.out.println("任务被部署时被执行");}@Overridepublic void jobUnscheduled(TriggerKey triggerKey) {System.out.println("任务被卸载时被执行");}@Overridepublic void triggerFinalized(Trigger trigger) {System.out.println("任务完成了它的使命,光荣退休时被执行");}@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被动态添加进来");}@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.printStackTrace();}@Overridepublic void schedulerInStandbyMode() {System.out.println("scheduler被设为standBy等候模式时被执行");}@Overridepublic void schedulerStarted() {System.out.println("scheduler启动时被执行");}@Overridepublic void schedulerStarting() {System.out.println("scheduler正在启动时被执行");}@Overridepublic void schedulerShutdown() {System.out.println("scheduler关闭时被执行");}@Overridepublic void schedulerShuttingdown() {System.out.println("scheduler正在关闭时被执行");}@Overridepublic void schedulingDataCleared() {System.out.println("scheduler中所有数据包括jobs, triggers和calendars都被清空时被执行");}
}

需要在任务调度器启动前,将SimpleSchedulerListener注册到Scheduler容器中!

// 创建一个Scheduler
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
//添加SchedulerListener监听器
scheduler.getListenerManager().addSchedulerListener(new SimpleSchedulerListener());
// 启动Scheduler
scheduler.start();

运行main方法,输出结果如下:

scheduler正在启动时被执行
scheduler启动时被执行
一个JobDetail被动态添加进来
任务被部署时被执行
2024-12-10 17:27:10
....

3.3.2、TriggerListener
TriggerListener,与触发器Trigger相关的事件都会被监听,它既可以全局监听,也可以实现局部监听。

所谓局部监听,就是对某个Trigger的名称或者组进行监听,简单示例如下:

public class SimpleTriggerListener implements TriggerListener {/*** Trigger监听器的名称* @return*/@Overridepublic String getName() {return "mySimpleTriggerListener";}/*** Trigger被激发 它关联的job即将被运行* @param trigger* @param context*/@Overridepublic void triggerFired(Trigger trigger, JobExecutionContext context) {System.out.println("myTriggerListener.triggerFired()");}/*** Trigger被激发 它关联的job即将被运行, TriggerListener 给了一个选择去否决 Job 的执行,如果返回TRUE 那么任务job会被终止* @param trigger* @param context* @return*/@Overridepublic boolean vetoJobExecution(Trigger trigger, JobExecutionContext context) {System.out.println("myTriggerListener.vetoJobExecution()");return false;}/*** 当Trigger错过被激发时执行,比如当前时间有很多触发器都需要执行,但是线程池中的有效线程都在工作,* 那么有的触发器就有可能超时,错过这一轮的触发。* @param trigger*/@Overridepublic void triggerMisfired(Trigger trigger) {System.out.println("myTriggerListener.triggerMisfired()");}/*** 任务完成时触发* @param trigger* @param context* @param triggerInstructionCode*/@Overridepublic void triggerComplete(Trigger trigger, JobExecutionContext context, Trigger.CompletedExecutionInstruction triggerInstructionCode) {System.out.println("myTriggerListener.triggerComplete()");}
}

与之类似,需要将SimpleTriggerListener注册到Scheduler容器中!

// 创建一个Scheduler
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
// 创建并注册一个全局的Trigger Listener
scheduler.getListenerManager().addTriggerListener(new SimpleTriggerListener(), EverythingMatcher.allTriggers());// 创建并注册一个局部的Trigger Listener
//scheduler.getListenerManager().addTriggerListener(new SimpleTriggerListener(), KeyMatcher.keyEquals(TriggerKey.triggerKey("myTrigger", "myJobTrigger")));// 创建并注册一个特定组的Trigger Listener
//scheduler.getListenerManager().addTriggerListener(new SimpleTriggerListener(), GroupMatcher.groupEquals("myTrigger"));
// 启动Scheduler
scheduler.start();

3.3.3、JobListener
JobListener,与任务执行Job相关的事件都会被监听,和Trigger一样,既可以全局监听,也可以实现局部监听。

简单示例如下:

public class SimpleJobListener implements JobListener {/*** job监听器名称* @return*/@Overridepublic String getName() {return "mySimpleJobListener";}/*** 任务被调度前* @param context*/@Overridepublic void jobToBeExecuted(JobExecutionContext context) {System.out.println("simpleJobListener监听器,准备执行:"+context.getJobDetail().getKey());}/*** 任务调度被拒了* @param context*/@Overridepublic void jobExecutionVetoed(JobExecutionContext context) {System.out.println("simpleJobListener监听器,取消执行:"+context.getJobDetail().getKey());}/*** 任务被调度后* @param context* @param jobException*/@Overridepublic void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {System.out.println("simpleJobListener监听器,执行结束:"+context.getJobDetail().getKey());}
}

同样的,将SimpleJobListener注册到Scheduler容器中,即可实现监听!

// 创建一个Scheduler
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
// 创建并注册一个全局的Job Listener
scheduler.getListenerManager().addJobListener(new SimpleJobListener(), EverythingMatcher.allJobs());// 创建并注册一个指定任务的Job Listener
//scheduler.getListenerManager().addJobListener(new SimpleJobListener(), KeyMatcher.keyEquals(JobKey.jobKey("myJob", "myJobGroup")));// 将同一任务组的任务注册到监听器中
//scheduler.getListenerManager().addJobListener(new SimpleJobListener(), GroupMatcher.jobGroupEquals("myJobGroup"));// 启动Scheduler
scheduler.start();

3.3.4、小结

如果想多个同时监听,将其依次加入即可!Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();//添加SchedulerListener监听器
scheduler.getListenerManager().addSchedulerListener(new SimpleSchedulerListener());// 创建并注册一个全局的Trigger Listener
scheduler.getListenerManager().addTriggerListener(new SimpleTriggerListener(), EverythingMatcher.allTriggers());// 创建并注册一个全局的Job Listener
scheduler.getListenerManager().addJobListener(new SimpleJobListener(), EverythingMatcher.allJobs());// 启动Scheduler
scheduler.start();

四、单体应用介绍
下面我们以每5秒执行一次任务为例,采用SpringBoot + Quartz进行技术实现。流程如下!

4.1、引入 quartz 包

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

4.2、编写具体任务

public class TestTask implements Job {@Overridepublic void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {System.out.println("testTask:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));}
}

4.3、编写任务调度配置服务
与上面的参数基本一致

@Configuration
public class TestTaskConfig {@Beanpublic JobDetail testQuartz() {return JobBuilder.newJob(TestTask.class).usingJobData("jobData", "test").withIdentity("myJob", "myJobGroup").storeDurably().build();}@Beanpublic Trigger testQuartzTrigger() {//5秒执行一次return TriggerBuilder.newTrigger().forJob(testQuartz()).withIdentity("myTrigger", "myTriggerGroup").startNow().withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?")).build();}
}

4.4、任务测试
启动应用程序,即可观察到对应的任务运行状况!

如果需要创建多个定时任务,配置流程也类似!

只是这种静态配置方式多了会带来一个问题,比如,现在这个任务是每5秒跑一次,我现在想改成1个小时或者凌晨2点跑一次,这个时候就必须要改代码呢,但是我又不想改代码,基于此需求,利用数据库存储,我们可以将其改成动态配置!

4.5、动态配置定时任务
从上面的代码中我们可以分析中,定时任务的有三个核心变量,其他的方法都可以封装成公共的。

  • 任务名称:例如myJob
  • 任务执行类:例如TestTask.class
  • 任务调度时间:例如0/5 * * * * ?

基于此规律,我们可以创建一个定时任务实体类,用于保存定时任务相关信息到数据库当中,然后编写一个定时任务工具库,用于创建、更新、删除、暂停任务操作,通过 restful 接口操作将任务存入数据库并管理定时任务!

4.5.1、引入 Jpa 包

<!--jpa 支持-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!--mysql 数据源-->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId>
</dependency>

在application.properties中加入数据源配置

spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

4.5.2、创建任务配置表

CREATE TABLE `tb_job_task` (`id` varchar(50)  NOT NULL COMMENT '任务ID',`job_name` varchar(100)  DEFAULT NULL COMMENT '任务名称',`job_class` varchar(200)  DEFAULT NULL COMMENT '任务执行类',`cron_expression` varchar(50)  DEFAULT NULL COMMENT '任务调度时间表达式',`status` int(4) DEFAULT NULL COMMENT '任务状态,0:启动,1:暂停,2:停用',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

4.5.3、编写任务实体类

@Entity
@Table(name = "tb_job_task")
public class QuartzBean {/*** 任务ID*/@Idprivate String id;/*** 任务名称*/@Column(name = "job_name")private String jobName;/*** 任务执行类*/@Column(name = "job_class")private String jobClass;/*** 任务调度时间表达式*/@Column(name = "cron_expression")private String cronExpression;/*** 任务状态,0:启动,1:暂停,2:停用*/@Column(name = "status")private Integer status;//get、set...
}

4.5.4、编写任务操作工具类

public class QuartzUtils {private static final Logger log = LoggerFactory.getLogger(QuartzUtils.class);/*** 创建定时任务 定时任务创建之后默认启动状态* @param scheduler   调度器* @param quartzBean  定时任务信息类* @throws Exception*/public static void createScheduleJob(Scheduler scheduler, QuartzBean quartzBean){try {//获取到定时任务的执行类  必须是类的绝对路径名称//定时任务类需要是job类的具体实现 QuartzJobBean是job的抽象类。Class<? extends Job> jobClass = (Class<? extends Job>) Class.forName(quartzBean.getJobClass());// 构建定时任务信息JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(quartzBean.getJobName()).build();// 设置定时任务执行方式CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(quartzBean.getCronExpression());// 构建触发器triggerCronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(quartzBean.getJobName()).withSchedule(scheduleBuilder).build();scheduler.scheduleJob(jobDetail, trigger);} catch (ClassNotFoundException e) {log.error("定时任务类路径出错:请输入类的绝对路径", e);} catch (SchedulerException e) {log.error("创建定时任务出错", e);}}/*** 根据任务名称暂停定时任务* @param scheduler  调度器* @param jobName    定时任务名称* @throws SchedulerException*/public static void pauseScheduleJob(Scheduler scheduler, String jobName){JobKey jobKey = JobKey.jobKey(jobName);try {scheduler.pauseJob(jobKey);} catch (SchedulerException e) {log.error("暂停定时任务出错", e);}}/*** 根据任务名称恢复定时任务* @param scheduler  调度器* @param jobName    定时任务名称* @throws SchedulerException*/public static void resumeScheduleJob(Scheduler scheduler, String jobName) {JobKey jobKey = JobKey.jobKey(jobName);try {scheduler.resumeJob(jobKey);} catch (SchedulerException e) {log.error("暂停定时任务出错", e);}}/*** 根据任务名称立即运行一次定时任务* @param scheduler     调度器* @param jobName       定时任务名称* @throws SchedulerException*/public static void runOnce(Scheduler scheduler, String jobName){JobKey jobKey = JobKey.jobKey(jobName);try {scheduler.triggerJob(jobKey);} catch (SchedulerException e) {log.error("运行定时任务出错", e);}}/*** 更新定时任务* @param scheduler   调度器* @param quartzBean  定时任务信息类* @throws SchedulerException*/public static void updateScheduleJob(Scheduler scheduler, QuartzBean quartzBean)  {try {//获取到对应任务的触发器TriggerKey triggerKey = TriggerKey.triggerKey(quartzBean.getJobName());//设置定时任务执行方式CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(quartzBean.getCronExpression());//重新构建任务的触发器triggerCronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();//重置对应的jobscheduler.rescheduleJob(triggerKey, trigger);} catch (SchedulerException e) {log.error("更新定时任务出错", e);}}/*** 根据定时任务名称从调度器当中删除定时任务* @param scheduler 调度器* @param jobName   定时任务名称* @throws SchedulerException*/public static void deleteScheduleJob(Scheduler scheduler, String jobName) {JobKey jobKey = JobKey.jobKey(jobName);try {scheduler.deleteJob(jobKey);} catch (SchedulerException e) {log.error("删除定时任务出错", e);}}
}

4.5.5、编写 Jpa 数据操作服务

public interface QuartzBeanRepository extends JpaRepository<QuartzBean,String> {/*** 修改任务状态* @param id* @param status*/@Modifying@Transactional@Query("update QuartzBean m set m.status = ?2 where m.id =?1")void updateState(String id, Integer status);/*** 修改任务调度时间* @param id* @param cronExpression*/@Modifying@Transactional@Query("update QuartzBean m set m.cronExpression = ?2 where m.id =?1")void updateCron(String id, String cronExpression);
}

4.5.6、编写controller服务

@RestController
@RequestMapping("/quartz")
public class QuartzController {private static final Logger log = LoggerFactory.getLogger(QuartzController.class);@Autowiredprivate Scheduler scheduler;@Autowiredprivate QuartzBeanRepository repository;/*** 创建任务* @param quartzBean*/@RequestMapping("/createJob")public HttpStatus createJob(@RequestBody  QuartzBean quartzBean)  {log.info("=========开始创建任务=========");QuartzUtils.createScheduleJob(scheduler,quartzBean);repository.save(quartzBean.setId(UUID.randomUUID().toString()).setStatus(0));log.info("=========创建任务成功,信息:{}", JSON.toJSONString(quartzBean));return HttpStatus.OK;}/*** 暂停任务* @param quartzBean*/@RequestMapping("/pauseJob")public HttpStatus pauseJob(@RequestBody QuartzBean quartzBean) {log.info("=========开始暂停任务,请求参数:{}=========", JSON.toJSONString(quartzBean));QuartzUtils.pauseScheduleJob(scheduler, quartzBean.getJobName());repository.updateState(quartzBean.getId(), 1);log.info("=========暂停任务成功=========");return HttpStatus.OK;}/*** 立即运行一次定时任务* @param quartzBean*/@RequestMapping("/runOnce")public HttpStatus runOnce(@RequestBody QuartzBean quartzBean) {log.info("=========立即运行一次定时任务,请求参数:{}", JSON.toJSONString(quartzBean));QuartzUtils.runOnce(scheduler,quartzBean.getJobName());log.info("=========立即运行一次定时任务成功=========");return HttpStatus.OK;}/*** 恢复定时任务* @param quartzBean*/@RequestMapping("/resume")public HttpStatus resume(@RequestBody QuartzBean quartzBean) {log.info("=========恢复定时任务,请求参数:{}", JSON.toJSONString(quartzBean));QuartzUtils.resumeScheduleJob(scheduler,quartzBean.getJobName());repository.updateState(quartzBean.getId(), 0);log.info("=========恢复定时任务成功=========");return HttpStatus.OK;}/*** 更新定时任务* @param quartzBean*/@RequestMapping("/update")public HttpStatus update(@RequestBody QuartzBean quartzBean)  {log.info("=========更新定时任务,请求参数:{}", JSON.toJSONString(quartzBean));QuartzUtils.updateScheduleJob(scheduler,quartzBean);repository.updateCron(quartzBean.getId(), quartzBean.getCronExpression());log.info("=========更新定时任务成功=========");return HttpStatus.OK;}/*** 删除定时任务* @param quartzBean*/@RequestMapping("/delete")public HttpStatus delete(@RequestBody QuartzBean quartzBean)  {log.info("=========删除定时任务,请求参数:{}", JSON.toJSONString(quartzBean));QuartzUtils.deleteScheduleJob(scheduler,quartzBean.getJobName());repository.updateState(quartzBean.getId(), 2);log.info("=========删除定时任务成功=========");return HttpStatus.OK;}}

4.5.7、服务重启补偿

在应用程序正常运行的时候,虽然没问题,但是当我们重启服务的时候,这个时候内存的里面的定时任务其实全部都被销毁,因此在应用程序启动的时候,还需要将正常的任务重新加入到服务中!

@Component
public class TaskConfigApplicationRunner implements ApplicationRunner {@Autowiredprivate QuartzBeanRepository repository;@Autowiredprivate Scheduler scheduler;@Overridepublic void run(ApplicationArguments args) throws Exception {List<QuartzBean> list = repository.findAll();if(!CollectionUtils.isEmpty(list)){for (QuartzBean quartzBean : list) {//加载启动类型的定时任务if(quartzBean.getStatus().intValue() == 0){QuartzUtils.createScheduleJob(scheduler,quartzBean);}//加载暂停类型的定时任务if(quartzBean.getStatus().intValue() == 1){QuartzUtils.createScheduleJob(scheduler,quartzBean);QuartzUtils.pauseScheduleJob(scheduler, quartzBean.getJobName());}}}}
}

在服务重启的时候,会重新将有效任务加入quartz 中!

4.5.8、接口服务测试
调用quartz/createJob接口,创建任务

=========开始创建任务=========
=========创建任务成功,信息:{"cronExpression":"0/5 * * * * ?","id":"9280b799-f762-47b5-90e4-4874e1ad3c60","jobClass":"com.example.quartz.config.TestTask","jobName":"myJob","status":0}
testTask:2024-12-07 22:31:05
testTask:2024-12-07 22:31:10
testTask:2024-12-07 22:31:15
...

调用quartz/pauseJob接口,暂停任务

=========开始暂停任务,请求参数:{"id":"9280b799-f762-47b5-90e4-4874e1ad3c60","jobName":"myJob"}
=========暂停任务成功=========

调用quartz/runOnce接口,立即运行一次定时任务

=========立即运行一次定时任务,请求参数:{"jobName":"myJob"}
=========立即运行一次定时任务=========
testTask:2024-12-07 22:36:30

调用quartz/resume接口,恢复定时任务

=========恢复定时任务,请求参数:{"id":"9280b799-f762-47b5-90e4-4874e1ad3c60","jobName":"myJob"}
=========恢复定时任务=========
testTask:2024-12-07 22:38:00
testTask:2024-12-07 22:38:05
testTask:2024-12-07 22:38:10
...

调用quartz/update接口,更新定时任务

=========更新定时任务,请求参数:{"cronExpression":"0/10 * * * * ?","id":"9280b799-f762-47b5-90e4-4874e1ad3c60","jobClass":"com.example.quartz.config.TestTask","jobName":"myJob"}
=========更新定时任务=========
testTask:2024-12-07 22:39:10
testTask:2024-12-07 22:39:20
testTask:2024-12-07 22:39:30
...

调用quartz/delete接口,删除定时任务

=========删除定时任务,请求参数:{"id":"9280b799-f762-47b5-90e4-4874e1ad3c60","jobName":"myJob"}=========
=========删除定时任务=========

4.5.9、添加监听器(选用)
当然,如果你想对某个任务实现监听,只需要添加一个配置类,将其注入即可!

@Configuration
public class TestTaskConfig {@Primary@Beanpublic Scheduler initScheduler() throws SchedulerException {Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();//添加SchedulerListener监听器scheduler.getListenerManager().addSchedulerListener(new SimpleSchedulerListener());// 创建并注册一个全局的Trigger Listenerscheduler.getListenerManager().addTriggerListener(new SimpleTriggerListener(), EverythingMatcher.allTriggers());// 创建并注册一个全局的Job Listenerscheduler.getListenerManager().addJobListener(new SimpleJobListener(), EverythingMatcher.allJobs());scheduler.start();return scheduler;}}

4.5.10、小结
需要注意的是:在 quartz 任务暂停之后再次启动时,会立即执行一次,在更新之后也会立即执行一次任务调度!

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com