SpringBoot(二)集成 Quartz:2.5.4

Quartz是一个广泛使用的开源任务调度框架,用于在Java应用程序中执行定时任务和周期性任务。它提供了强大的调度功能,允许您计划、管理和执行各种任务,从简单的任务到复杂的任务。

以下是Quartz的一些关键特点和功能:

  • 灵活的调度器:Quartz提供了一个高度可配置的调度器,允许您根据不同的时间表执行任务,包括固定的时间、每日、每周、每月、每秒等。您可以设置任务执行的时间和频率。
  • 多任务支持:Quartz支持同时管理和执行多个任务。您可以定义多个作业和触发器,并将它们添加到调度器中。
  • 集群和分布式调度:Quartz支持集群模式,可以在多台机器上协调任务的执行。这使得Quartz非常适合大规模和分布式应用,以确保任务的高可用性和负载均衡。
  • 持久化:Quartz可以将任务和调度信息持久化到数据库中,以便在应用程序重启时不会丢失任务信息。这对于可靠性和数据保持非常重要。
  • 错过任务处理:Quartz可以配置在任务错过执行时如何处理,例如,是否立即执行、延迟执行或丢弃任务。
  • 监听器:Quartz提供了各种监听器,可以用来监视任务的执行,以及在任务执行前后执行自定义操作。
  • 多种作业类型:Quartz支持不同类型的作业,包括无状态作业(Stateless Job)和有状态作业(Stateful
    Job)。这允许您选择最适合您需求的作业类型。
  • 插件机制:Quartz具有灵活的插件机制,可以扩展其功能。您可以创建自定义插件,以满足特定需求。
  • 丰富的API:Quartz提供了丰富的Java API,使任务调度的配置和管理非常方便。

依赖

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

配置

spring.quartz.job-store-type=jdbc
# The first boot uses ALWAYS
spring.quartz.jdbc.initialize-schema=never
spring.quartz.auto-startup=true
spring.quartz.startup-delay=5s
spring.quartz.overwrite-existing-jobs=true
spring.quartz.properties.org.quartz.scheduler.instanceName=ClusterQuartz
spring.quartz.properties.org.quartz.scheduler.instanceId=AUTO
spring.quartz.properties.org.quartz.jobStore.class=org.springframework.scheduling.quartz.LocalDataSourceJobStore
spring.quartz.properties.org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
spring.quartz.properties.org.quartz.jobStore.tablePrefix=QRTZ_
spring.quartz.properties.org.quartz.jobStore.isClustered=true
spring.quartz.properties.org.quartz.jobStore.acquireTriggersWithinLock=true
spring.quartz.properties.org.quartz.jobStore.misfireThreshold=12000
spring.quartz.properties.org.quartz.jobStore.clusterCheckinInterval=5000
spring.quartz.properties.org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
spring.quartz.properties.org.quartz.threadPool.threadCount=1
spring.quartz.properties.org.quartz.threadPool.threadPriority=5
spring.quartz.properties.org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread=true

配置解释

spring.quartz.job-store-type=jdbc:指定使用数据库作为Quartz的作业存储。spring.quartz.jdbc.initialize-schema=never:此属性设置为"never",表示不会自动初始化Quartz数据库架构。这意味着您需要手动创建Quartz数据库表,以便Quartz正常运行。您可以使用Quartz提供的SQL脚本来创建这些表。spring.quartz.auto-startup=true:设置为true,表示Quartz在Spring Boot应用程序启动时自动启动。spring.quartz.startup-delay=5s:Quartz启动延迟时间,设置为5秒。spring.quartz.overwrite-existing-jobs=true:设置为true,表示如果任务已经存在,则覆盖现有的任务。spring.quartz.properties.org.quartz.scheduler.instanceName=ClusterQuartz:为Quartz调度器设置实例名称。spring.quartz.properties.org.quartz.scheduler.instanceId=AUTO:Quartz调度器实例ID设置为"AUTO",这意味着它会自动分配一个唯一的实例ID。spring.quartz.properties.org.quartz.jobStore.class=org.springframework.scheduling.quartz.LocalDataSourceJobStore:指定使用org.springframework.scheduling.quartz.LocalDataSourceJobStore作为作业存储。spring.quartz.properties.org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate:指定使用PostgreSQL数据库的委托类。spring.quartz.properties.org.quartz.jobStore.tablePrefix=QRTZ_:为Quartz数据库表添加前缀,以避免与其他表冲突。spring.quartz.properties.org.quartz.jobStore.isClustered=true:启用Quartz集群模式。spring.quartz.properties.org.quartz.jobStore.acquireTriggersWithinLock=true:设置为true,以确保在获取触发器时使用锁来处理并发。spring.quartz.properties.org.quartz.jobStore.misfireThreshold=12000:设置Quartz任务的超时时间,以确定任务是否错过执行。spring.quartz.properties.org.quartz.jobStore.clusterCheckinInterval=5000:设置节点之间检查其状态的时间间隔。spring.quartz.properties.org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool:定义Quartz线程池的类型。spring.quartz.properties.org.quartz.threadPool.threadCount=1:设置线程池中线程的数量。spring.quartz.properties.org.quartz.threadPool.threadPriority=5:设置线程的优先级。spring.quartz.properties.org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread=true:允许线程继承初始化线程的类加载器。

job


import cn.hutool.extra.spring.SpringUtil;
import lombok.extern.slf4j.Slf4j;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.PersistJobDataAfterExecution;
import org.springframework.stereotype.Component;/*** @author Wang*/
@PersistJobDataAfterExecution
@DisallowConcurrentExecution
@Slf4j
@Component
public class DealerJob implements Job {@Overridepublic void execute(JobExecutionContext context) {log.info("start Quartz job name: {}", context.getJobDetail().getKey().getName());DealerImportFacade dealerImportFacade = SpringUtil.getBean(DealerImportFacade.class);log.info(" start import US dealer data ");RequestContext.current().set(RequestContextCons.REGION, DataSourceEnum.US.toString().toLowerCase());try {
//            dealerImportFacade.importUsDealerData();log.info(" end import US dealer data ");} catch (Exception e) {log.error(e.getMessage(), e);}}
}

controller


import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;/*** @author Wang*/
@RequiredArgsConstructor
@Slf4j
@RestController
@RequestMapping("/schedule/job")
public class ScheduleJobController {final ScheduleJobService scheduleJobService;final QuartzHelper quartzHelper;@PostMappingpublic AjaxRespData<ScheduleJobVO> addJob(@Valid @RequestBody AddScheduleJobDTO scheduleJobDTO) {ScheduleJobEntity scheduleJobEntity = BeanConvertUtils.convert(scheduleJobDTO, ScheduleJobEntity.class);scheduleJobEntity.init();scheduleJobEntity.setStatus(EnumScheduleJobStatus.RUN);ScheduleJobData data = scheduleJobService.save(scheduleJobEntity);quartzHelper.scheduleJob(data);return AjaxRespData.success(BeanConvertUtils.convert(data, ScheduleJobVO.class));}@DeleteMapping("/{jobId}")public AjaxRespData<Void> removeJob(@PathVariable("jobId") String jobId) {ScheduleJobEntity scheduleJobEntity = scheduleJobService.checkExist(jobId, EnumError.E30001);scheduleJobService.remove(jobId);quartzHelper.remove(scheduleJobEntity);return AjaxRespData.success();}@PutMapping("/{jobId}")public AjaxRespData<ScheduleJobVO> updateJob(@PathVariable String jobId, @Valid @RequestBody AddScheduleJobDTO scheduleJobDTO) {ScheduleJobEntity scheduleJobEntity = BeanConvertUtils.convert(scheduleJobDTO, ScheduleJobEntity.class);scheduleJobEntity.setId(jobId);ScheduleJobData data = scheduleJobService.update(scheduleJobEntity);quartzHelper.scheduleJob(data);return AjaxRespData.success(BeanConvertUtils.convert(data, ScheduleJobVO.class));}@GetMapping("/{jobId}")public AjaxRespData<ScheduleJobVO> getJob(@PathVariable("jobId") String jobId) {ScheduleJobEntity scheduleJobEntity = scheduleJobService.checkExist(jobId, EnumError.E30001);return AjaxRespData.success(BeanConvertUtils.convert(scheduleJobEntity, ScheduleJobVO.class));}@PutMapping("/operate")public void operateJob(@Valid @RequestBody AddScheduleJobDTO scheduleJobDTO) {ScheduleJobEntity scheduleJobEntity = scheduleJobService.checkExist(scheduleJobDTO.getId(), EnumError.E30001);scheduleJobEntity.setStatus(scheduleJobDTO.getStatus());scheduleJobService.update(scheduleJobEntity);quartzHelper.operateJob(scheduleJobDTO.getStatus(), scheduleJobEntity);}}

service


import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;import java.util.List;/*** @author Wang*/
@RequiredArgsConstructor
@Slf4j
@Service
public class ScheduleJobService extends BaseService<ScheduleJobEntity, ScheduleJobData> {final ScheduleJobRepository scheduleJobRepository;final QuartzHelper quartzHelper;@PostConstructpublic void init(){log.info("init schedule job...");List<ScheduleJobEntity> jobs = this.getRepository().findAll();for (ScheduleJobEntity job : jobs) {quartzHelper.scheduleJob(job);quartzHelper.operateJob(EnumScheduleJobStatus.PAUSE, job);if (job.getStatus().equals(EnumScheduleJobStatus.RUN)) {quartzHelper.operateJob(EnumScheduleJobStatus.RUN, job);}}log.info("init schedule job completed...");}@Overridepublic BaseRepository<ScheduleJobEntity> getRepository() {return scheduleJobRepository;}}

helper


import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.stereotype.Component;import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.Objects;/*** @author Wang*/
@RequiredArgsConstructor
@Slf4j
@Component
public class QuartzHelper {final Scheduler scheduler;public void scheduleJob(ScheduleJobEntity jobInfo) {JobKey jobKey = JobKey.jobKey(jobInfo.getJobName(), jobInfo.getJobGroup());try {JobDetail jobDetail = scheduler.getJobDetail(jobKey);if (Objects.nonNull(jobDetail)){scheduler.deleteJob(jobKey);}} catch (SchedulerException e) {e.printStackTrace();}JobDetail jobDetail = JobBuilder.newJob(getJobClass(jobInfo.getType())).withIdentity(jobKey).build();Trigger trigger = TriggerBuilder.newTrigger().withIdentity(jobInfo.getTriggerName(), jobInfo.getTriggerGroup()).startNow().withSchedule(CronScheduleBuilder.cronSchedule(jobInfo.getCronExpression())).build();try {scheduler.scheduleJob(jobDetail, trigger);} catch (SchedulerException e) {log.error(e.getMessage(), e);}}public void rescheduleJob(ScheduleJobEntity job) {TriggerKey triggerKey = new TriggerKey(job.getTriggerName(), job.getTriggerGroup());try {CronTrigger cronTrigger = (CronTrigger) scheduler.getTrigger(triggerKey);CronTrigger newCronTrigger = cronTrigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(CronScheduleBuilder.cronSchedule(job.getCronExpression())).build();scheduler.rescheduleJob(triggerKey, newCronTrigger);} catch (SchedulerException e) {throw new RuntimeException(e);}}public void remove(ScheduleJobEntity job) {TriggerKey triggerKey = new TriggerKey(job.getTriggerName(), job.getTriggerGroup());try {scheduler.pauseTrigger(triggerKey);scheduler.unscheduleJob(triggerKey);scheduler.deleteJob(JobKey.jobKey(job.getTriggerName(), job.getTriggerGroup()));} catch (SchedulerException e) {throw new RuntimeException(e);}}public void unscheduleJob(ScheduleJobEntity job) {TriggerKey triggerKey = new TriggerKey(job.getTriggerName(), job.getTriggerGroup());try {scheduler.unscheduleJob(triggerKey);} catch (SchedulerException e) {throw new RuntimeException(e);}}public void operateJob(EnumScheduleJobStatus status, ScheduleJobEntity job) {JobKey jobKey = JobKey.jobKey(job.getJobName(), job.getJobGroup());try {switch (status) {case RUN:scheduler.resumeJob(jobKey);break;case PAUSE:scheduler.pauseJob(jobKey);break;default:throw new IllegalArgumentException();}} catch (SchedulerException e) {throw new RuntimeException(e);}}public String nextTime(ScheduleJobEntity job) {TriggerKey triggerKey = new TriggerKey(job.getTriggerName(), job.getTriggerGroup());try {Trigger trigger = scheduler.getTrigger(triggerKey);Date nextFireTime = trigger.getNextFireTime();return DateUtil.format(nextFireTime, DateTimeFormatter.ISO_DATE_TIME);} catch (SchedulerException e) {throw new RuntimeException(e);}}private Class<? extends Job> getJobClass(EnumScheduleJobType type) {Class<? extends Job> clazz;switch (type) {case DEALER_IMPORT:clazz = DealerJob.class;break;
//            case SECONDARY_INVITING_EXPIRE:
//                clazz = MockDeviceReportJob.class;
//                break;default:throw new IllegalArgumentException();}return clazz;}
}

最终效果

实例1,8281
在这里插入图片描述
实例2,8282
在这里插入图片描述

踩坑

定时任务执行间隔,最低设置一分钟

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/166233.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Oracle的立场:官网更换首页与以色列站在一起

Oracle公司的官网&#xff0c;更换了首页内容&#xff0c;明确表明立场&#xff1a;Oracle与以色列站在一起。 声明指出&#xff1a; Oracle谴责针对以色列及其公民的恐怖袭击。Oracle将为其员工、以色列政府和国防机构提供一切必要的支持。 Magen David Adom是一家为以色列公民…

Android屏幕刷新机制

基础知识 CPU运行在Android设备上的中央处理器&#xff08;Central Processing Unit&#xff09;是Android设备的核心组件之一&#xff0c;负责执行计算和控制设备的各种操作。 Android设备上的CPU通常采用ARM架构&#xff0c;如ARM Cortex-A系列处理器。这些处理器具有高性能…

Hadoop3教程(三十三):(生产调优篇)慢磁盘监控与小文件归档

文章目录 &#xff08;161&#xff09;慢磁盘监控&#xff08;162&#xff09;小文件归档小文件过多的问题如何对小文件进行归档 参考文献 &#xff08;161&#xff09;慢磁盘监控 慢磁盘&#xff0c;是指写入数据时特别慢的一类磁盘。这种磁盘并不少见&#xff0c;当机器运行…

Java学习笔记(五)——数组、排序和查找

一、数组 数组可以存放多个同一类型的数据。数组也是一种数据类型&#xff0c;是引用类型。即数组就是一组数据。 &#xff08;一&#xff09;数组的使用 1、使用方式1——动态初始化 &#xff08;1&#xff09;数组的定义&#xff1a; 数据类型 数组名[] new 数据类型…

【C语言】每日一题(添加逗号)

添加逗号&#xff0c;链接奉上 目录 方法1&#xff1a;整体存入思路&#xff1a;代码实现&#xff1a; 方法2&#xff1a;分段输出思路&#xff1a;代码实现&#xff1a; 方法1&#xff1a;整体存入 思路&#xff1a; 整体思路&#xff1a; 我们发现这个整数N对于最后1位是比…

会声会影2023官方破解版激活码

随着短视频、vlog等媒体形式的兴起&#xff0c;视频剪辑已经成为了热门技能。甚至有人说&#xff0c;不会修图可以&#xff0c;但不能不会剪视频。实际上&#xff0c;随着各种智能软件的发展&#xff0c;视频剪辑已经变得越来越简单。功能最全的2023新版&#xff0c;全新视差转…

Hadoop3教程(三十四):(生产调优篇)MapReduce生产经验汇总

文章目录 &#xff08;164&#xff09;MR跑得慢的原因&#xff08;165&#xff09;MR常用调优参数Map阶段Reduce阶段 &#xff08;166&#xff09;MR数据倾斜问题参考文献 &#xff08;164&#xff09;MR跑得慢的原因 MR程序执行效率的瓶颈&#xff0c;或者说当你觉得你的MR程…

《动手学深度学习 Pytorch版》 9.4 双向循环神经网络

之前的序列学习中假设的目标是在给定观测的情况下对下一个输出进行建模&#xff0c;然而也存在需要后文预测前文的情况。 9.4.1 隐马尔可夫模型中的动态规划 数学推导太复杂了&#xff0c;略。 9.4.2 双向模型 双向循环神经网络&#xff08;bidirectional RNNs&#xff09;…

解决windows10、windows11故障:Microsoft-Windows-Kernel-Processor-Power 事件ID:37

一、现象 windows系统日志中出现大量的“Microsoft-Windows-Kernel-Processor-Power”错误。 经过分析&#xff1a;原因是windows配置的【使用电池】默认值是5%&#xff0c;按5%计算出来的功率与CPU的最小功率不兼容&#xff0c;如&#xff1a;本机CPU最高功率是25W&#xff0…

flink中使用GenericWriteAheadSink的优缺点

背景 GenericWriteAheadSink是flink中提供的实现几乎精确一次输出的数据汇抽象类&#xff0c;本文就来看一下使用GenericWriteAheadSink的优缺点 GenericWriteAheadSink的优缺点 先看一下GenericWriteAheadSink的原理图 优点&#xff1a; 几乎可以精确一次的输出&#xf…

数据库MongoDB

MongoDB记录是一个文档&#xff0c;由一个字段和值对组成的数据结构&#xff0c;文档类似于JSON对象。 一个文档认为就是一个对象&#xff0c;字段的数据类型是字符型&#xff0c;值除了使用基本类型外&#xff0c;还可以包括其他文档&#xff0c;普通数组和文档数组。 一、…

FreeRTOS介绍 和 将FreeRTOS移植到STM32F103C8T6

一、FreeRTOS 介绍 什么是 FreeRTOS &#xff1f; Free即免费的&#xff0c;RTOS的全称是Real time operating system&#xff0c;中文就是实时操作系统。 注意&#xff1a;RTOS不是指某一个确定的系统&#xff0c;而是指一类操作系统。比如&#xff1a;uc/OS&#xff0c;Fr…

[翻译]理解Postgres的IOPS:为什么数据即使都在内存,IOPS也非常重要

理解Postgres的IOPS&#xff1a;为什么数据即使都在内存&#xff0c;IOPS也非常重要 磁盘IOPS&#xff08;每秒输入/输出操作数&#xff09;是衡量磁盘系统性能的关键指标。代表每秒可以执行的读写操作数量。对于严重依赖于磁盘访问的PG来说&#xff0c;了解和优化磁盘IOPS对实…

虹科分享 | 赋能物流机器人:CANopen通信如何发挥重要作用?

现代物流领域迅速融入了技术进步&#xff0c;特别是随着自主机器人的兴起&#xff0c;这一趋势越发明显。确保这些机器人在复杂的仓库环境中精确运行的一个关键方面是CANopen通信协议。该协议集成了各种组件&#xff08;电机、传感器、摄像头和先进的电池系统&#xff09;&…

flask入门(四)前后端数据传输

文章目录 1、flask后端接收来自前端的数据1&#xff09;如果前端提交的方法为POST2&#xff09;如果前段提交的方法是GET 2、flask后端向前端传数据3、案例参考文献 1、flask后端接收来自前端的数据 1&#xff09;如果前端提交的方法为POST 后端接收时的代码&#xff1a; xx…

C#使用PPT组件的CreateVideo方法生成视频

目录 需求 实现 CreateVideo方法 关键代码 CreateVideoStatus 其它 需求 我们在使用PowerPoint文档时&#xff0c;经常会使用其导出功能以创建视频&#xff0c;如下图&#xff1a; 手工操作下&#xff0c;在制作好PPT文件后&#xff0c;点击文件 -> 导出 -> 创建视…

云安全—分布式基础

0x00 前言 云必然是依赖于分布式技术来进行实现的&#xff0c;所以有必要学习和来了解分布式相关的内容 0x01 分布式计算 1.基本概述 分布式计算的定义&#xff1a;通过网络互联的计算机都具有一定的计算能力&#xff0c;他们之间互相传递数据&#xff0c;实现信息共享&…

互联网Java工程师面试题·Java 面试篇·第三弹

目录 39、JRE、JDK、JVM 及 JIT 之间有什么不同&#xff1f; 40、解释 Java 堆空间及 GC&#xff1f; 41、你能保证 GC 执行吗&#xff1f; 42、怎么获取 Java 程序使用的内存&#xff1f;堆使用的百分比&#xff1f; 43、Java 中堆和栈有什么区别&#xff1f; 44、“ab”…

记录阿里云服务器(Centos7.9)部署Thingsboard(3.4.2)遇到的一些问题

记录编译Thingsboard遇到的一些问题 部署了一个thingsboard项目到阿里云服务器上&#xff0c;历时十一天&#xff0c;遇到了很多困难&#xff0c;国内关于Thingsboard的资料确实很少&#xff0c;所以想着写一篇博客记录一下&#xff0c;或许能够给以后编译遇到类似问题的人一些…

基于nodejs+vue语言的酒店管理系统

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性&#xff1a;…