任务调度之Quartz(二):Quartz体系结构

news2025/3/2 2:27:15

1、Quartz 体系结构

      由上一篇的Quartz基本使用可以发现,Quartz 主要包含一下几种角色:

            1)Job:也可以认为是JobDtetail,表示具体的调度任务

            2)Trigger:触发器,用于定义任务Job出发执行的规律

            3)Scheduler:调度器,用于将 JobDetail 和 Trigger绑定,并注册到容器中

            4)Listener:监听器,Quartz 中提供了3种监听器,即 JobListener、TriggerListener、

                                  SchedulerListener分别用来监听 Job、Trigger、Scheduler 的执行情况

            5)Jobstore:用来存储任务和触发器相关的信息

           如下图所示:

                  

            注意:

                    由上图可以发现,其中JobDetail是1对多(1:N)的关系,即一个JobDetail可以

                   去绑定多个触发器Trigger

      

2、JobDetail

     由Quartz基本使用笔记可以知道,在 Quartz 中Job需要通过JobBuilder 包装成JobDetail

     后才能被使用,具体用法请参考“Quartz基本使用”。

3、Trigger

      触发器 Trigger 通过Trigger Builder来构建,用于定义任务Job出发执行的规律。

      Trigger 在Quartz 中有4种子接口,分别是:

              

              1)SimpleTrigger:简单触发器,固定时刻或时间间隔触发,单位毫秒

                                   可以定义固定时刻或者固定时间间隔的调度规则(精确到毫秒)。

                                   例如:每天 9 点钟运行;每隔 30 分钟运行一次。

              2)CalendarIntervalTrigge:基于日历的触发器,单位秒,比简单触发器更多时间单位,

                                    支持非固定时间的触发,例如一 年可能 365/366,一个月可能 28/29/30/31

                                    好处是不需要去计算时间间隔,比如 1 个小时等于多少毫秒。

                                    每年的月数和每个月的天数不是固定的,这种情况也适用。   

              3)DailyTimeIntervalTrigger:基于日期的触发器,每天某个时间段触发,即每天的某

                                    个时间段内,以一定的时间间隔执行任务。

                                     例如:每天早上 9 点到晚上 9 点,每隔半个小时执行一次,并且只在

                                                周一到周六执行。

              4)CronTrigger:基于 Cron 表达式的触发器,可以定义基于 Cron 表达式的调度规则,

                                     是最常用的触发器类型。

      

3.1、Cron 表达式

         是一种用于指定定期执行任务的时间规则的字符串表达式。它由6或7个字段组成,

         每个字段代表不同的时间单位,包括秒、分、时、日、月、星期和年。

         Cron表达式通常以空格分隔这些字段,格式如下:

                 秒 分 时 日 月 星期 年

位置时间域特殊值
10-59, - * /
2分钟0-59, - * /
3小时0-23, - * /
4日期1-31, - * ? / L W C
5月份1-12, - * /
6星期1-7, - * ? / L W C
7年份(可选)1-31, - * /

        Cron 表达式特殊值含义:

         1)星号(*):可用在所有字段中,表示对应时间域的每一个时刻,

                             例如,在分钟字段时,表示“每分钟”;

         2)问号(?):该字符只在日期和星期字段中使用,它通常指定为“无意义的值”,

                                  相当于点(.)位符;

         3)减号(-):表达一个范围,如在小时字段中使用“10-12”,则表示从 10 到 12 点,

                              即 10,11,12;

         4)斜杠(/):x/y 表达一个等步长序列,x 为起始值,y 为增量步长值。

                           如:在分钟字段中使用 0/15,则表示为 0,15,30 和 45 秒,而 5/15 在分钟字段

                                 中表示 5,20,35,50,你也可以使用*/y,它等同于 0/y;

         5)L:该字符只在日期和星期字段中使用,代表“Last”的意思,但它在两个字段中意思不

                    同。L 在日期字段中,表示 这个月份的最后一天,如一月的 31 号,非闰年二月

                    的 28 号;如果 L 用在星期中,则表示星期六,等同于 7。但是,如果 L 出现在

                    星期字段里,而且在前面有一个数值 X,则表示“这个月的最后 X 天”,

                    例如:6L 表示该月的最后星期五;

         6)W:该字符只能出现在日期字段里,是对前导日期的修饰,表示离该日期最近的工作日。

                     例如 :15W 表示离该月 15号最近的工作日,如果该月 15 号是星期六,则匹配 14

                                 号星期五;如果 15 日是星期日,则匹配 16 号星期一;如果 15号是星期二,

                                  那结果就是 15 号星期二。但必须注意关联的匹配日期不能够跨月,如你指定

                                  1W,如果 1 号是星期六,结果匹配的是 3 号星期一,而非上个月最后的那

                                   天。W 字符串只能指定单一日期,而不能指定日期范围;

         7)LW 组合:在日期字段可以组合使用 LW,它的意思是当月的最后一个工作日;

         8)井号(#):该字符只能在星期字段中使用,表示当月某个工作日。

                             如 :6#3 表示当月的第三个星期五(6 表示星期五,#3 表示当前的第三个),而

                                    4#5 表示当月的第五个星期三,假设当月没有第五个星期三,忽略不触发;

         9)C:该字符只在日期和星期字段中使用,代表“Calendar”的意思。它的意思是计划所关联

                     的日期,如果日期没有被关联,则相当于日历中所有日期。

                      例如: 5C 在日期字段中就相当于日历 5 日以后的第一天。1C 在星期字段中相当于

                                  星期日后的第一天。

           注意:

                   Cron 表达式对特殊字符的大小写不敏感,对代表星期的缩写英文大小写也不敏感。

4、Scheduler

      调度器Scheduler 是Quartz的指挥官,由StdSchedulerFactory产生。它是单例的。

      Scheduler默认是实现类是StdScheduler,里面包含了一个QuartzScheduler,

      QuartzScheduler里面又包含了一个QuartzSchedulerThread。

      Scheduler中的方法主要分为三大类:

            1)操作调度器本身,例如调度器的启动start()、调度器的关闭shutdown()。

            2)操作Trigger,例如pauseTriggers()、resumeTrigger()。

            3)操作Job,例如scheduleJob()、unscheduleJob()、rescheduleJob()

        Scheduler 方法非常多,这里就不一一列举了。

5、Listener

      Quartz 中提供了3种监听器,即 JobListener、TriggerListener、SchedulerListener分

      别用来监听 Job、Trigger 和 Scheduler 的运行情况。

5.1、JobListener

         JobListener 主要用于监听 JobDetail(即Job) 在运行过程中是否有关键事件发生;

        这些关键事件包括:JobDetail是否被Trigger否决、JobDetail 是否执行完成等。

        JobListener 主要方法包括:

              1)getName():返回JobListener 的名称

              2)jobToBeExecuted():Scheduler 在 JobDetail 将要被执行时调用这个方法

              3)jobExecutionVetoed():Scheduler 在 JobDetail 即将被执行,但又被 TriggerListener

                           否决了时调用这个方法

              4)jobWasExecuted():Scheduler 在 JobDetail 被执行之后调用这个方法

5.2、TriggerListener

         TriggerListener 主要被用来监听触发器Trigger是否被触发,及触发后Job的execute 方法

         是否被执行。

         TriggerListener 常用方法如下:

                1)getName():返回监听器的名称

                2)triggerFired():Trigger 被触发,Job 上的 execute() 方法将要被执行时,Scheduler

                              就调用这个方法

                3)vetoJobExecution():在 Trigger 触发后,Job 将要被执行时由 Scheduler 调用这个

                              方法。TriggerListener 给了一个选择去否决 Job 的执行。假如这个方法返回

                              true,这个 Job 将不会为此次 Trigger 触发而得到执行

                4)triggerMisfired():Trigger 错过触发时调用

                5)triggerComplete():Trigger 被触发并且完成了 Job 的执行时,Scheduler 调用这个

                                方法

5.3、SchedulerListener

        SchedulerListener主要用于监控 Scheduler 的生命周期中是否有关键事件发生,

        当 Scheduler 有关键事件发生时 SchedulerListener 会被调用

        与Scheduler有关的事件包括:增加一个job/trigger,删除一个job/trigger,scheduler

        运行时发送错误,关闭scheduler等。

6、Jobstore

     Jobstore 主要用来存储任务和触发器相关的信息,例如所有任务的名称、数量、状态等等。

     Quartz中有两种存储任务的方式,一种在在内存,一种是在数据库。

6.1、RAMJobstore

      Quartz默认的JobStore是RAMJobstore,也就是把任务和触发器信息运行的信息存储在内

      存中,用到了HashMap、TreeSet、HashSet等等数据结构。

      如果程序崩溃或重启,所有存储在内存中的数据都会丢失。所以我们需要把这些数据持久化

      到磁盘或保存到数据库中。

6.2、JDBCJobStore

        JDBCJobStore可以通过JDBC接口,将任务运行数据保存在数据库中。

        JDBC的实现方式有两种,JobStoreSupport类的两个子类:

        JobStoreTX:在独立的程序中使用,自己管理事务,不参与外部事务。

        JobStoreCMT:(Container Managed Transactions (CMT),如果需要容器管理事务时

                             ,使用它。

         如下图所示:

                

        注意:

                使用JDBCJobSotre时,需要配置数据库信息并创建对应的表结构

                在quartz-jobsb包下,路径 src\org\quartz\impl\jdbcjobstore 下,Quartz

                提供了各种数据库的sql文件,直接拿来执行就行了,如下图所示:

                           

                           

                数据库配置如下:

                       在配置文件 quartz.properties 中配置 数据源信息,如下所示:    


 
/**
  JobStore持久化配置:将Quartz的数据保存到数据库中的配置
*/
org.quartz.jobStore.class:org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass:org.quartz.impl.jdbcjobstore.StdJDBCDelegate
# 使用quartz.properties,不使用默认配置
org.quartz.jobStore.useProperties:true
#数据库中quartz表的表名前缀
org.quartz.jobStore.tablePrefix:QRTZ_
org.quartz.jobStore.dataSource:myDS
 
#配置数据源
org.quartz.dataSource.myDS.driver:com.mysql.jdbc.Driver
org.quartz.dataSource.myDS.URL:jdbc:mysql://localhost:3306/quartz?useUnicode=true&characterEncoding=utf8
org.quartz.dataSource.myDS.user:root
org.quartz.dataSource.myDS.password:123456
org.quartz.dataSource.myDS.validationQuery=select 0 from dual


                         

               

quartz 需要的表名称与作用如下:

表名作用
QRTZ_BLOB_TRIGGERSTrigger作为Blob类型存储
QRTZ_CALENDARS存储Quartz的Calendar信息
QRTZ_CRON_TRIGGERS存储CronTrigger,包括Cron表达式和时区信息
QRTZ_FIRED_TRIGGERS存储与已触发的Trigger相关的状态信息,以及相关Job的执行信息
QRTZ_JOB_DETAILS存储每一个已配置的Job的详细信息
QRTZ_LOCKS存储程序的悲观锁的信息
QRTZ_PAUSED_TRIGGER_GRPS存储已暂停的Trigger组的信息
QRTZ_SCHEDULER_STATE存储少量的有关Scheduler的状态信息,和别的Scheduler实例
QRTZ_SIMPLE_TRIGGERS存储SimpleTrigger的信息,包括重复次数、间隔、以及已触的次数
QRTZ_SIMPROP_TRIGGERS存储CalendarIntervalTrigger和DailyTimeIntervalTrigger两种类型的触发器
QRTZ_TRIGGERS存储已配置的Trigger的信息

                

                 

        

                          

          

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

141.环形链表 142.环形链表II

141.环形链表 & 142.环形链表II 141.环形链表 思路:快慢指针 or 哈希表 快慢指针代码: class Solution { public:bool hasCycle(ListNode *head) {if(headnullptr||head->nextnullptr)return false;ListNode *fasthead->next; //不能设置成…

软件项目体系建设文档,项目开发实施运维,审计,安全体系建设,验收交付,售前资料(word原件)

软件系统实施标准化流程设计至关重要,因为它能确保开发、测试、部署及维护等各阶段高效有序进行。标准化流程能减少人为错误,提升代码质量和系统稳定性。同时,它促进了团队成员间的沟通与协作,确保项目按时交付。此外,…

uniapp-vue3 实现, 一款带有丝滑动画效果的单选框组件,支持微信小程序、H5等多端

采用 uniapp-vue3 实现, 是一款带有丝滑动画效果的单选框组件,提供点状、条状的动画过渡效果,支持多项自定义配置,适配 web、H5、微信小程序(其他平台小程序未测试过,可自行尝试) 可到插件市场下载尝试&…

python vue3实现大文件分段续传(断点续传)--带暂停和继续功能

后端内容无变化具体设置可参考上一篇点击进入上一篇,需要注意的是big_file_upload_backend/settings.py下的 是statics 多个s其实无所谓,但是要一致 STATIC_URL "statics/" STATICFILES_DIRS [os.path.join(BASE_DIR, "../statics&quo…

STM32之CAN通讯(十一)

STM32F407 系列文章 - CAN通讯(十一) 目录 前言 一、CAN 二、CAN驱动电路 三、CAN软件设计 1.CAN状态初始化 2.头文件相关定义 3.接收中断服务函数 4.用户层使用 1.用户层相关定义 2.发送数据 3.接收数据 1.查询方式处理 2.中断方式处理 3…

初学Linux电源管理

学习文档出处: 万字整理 | 深入理解Linux电源管理:万字整理 | 深入理解Linux电源管理-CSDN博客 电源管理 因为设备需要用电,而且设备中的各个硬件所需要的电压是不一样的。故计算机需要对硬件的电源状态管理。但是电能并不是免费的&#x…

若依中Feign调用的具体使用(若依微服务版自身已集成openfeign依赖,并在此基础上定义了自己的注解)

若依中Feign调用具体使用 注意:以下所有步骤实现的前提是需要在启动类上加入注解 EnableRyFeignClients 主要是为开启feign接口扫描 1.创建服务提供者(provider) 导入依赖(我在分析依赖时发现若依本身已经引入openfeign依赖,并在此基础上自定义了自己的EnableRyF…

CS·GO搬砖流程详细版

说简单点,就是Steam买了然后BUFF上卖,或许大家都知道这点,但就是一些操作和细节问题没那么明白。我相信,你看完这篇文章以后,至少会有新的认知。 好吧,废话少说,直接上实操! 首先准…

每日一题:链表中环的入口结点

文章目录 判断链表环的入口节点描述数据范围:复杂度要求:输入输出 示例代码实现思路解析注意事项: 判断链表环的入口节点 描述 给定一个链表,判断该链表是否存在环。如果存在环,返回环的入口节点;如果不存…

以C++为基础快速了解C#

using System: - using 关键字用于在程序中包含 System 命名空间。 一个程序一般有多个 using 语句, 相当于C的 using namespace std; C# 是大小写敏感的。 所有的语句和表达式必须以分号(;)结尾。 程序的执行从 Main 方法开始。 与 Java 不同的是&#…

保险丝驱动电路·保险丝有什么用应该如何选型详解文章!!!

目录 保险丝基础知识 保险丝常见类型 保险丝功能讲解 保险丝驱动电路 ​​​​​​​ ​​​​​​​ 编写不易,仅供学习,请勿搬运,感谢理解 常见元器件驱动电路文章专栏连接 LM7805系列降压芯片驱动电路降压芯片驱动电…

如何在读博过程中缓解压力

博士生涯充满了挑战和压力,但通过一些实用的方法,我们可以有效地缓解这些压力。以下是我在博士期间采用的一些策略,希望能对正在读博或即将开始博士生涯的你有所帮助。 1. 周末彻底放松 在周末,我尽量避免进行论文写作。这两天…

ue5 替换角色的骨骼网格体和动画蓝图

一开始动画蓝图,骨骼网格体都是用的女性角色 现在把它换成男性 编译 保存 运行 把动画类换成ABP_Manny 进入ABP_Manny中 进入到idle 找到这个拖进来 编译 就变成站着端枪 运行一下,没有问题

西南大学计算机复试该怎么准备?有哪些注意事项?

西南大学计算机专业复试只有面试!只要你表现的自信大方,专业知识问题回答的很好,一般都没问题 一、考试内容 复试的考核内容包含以下几个方面: 1.专业素质和能力(占复试成绩的60%) (1&#x…

【UI自动化测试】selenium八种定位方式

🏡个人主页:謬熙,欢迎各位大佬到访❤️❤️❤️~ 👲个人简介:本人编程小白,正在学习互联网求职知识…… 如果您觉得本文对您有帮助的话,记得点赞👍、收藏⭐️、评论💬&am…

RDD的相关算子

一,算子的分类 整个DRR算子分为两大类: Transformation(转换算子): 返回值:是一个新的DRR 特点:转换算子只是定义数据的处理规则,并不会立刻执行,是lazy(…

简单编程实现QT程序黑色主题显示

代码如下 int main(int argc, char *argv[]) {QApplication a(argc, argv);//QSurfaceFormat::setDefaultFormat(QVTKOpenGLStereoWidget::defaultFormat());QPalette darkpalette;a.setStyle(QStyleFactory::create("Fusion"));darkpalette.setColor(QPalette::Wind…

【Redis】简介|优点|使用场景|为什么Redis快

目录 一、简介 二、特性(优点) 三、使用场景 一、简介 内存中存储数据的中间件,用于数据库,数据缓存,在分布式系统中能够大展拳脚 中间件:应用程序可以直接从 Redis 中获取数据,而不必频繁地…

封装深拷贝方法

前言 在今年的四月份我写了一篇有关深拷贝的博客文章 我与深拷贝_radash 深拷贝-CSDN博客。在该文章中有一个令我感到遗憾的点就是我没有实现一个自己手写的深拷贝。如今我想弥补当初的遗憾,在这篇文章中详细的讲述一下如何手写一个深拷贝方法。 lodash中是如何实…

maven多模块项目编译一直报Failure to find com.xxx.xxx:xxx-xxx-xxx:pom:1.0-SNAPSHOT in问题

工作中项目上因为多版本迭代,需要对不同迭代版本升级版本号,且因为项目工程本身是多模块结构,且依然多个其他模块工程。 在将工程中子模块的pom.xml中版本号使用变量引用父模块中定义的版本号时,一直报Failure to find com.xxx.x…