首页 > 运维 > linux运维 > 正文

玩转 Spring Boot 集成篇(定时任务框架Quartz)

星夢妙者
发布: 2025-07-14 10:18:01
原创
1075人浏览过

在日常项目研发中,定时任务可谓是必不可少的一环,关于 spring boot 如何实现静态定时任务、动态定时任务以及如何开启多线程跑任务,均已在上篇分享过,不再赘述。

虽然 Spring Boot 内置注解方式实现的定时任务,在一定程度上也能解决一定的业务场景问题,但是若做更复杂的动作,例如启停任务、删除任务等等操作,实现起来则稍显复杂,此时便可以通过集成开源任务框架来实现。

常见的定时任务框架有 Quartz、elastic-job、xxl-job等等,本次主要介绍 Spring Boot 集成定时任务第 3 部分:Spirng Boot 集成 Quartz 定时任务框架。

玩转 Spring Boot 集成篇(定时任务框架Quartz)

Quartz 存储方式有两种:MEMORY 和 JDBC。默认是内存形式维护任务信息,意味着服务重启了任务就从头再来,就像喝酒断片了一样;而 JDBC 形式就是能够把任务信息持久化到数据库,虽然服务重启了,依然还能接着来。

Quartz 提供了单机版和集群版,默认就是单机版,接下来逐一分享一波。

Spring Boot 集成 Quartz 的方式也很简单,首先引入封装好的 Quartz 依赖。

代码语言:javascript代码运行次数:0运行复制
<code class="javascript"><!-- 引入 Quartz 依赖--><dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-quartz</artifactId></dependency></code>
登录后复制

1. 内存方式存储任务信息

1.1 定义任务类

可以通过实现 Job 接口来定义任务,也可以通过继承 QuartzJobBean 这个抽象类来定义任务,其实 QuartzJobBean 本身也实现了 Job 接口,其本质都是实现 Job 接口来定义任务。

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;import org.springframework.scheduling.quartz.QuartzJobBean;/** * 定义任务 */public class DongAoJob extends QuartzJobBean {    private static final Log logger = LogFactory.getLog(DongAoJob.class);    @Override    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {        logger.info("幼年是盼盼,青年是晶晶,中年是冰墩墩,生活见好逐渐发福");    }}</code>
登录后复制

1.2 定义任务描述及任务触发规则

定义每隔 5 秒执行一次任务,代码如下。

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">import com.example.demo.quartz.task.DongAoJob;import org.quartz.*;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;/** * 定义任务描述和具体的执行时间 */@Configurationpublic class QuartzConfig {    @Bean    public JobDetail jobDetail() {        //指定任务描述具体的实现类        return JobBuilder.newJob(DongAoJob.class)                // 指定任务的名称                .withIdentity("dongAoJob")                // 任务描述                .withDescription("任务描述:用于输出冬奥欢迎语")                // 每次任务执行后进行存储                .storeDurably()                .build();    }        @Bean    public Trigger trigger() {        //创建触发器        return TriggerBuilder.newTrigger()                // 绑定工作任务                .forJob(jobDetail())                // 每隔 5 秒执行一次 job                .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(5))                .build();    }}</code>
登录后复制

1.3 程序入口 main 函数

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplicationpublic class DemoJobApplication {    public static void main(String[] args) {        SpringApplication.run(DemoJobApplication.class, args);    }}</code>
登录后复制

1.4 运行验证

玩转 Spring Boot 集成篇(定时任务框架Quartz)

通过控制台输出能够看到每 5 秒输出一次信息,达到预期效果。

通过控制台标注 1 的部分能够看到默认采用的是 RAMJobStore,就是将任务相关信息保存在内存里,应用重启后,定时任务信息将会丢失。

2. 数据库方式存储任务信息

2.1 引入依赖

在 pom.xml 文件中加入如下依赖信息。

代码语言:javascript代码运行次数:0运行复制
<code class="javascript"><dependency>    <groupId>com.mchange</groupId>    <artifactId>c3p0</artifactId>    <version>0.9.5.4</version></dependency><!-- MySQL 驱动 --><dependency>    <groupId>mysql</groupId>    <artifactId>mysql-connector-java</artifactId></dependency></code>
登录后复制

2.2 添加 Quartz 配置信息

在 application.properties 文件中加入 Quartz 相关配置。

代码语言:javascript代码运行次数:0运行复制
<code class="javascript"># 将 Quartz 持久化方式修改为 jdbcspring.quartz.job-store-type=jdbc# 实例名称(默认为quartzScheduler)spring.quartz.properties.org.quartz.scheduler.instanceName=SC_Scheduler# 实例节点 ID 自动生成spring.quartz.properties.org.quartz.scheduler.instanceId=AUTO# 修改存储内容使用的类spring.quartz.properties.org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX# 数据源信息spring.quartz.properties.org.quartz.jobStore.dataSource=quartz_jobsspring.quartz.properties.org.quartz.dataSource.quartz_jobs.driver=com.mysql.cj.jdbc.Driverspring.quartz.properties.org.quartz.dataSource.quartz_jobs.URL=jdbc:mysql://127.0.0.1:3306/quartz_jobs?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8spring.quartz.properties.org.quartz.dataSource.quartz_jobs.user=rootspring.quartz.properties.org.quartz.dataSource.quartz_jobs.password=123456</code>
登录后复制

2.3 初始化 Quartz 数据表信息

下载 Quartz 发布包,下载完成后,解压缩进入 quartz-2.2.3/docs/dbTables 目录,找到匹配数据库的 SQL 文件。

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">下载地址:https://www.quartz-scheduler.org/downloads/files/quartz-2.2.3-distribution.tar.gz</code>
登录后复制

为了方便演示,单独创建 quartz_jobs 数据库。

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">create database quartz_jobs default charset utf8;use quartz_jobs;</code>
登录后复制

然后在数据库中执行 tables-mysql.sql 初始化脚本,脚本内容如下(来源于官网压缩包),先别细究每个表的意义,用起来才是硬道理。

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">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(200) NOT NULL,    JOB_GROUP VARCHAR(200) 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));CREATE TABLE QRTZ_TRIGGERS  (    SCHED_NAME VARCHAR(120) NOT NULL,    TRIGGER_NAME VARCHAR(200) NOT NULL,    TRIGGER_GROUP VARCHAR(200) NOT NULL,    JOB_NAME  VARCHAR(200) NOT NULL,    JOB_GROUP VARCHAR(200) 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(200) 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));CREATE TABLE QRTZ_SIMPLE_TRIGGERS  (    SCHED_NAME VARCHAR(120) NOT NULL,    TRIGGER_NAME VARCHAR(200) NOT NULL,    TRIGGER_GROUP VARCHAR(200) 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));CREATE TABLE QRTZ_CRON_TRIGGERS  (    SCHED_NAME VARCHAR(120) NOT NULL,    TRIGGER_NAME VARCHAR(200) NOT NULL,    TRIGGER_GROUP VARCHAR(200) NOT NULL,    CRON_EXPRESSION VARCHAR(200) NOT NULL,    TIME_ZONE_ID VARCHAR(80),    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));CREATE TABLE QRTZ_SIMPROP_TRIGGERS  (              SCHED_NAME VARCHAR(120) NOT NULL,    TRIGGER_NAME VARCHAR(200) NOT NULL,    TRIGGER_GROUP VARCHAR(200) NOT NULL,    STR_PROP_1 VARCHAR(512) NULL,    STR_PROP_2 VARCHAR(512) NULL,    STR_PROP_3 VARCHAR(512) NULL,    INT_PROP_1 INT NULL,    INT_PROP_2 INT NULL,    LONG_PROP_1 BIGINT NULL,    LONG_PROP_2 BIGINT NULL,    DEC_PROP_1 NUMERIC(13,4) NULL,    DEC_PROP_2 NUMERIC(13,4) NULL,    BOOL_PROP_1 VARCHAR(1) NULL,    BOOL_PROP_2 VARCHAR(1) 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));CREATE TABLE QRTZ_BLOB_TRIGGERS  (    SCHED_NAME VARCHAR(120) NOT NULL,    TRIGGER_NAME VARCHAR(200) NOT NULL,    TRIGGER_GROUP VARCHAR(200) NOT NULL,    BLOB_DATA BLOB 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));CREATE TABLE QRTZ_CALENDARS  (    SCHED_NAME VARCHAR(120) NOT NULL,    CALENDAR_NAME  VARCHAR(200) NOT NULL,    CALENDAR BLOB NOT NULL,    PRIMARY KEY (SCHED_NAME,CALENDAR_NAME));CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS  (    SCHED_NAME VARCHAR(120) NOT NULL,    TRIGGER_GROUP  VARCHAR(200) NOT NULL,     PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP));CREATE TABLE QRTZ_FIRED_TRIGGERS  (    SCHED_NAME VARCHAR(120) NOT NULL,    ENTRY_ID VARCHAR(95) NOT NULL,    TRIGGER_NAME VARCHAR(200) NOT NULL,    TRIGGER_GROUP VARCHAR(200) NOT NULL,    INSTANCE_NAME VARCHAR(200) NOT NULL,    FIRED_TIME BIGINT(13) NOT NULL,    SCHED_TIME BIGINT(13) NOT NULL,    PRIORITY INTEGER NOT NULL,    STATE VARCHAR(16) NOT NULL,    JOB_NAME VARCHAR(200) NULL,    JOB_GROUP VARCHAR(200) NULL,    IS_NONCONCURRENT VARCHAR(1) NULL,    REQUESTS_RECOVERY VARCHAR(1) NULL,    PRIMARY KEY (SCHED_NAME,ENTRY_ID));CREATE TABLE QRTZ_SCHEDULER_STATE  (    SCHED_NAME VARCHAR(120) NOT NULL,    INSTANCE_NAME VARCHAR(200) NOT NULL,    LAST_CHECKIN_TIME BIGINT(13) NOT NULL,    CHECKIN_INTERVAL BIGINT(13) NOT NULL,    PRIMARY KEY (SCHED_NAME,INSTANCE_NAME));CREATE TABLE QRTZ_LOCKS  (    SCHED_NAME VARCHAR(120) NOT NULL,    LOCK_NAME  VARCHAR(40) NOT NULL,     PRIMARY KEY (SCHED_NAME,LOCK_NAME));commit;</code>
登录后复制

2.4 运行验证

代码无需任何变动,直接运行 main 函数,控制台输出如下:

玩转 Spring Boot 集成篇(定时任务框架Quartz)

通过控制台输出发现任务正常跑起来,而且任务存储的方式变为了 jdbcjobstore.JobStoreTx,此时数据库表中也有任务信息插入了。

集简云
集简云

软件集成平台,快速建立企业自动化与智能化

集简云 22
查看详情 集简云
玩转 Spring Boot 集成篇(定时任务框架Quartz)

至此,Spring Boot 集成 Quartz 的两种存储任务方式就完事儿了,其实很简单,稍显复杂的多是 Quartz 相关的持久化依赖的 SQL 及配置信息。

但是,在某些业务场景下要求任务必须高可用、可扩展,那么单台服务器不能满足业务需求,这时就需要开启 Quartz 分布式定时任务啦。

3. 分布式任务支持

3.1 开启集群配置

在 application.properties 文件中,加入 Quartz 集群的配置信息。

代码语言:javascript代码运行次数:0运行复制
<code class="javascript"># 开启集群,多个 Quartz 实例使用同一组数据库表spring.quartz.properties.org.quartz.jobStore.isClustered=true</code>
登录后复制

注意 Quartz 使用同一组数据库表作集群时,只需要配置相同的 instanceName 实例名称就可以,例如本次都用 SC_Scheduler。

代码语言:javascript代码运行次数:0运行复制
<code class="javascript"> spring.quartz.properties.org.quartz.scheduler.instanceName=SC_Scheduler</code>
登录后复制

3.2 运行验证

为了方便启动多实例验证,把服务启动的端口进行随机生成,application.properties 文件加入配置如下。

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">server.port=${random.int[10000,19999]}</code>
登录后复制

直接运行 main 函数,启动实例 1;再次运行 main 函数,启动实例2(如果 IDEA 不让重复运行,那就重新复制一个启动类,再运行)。

玩转 Spring Boot 集成篇(定时任务框架Quartz)

通过红色圈住部分 is clustered,显然已是开启了集群。若关闭其中一个正在跑任务的节点,观察另一个节点是否会自动检测继续执行任务呢?

停掉节点 1:

玩转 Spring Boot 集成篇(定时任务框架Quartz)

节点 2 继续接着执行任务:

玩转 Spring Boot 集成篇(定时任务框架Quartz)

至此,Spring Boot 集成 Quartz 可以接近尾声了。

不过稍显不甘心呢,因为回头看代码,会发现 QuartzConfig 中的 job 和 trigger 都是硬编码方式完成的。

玩转 Spring Boot 集成篇(定时任务框架Quartz)

这样肯定无法管理任务的状态,无法做到扩展,更达不到 Spring Boot 的思想让程序员更专注业务开发,所以仍有改进的空间,仍存很多疑问。

疑问:是否可以通过 API 动态创建任务呢?

疑问:是否可以通过 API 编辑任务的执行时间呢?

疑问:是否可以通过 API 暂停/恢复任务呢?

疑问:是否可以通过 API 删除任务呢?

疑问:是否可以 ... ...

此时,可以这么回答:of course.Im very sure. 老鼠拉木锨——大头在后面呢,不过限于自定义代码较多,单独放一代码篇去分享。

4. 例行回顾

本文是 Spring Boot 项目集成 Quartz 定时任务框架讲解,主要分享了如下部分:

默认内存方式存储任务信息;数据库方式任务信息;分布式任务支持

玩转 Spring Boot 集成 Quartz 定时任务就写到这里,下次一起编码实现 Quartz 任务的动态管理。

历史系列文章:

以上就是玩转 Spring Boot 集成篇(定时任务框架Quartz)的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号