Springboot整合quartz

一 什么是Quartz

  Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用。Quartz可以用来创建简单或为运行十个,百个,甚至是好几万个Jobs这样复杂的程序。Jobs可以做成标准的Java组件或 EJBs。官网地址:https://www.quartz-scheduler.org/

特点如下

  • 纯java实现,可以作为独立的应用程序,也可以嵌入在另一个独立式应用程序运行
    强大的调度功能,Spring默认的调度框架,灵活可配置;
  • 作业持久化,调度环境持久化机制,可以保存并恢复调度现场。系统关闭数据不会丢失;灵活的应用方式,可以任意定义触发器的调度时间表,支持任务和调度各种组合,组件式监听器、各种插件、线程池等功能,多种存储方式等;
  • 分布式和集群能力,可以被实例化,一个Quartz集群中的每个节点作为一个独立的Quartz使用,通过相同的数据库表来感知到另一个Quartz应用

二 内部实现

在这里插入图片描述

1.核心概念

  1. Scheduler(任务调度器):实际执行任务调度的控制器,在spring中通过SchedulerFactoryBean封装起来

  2. Trigger(触发器): 任务的触发,触发器有SimpleTrigger,CronTrigger,DateIntervalTrigger和NthIncludedDayTrigger四种类型,其中SimpleTrigger:能够周期性的设置任务触发;CronTrigger:使用cron表达式的方式实现任务触发,实现更多样,使用场景也是最多的。其中任务和触发器的关系是:一个任务可以有多个触发器,一个触发器只能对应一个任务。

  3. JobDetail(定时任务的信息载体): 业务需要执行的任务操作,实现Job接口,或者继承QuartzJobBean,实现/重写里面的方法。

2.重要组成

  1. Job: 是一个接口只有一个方法,void execute(JobExecutionContext var1),JobExecutionContext这个类提供了调度上下文的各种信息,Job运行时的信息就保存在JobExecutionContext里的JobDataMap实例中。上文也提到了QuartzJobBean,QuartzJobBean跟Job一样也是用来实现自己的任务的,只不过QuartzJobBean是一个抽象类,用户可以继承该类去实现executeInternal这个抽象方法去实现自己的任务逻辑即可。
  2. JobDetail: Quartz在每次执行实例的时候都重新创建一个job实例,所以它不直接接受一个job实例,而是通过接受一个job实现类,以便运行时通过new Instance()的反射机制实例化job,因此需要通过一个类来描述job的实现类及其他相关静态信息,如job的名字,描述,关联监听器等信息。(即用来绑定job,并且在job执行的时候携带一些执行的信息)通过该类的构造函数可以更具体地了解它的功用:JobDetail(java.lang.String name, java.lang.String group, java.lang.Class jobClass),该构造函数要求指定Job的实现类,以及任务在Scheduler中的组名和Job名称;
  3. JobBuilder: 用来定义或者创建JobDetail的实例,JobDetail限定了只能是job的实例。
  4. JobStore: 接口,用来保存job数据,实现类主要有RAMJobStore,JobStoreTX,JobStoreCMT;
    JobStoreTX和JobStoreCMT均将数据保存在数据库中,RAMJobStore将数据保存在内存中,保存一些执行的信息。
  5. Trigger: 一个类,描述触发的job执行时的时间触发规则;主要有SimpleTrigger和CronTrigger两个子类。当仅触发一次或者以固定时间间隔周期执行时,使用SimpleTrigger;CronTrigger通过cron表达式,定义出各种复杂时间规则的调度方案,如每天早晨的固定时间执行,或周二周三的固定时间执行等需求。
  6. TriggerBuilder: 使用builder模式,用来定义或者创建触发器的实例
  7. ThreadPool: Timer有且只有一个后台线程在执行,Quartz的schedule下有ThreadPool整个线程池来运行,schedule使用线程池作为任务运行的基础设施,任务通过共享线程池中的线程提高运行的效率,从而解决并发问题.
  8. Scheduler: 调度器,代表Quartz的一个独立运行容器,Trigger和JobDetail可以注册Scheduler中,两者在Scheduler中拥有各自的组及名称,组及名称是Scheduler查找定位容器中某一对象的依据,Trigger的组及名称必须唯一,JobDetail的组和名称也必须唯一(但可以和Trigger的组和名称相同,因为它们是不同类型的)。Scheduler定义了多个接口方法,允许外部通过组及名称访问和控制容器中Trigger和JobDetail。Scheduler可以将Trigger绑定到某一JobDetail中,这样当Trigger触发时,对应的Job就被执行。一个Job可以对应多个Trigger,但一个Trigger只能对应一个Job。可以通过SchedulerFactory创建一个Scheduler实例。Scheduler拥有一个SchedulerContext,它类似于ServletContext,保存着Scheduler上下文信息,Job和Trigger都可以访问SchedulerContext内的信息。SchedulerContext内部通过一个Map,以键值对的方式维护这些上下文数据,SchedulerContext为保存和获取数据提供了多个put()和getXxx()的方法。可以通过Scheduler# getContext()获取对应的SchedulerContext实例
  9. Calendar: 一个Trigger可以和多个Calendar关联,以排除或包含某些时间点。比如某个任务希望放假时间不执行。
  10. 监听器:JobListener,TriggerListener,SchedulerListener;分别对Job,Trigger,Scheduler的事件进行监听,包括scheduler一运行起来的时候,或者在执行任务的时候,或终止的时候进行监听,监听的时候加入一些自定义的某些逻辑,比如打印日志信息。

3.数据存储和持久化

为什么要持久化?
  当程序突然被中断时,如断电,内存超出时,很有可能造成任务的丢失。 可以将调度信息存储到数据库里面,进行持久化,当程序被中断后,再次启动,仍然会保留中断之前的数据,继续执行,而并不是重新开始。
提供了两种存储方式:

  1. RAMJobStore:在默认情况下Quartz将任务调度的运行信息保存在内存中,这种方法提供了最佳的性能,因为内存中数据访问最快。不足之处是缺乏数据的持久性,当程序路途停止或系统崩溃时,所有运行的信息都会丢失。
  2. JobStoreTX:所有的任务信息都会保存到数据库中,可以控制事物,还有就是如果应用服务器关闭或者重启,任务信息都不会丢失,并且可以恢复因服务器关闭或者重启而导致执行失败的任务。

三 Springboot整合quartz

本示例:采用了springboot已经整合了quartz,如果用户是自己单独集成的,类似这样在这里插入图片描述
可寻找其他示例。

1. 添加Quartz依赖

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

<!-- mysql/mysql-connector-java -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.28</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

里面依赖了quartz的starter,以及mysql数据库,引入数据库的依赖目的是在于,后续quartz的job,trigger等,以及集群相关配置用到的锁,来控制任务集群模式下的重复执行等信息都是需要保存到数据库的,默认是放在内存中,内存中不利于管理,使用quartz的意义就不明显了。

2. mysql的建表sql:

#
# In your Quartz properties file, you'll need to set
# org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#
#
# By: Ron Cordell - roncordell
#  I didn't see this anywhere, so I thought I'd post it here. This is the script from Quartz to create the tables in a MySQL database, modified to use INNODB instead of MYISAM.
 
DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS;
DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE;
DROP TABLE IF EXISTS QRTZ_LOCKS;
DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_JOB_DETAILS;
DROP TABLE IF EXISTS QRTZ_CALENDARS;
 
CREATE TABLE QRTZ_JOB_DETAILS(
SCHED_NAME VARCHAR(120) NOT NULL,
JOB_NAME VARCHAR(190) NOT NULL,
JOB_GROUP VARCHAR(190) NOT NULL,
DESCRIPTION VARCHAR(250) NULL,
JOB_CLASS_NAME VARCHAR(250) NOT NULL,
IS_DURABLE VARCHAR(1) NOT NULL,
IS_NONCONCURRENT VARCHAR(1) NOT NULL,
IS_UPDATE_DATA VARCHAR(1) NOT NULL,
REQUESTS_RECOVERY VARCHAR(1) NOT NULL,
JOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP))
ENGINE=InnoDB;
 
CREATE TABLE QRTZ_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(190) NOT NULL,
TRIGGER_GROUP VARCHAR(190) NOT NULL,
JOB_NAME VARCHAR(190) NOT NULL,
JOB_GROUP VARCHAR(190) NOT NULL,
DESCRIPTION VARCHAR(250) NULL,
NEXT_FIRE_TIME BIGINT(13) NULL,
PREV_FIRE_TIME BIGINT(13) NULL,
PRIORITY INTEGER NULL,
TRIGGER_STATE VARCHAR(16) NOT NULL,
TRIGGER_TYPE VARCHAR(8) NOT NULL,
START_TIME BIGINT(13) NOT NULL,
END_TIME BIGINT(13) NULL,
CALENDAR_NAME VARCHAR(190) NULL,
MISFIRE_INSTR SMALLINT(2) NULL,
JOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP))
ENGINE=InnoDB;
 
CREATE TABLE QRTZ_SIMPLE_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(190) NOT NULL,
TRIGGER_GROUP VARCHAR(190) NOT NULL,
REPEAT_COUNT BIGINT(7) NOT NULL,
REPEAT_INTERVAL BIGINT(12) NOT NULL,
TIMES_TRIGGERED BIGINT(10) NOT NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
 
CREATE TABLE QRTZ_CRON_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT 
  • 22
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值