quartz 使用手册
📄字数 10.6K
👁️阅读量 加载中...
本文将介绍在 spring-boot-web 应用中如何使用原生 quartz v2.3.2 连接 XuguDB,测试动态控制定时任务的启动、添加、修改、暂停、重启、删除等操作,以及配置文件中各个属性配置是否兼容。
spring-boot-starter-quartz 是 Spring Boot 官方提供的 Starter,它基于 Quartz 官方版本进行了封装和扩展,本文不做讨论。
框架名称 | 适配起始版本 | 官网地址 | 源框架下载地址 | XuguDB框架下载 | demo程序地址 |
---|---|---|---|---|---|
quartz | 1.8.0 | quartz官网 | quartz源码 | 版本发布 | xugu-quartz |
提示
其他支持版本可详见版本发布列表
一、使用说明
目前已支持版本中使用 quartz 连接 XuguDB,只需执行数据库初始化文件 tables_xugu.sql
,程序中代码无需变更。
虚谷对 quartz 提供了两种获取方式,在线获取数据库执行 SQL 文件和源码 install 进行本地 maven 仓库部署。
1.1 在线获取数据库执行 SQL 文件
quartz框架的接口功能是支持虚谷数据库通过JDBC建立连接,只需要改动其初始化sql脚本即可。
V2.3.0 ~ V2.3.2 版本中,数据库执行文件
tables_xugu.sql
存放在.\quartz-core\src\main\resources\org\quartz\impl\jdbcjobstore\
目录中。图 1.1 在线获取V2.3.0~V2.3.2数据库执行文件
V2.2.0 ~ V2.2.3 版本中,数据库执行文件
tables_xugu.sql
存放在.\distribution\src\main\assembly\root\docs\dbTables\
目录下。图 1.2 在线获取V2.2.0~V2.2.3数据库执行文件
V1.8.0 ~ V2.1.7 版本中,数据库执行文件
tables_xugu.sql
存放在.\docs\dbTables\
目录下。图 1.3 在线获取V1.8.0~V2.1.7数据库执行文件
1.2 V2.3.0 ~ V2.3.2 本地 maven 仓库部署
低版本不支持源码 install 进行本地 maven 仓库部署,最低版本要求 V2.3.0
。
访问虚谷数据库开放源代码仓库,选择所需版本分支。
图 1.4 虚谷quartz仓库分支选择
直接下载当前分支源码(本地未安装 Git)。
图 1.5 虚谷quartz分支代码下载
使用命令
mvn clean install -Dmaven.test.skip=true
本地 Maven 仓库部署,出现BUILD SUCCESS
即执行成功。图 1.6 maven本地部署quartz
二、连接示例
2.1 前提条件
- 计算机已安装 JDK 1.8 和 Maven。
- 计算机已安装 IntelliJ IDEA。
- 计算机已安装 DBManager 或者 xgconsole。
- 计算机已安装 Apifox 或者 postman
- 计算机已部署 XuguDB 12.0.0 或有能连接访问的虚谷数据库实例。
提示
本文档示例程序运行使用的软件为 IntelliJ IDEA 2025.1.2 (Community Edition),也可以按照自己的喜好选择其它开发工具运行此示例程序。
2.2 操作步骤
- 导入
xugu-quartz
项目到 IDEA 中。 - 修改
xugu-quartz
项目中数据库连接信息。 - 运行
xugu-quartz
项目。
提示
本文是在 Windows 环境中进行操作说明的,如果使用的是其它操作环境,那么与本文中的步骤可能存在不同。
2.2.1 导入 xugu-quartz 项目到 IDEA 中
参考 IntelliJ IDEA 官方文档,导入项目。
- 启动 IntelliJ IDEA。 如果欢迎屏幕打开,请选择左侧栏目中项目(Projects)-> 右侧选项打开(Open)。 否则,请转到左上角主菜单的 文件(File)-> 打开(Open)。
- 在打开的对话框中,选择下载的源代码、库目录下的二级目录
xugu-quartz2.3.2
,然后点击 Select Folder 打开。
项目结构设置。
更改项目 SDK 设置:参考 SDK | IntelliJ IDEA 文档,请点击右上角工具栏上的齿轮⚙设置按钮并选择项目结构按钮(Project Structure...)。 或者,前往 文件(File)-> 项目结构(Project Structure...) 或按
Ctrl
+Alt
+Shift
+S
。图 2.1 xugu-quartz2.3.2项目JDK设置
项目 Maven 设置:参考 Maven | IntelliJ IDEA 文档,文件 -> 设置 -> 构建、执行、部署 -> 构建工具 -> Maven。
图 2.2 xugu-quartz2.3.2项目Maven设置
检查
pom.xml
依赖设置。图 2.3 xugu-quartz2.3.2依赖设置
提示
quartz-2.3.2.jar
来自步骤1.2 本地 Maven 仓库部署,亦可直接引用本地 Maven 仓库。
2.2.2 修改 xugu-quartz 项目中数据库连接信息
执行示例项目中
xugu-quartz2.3.2/sql/
目录中createDatabase.sql
,创建数据库。sql-- 在SYSTEM下执行 CREATE DATABASE `quartz` CHARACTER SET 'utf8_general_ci' TIME ZONE 'GMT+08:00';
可选择执行
tables_xugu.sql
手动创建所需表,也可在xugu-quartz2.3.2/src/main/resources/application.yml
中配置spring.quartz.jdbc.initialize-schema = ALWAYS
。提示
已执行步骤1.2 本地 Maven 仓库部署,可忽略此步骤。
配置spring.quartz.jdbc.initialize-schema = ALWAYS
表示每次重启应用时执行tables_xugu.sql
。修改
xugu-quartz2.3.2/src/main/resources/application.yml
文件中的数据库连接信息。yamlserver: # 程序的 HTTP 服务器监听的端口号 port: 8080 spring: jackson: # JSON 中日期格式 date-format: yyyy-MM-dd HH:mm:ss # 时区 time-zone: Asia/Shanghai datasource: # 数据库url连接 url: jdbc:xugu://127.0.0.1:5138/quartz # 数据库用户名 username: SYSDBA # 数据库密码 password: SYSDBA # 数据库驱动类名 driver-class-name: com.xugu.cloudjdbc.Driver # 数据库连接池类名称 type: com.alibaba.druid.pool.DruidDataSource druid: # 初始化连接池大小 initialSize: 5 # 最小连接数 minIdle: 10 # 最大连接数 maxActive: 20 # 获取连接时的最大等待时间,超过该时间则抛出异常 maxWait: 6000 # 间隔多久才进行一次检测,检测需要关闭的空闲连接 time-between-eviction-runs-millis: 2000 # 连接在被清理前的最小空闲时间 # 如果此时minEvictableIdleTimeMillis还没有赋值,则使用默认值1800000 min-evictable-idle-time-millis: 600000 max-evictable-idle-time-millis: 1800000 # 心跳检测语句 validationQuery: SELECT 1 testWhileIdle: true # 申请连接时执行validationQuery检测连接是否有效,默认true,开启后会降低性能 testOnBorrow: false # 归还连接时执行validationQuery检测连接是否有效,默认false,开启后会降低性能 testOnReturn: false keep-alive: true quartz: ### quartz v2.3.0-V2.3.2可以配置 ALWAYS 进行第一次初始化数据库表,然后改为 NEVER,springBoot集成版本默认为2.3.2 ### v1.8.0-v2.2.2只能设置 NEVER 并手动创建表 jdbc: initialize-schema: NEVER # spring framework 不识别虚谷 platform: xugu # 作业存储类型,默认存储在内存中 job-store-type: jdbc ### 优先级较下面properties配置中高 scheduler-name: MyScheduler properties: org: quartz: scheduler: ### 用于在同一程序中使用多个实例时区分调度程序 # instanceName: aaa ### 集群模式下:对于所有调度程序必须是唯一的,AUTO自动生成,SYS_PROP则来自系统属性 org.quartz.scheduler.instanceId,默认'NON_CLUSTERED' # instanceId: AUTO ### 设置AUTO时:默认实现为主机名和时间戳生成实例Id # instanceIdGenerator: # class: org.quartz.simpl.SimpleInstanceIdGenerator ### 默认用Scheduler的名字(org.quartz.scheduler.instanceName)加上字符串“_QuartzSchedulerThread” threadName: MyQuartzThread ### 表明scheduler的主线程是否为守护线程 # makeSchedulerThreadDaemon: false ### 指定 Quartz 生成的线程是否将继承上下文初始化线程(初始化 Quartz 实例的线程)的 ClassLoader # threadsInheritContextClassLoaderOfInitializer: false ### 调度程序在重新查询可用触发器之前将等待的时间量(以毫秒为单位),除非使用 XA 事务,否则不必调整此参数 # idleWaitTime: 30000 ### 当检测到失去与JobStore(或数据库)的连接时,scheduler重连的等待时间(单位毫秒) # dbFailureRetryInterval: 15000 ### 默认为最稳定的方法,它会使用其它的ClassLoadHelper类,直到有一个工作。所有当前实现的ClassLoadHelper都位于org.quartz.simpl包下。 # classLoadHelper: # class: org.quartz.simpl.CascadingClassLoadHelper ### jobFactory负责生成Job实例。 # jobFactory: # class: org.quartz.simpl.PropertySettingJobFactory ### 只有使用JobStoreCMT且org.quartz.scheduler.wrapJobExecutionInUserTransaction为true时,才需要配置这个属性。 ### Websphere用户需要将它设置为“jta/usertransaction” # userTransactionURL: java:comp/UserTransaction ### 如果想要在执行Job之前启动一个UserTransaction,那么这个值就需要设置true。在Job执行完成且JobDataMap更新完成(有状态Job)之后,事务就会条提交。 ### 也可能对在Job类上使用@ExecuteInJTATransaction # wrapJobExecutionInUserTransaction: false ### 是否跳过快速访问web请求,以确定是否需要下载Quartz的更新版本。在启动命令行用-D参数指定。 # skipUpdateCheck: true ### Scheduler一次获取trigger的最大数量,这个数字越大,触发效率越高(在有许多trigger需要同时触发的场景下) ### 如果这个属性的值大于1,且使用JDBCJobStore,那么属性“org.quartz.jobStore.acquireTriggersWithinLock”必须设置true,以避免数据损坏。 # batchTriggerAcquisitionMaxCount: 1 ### 允许trigger在调度时间之前获取和触发的时间(单位毫秒),默认0。 ### 这个数字越大,批量获取要触发的trigger且在同一时刻触发一个以上的trigger的可能性越大,但是以不精确调度为代价的(triggers可能提前触发)。 # batchTriggerAcquisitionFireAheadTimeWindow: 0 ### 没有基本属性是必需的,都有默认值。 rmi: ### 通过 RMI 将自身导出为服务器(默认false) export: true ### 可以找到RMI注册表的主机 # registryHost: localhost ### 默认RMI注册表监听的端口 # registryPort: 1099 ### true或as_needed:让Quartz第一次尝试使用已有的注册表,然后创建一个 ### never或false(默认):不想让Quartz创建注册表 ### always:要Quartz尝试创建一个注册表,然后使用它 createRegistry: true ### Quartz Scheduler服务绑定和监听连接的端口。默认情况下,RMI服务会随机选择一个端口将scheduler绑定到RMI注册表。 # serverPort: ### 表示键-值对,它会作为字符串放入SchedulerContext中(参见Scheduler.getContext()) context: key: MyKey: MyValue dataSource: ### springBoot2.5.7及之后jobStore配置了 JobStoreTX 需要再设置以下此 dataSource # myDS: # driver: ${spring.datasource.driver-class-name} # URL: ${spring.datasource.url} # user: ${spring.datasource.username} # password: ${spring.datasource.password} # maxConnections: 10 # validationQuery: SELECT 1 FROM DUAL ### 空闲连接测试的时间(单位秒) # idleConnectionValidationSeconds: 50 ### 是否每一次从数据源连接池中获取连接时,都要去数据库执行SQL查询,以确保连接有效。如果为false,那么将在check-in时验证。默认值为false。 # validateOnCheckout: false ### 丢弃连接的超时时间。若值为0,则禁止这个特性。默认值为0。 # discardIdleConnectionsSeconds: 0 ### 自定义org.quartz.utils.ConnectionProvider实现,然后自动按照JavaBean风格设置它的配置属性 # connectionProvider: # class: com.example.demo.config.DruidConnectionProvider jobStore: ### 1、====================================================================================================================================================================== ### SpringBoot V2.5.7 之前可配置 org.quartz.impl.jdbcjobstore.JobStoreTX;默认可省略则为 LocalDataSourceJobStore ### v2.5.7及之后默认是 org.springframework.scheduling.quartz.LocalDataSourceJobStore,可省略(使用的是JobStoreCMT) # class: org.quartz.impl.jdbcjobstore.JobStoreTX ### 2、====================================================================================================================================================================== ### JobStoreCMT依赖于使用Quartz的应用管理的事务 # class: org.quartz.impl.jdbcjobstore.JobStoreCMT ### JobStoreCMT需要第二个数据源,它包含一些不受容器管理的事务。这个属性的值必须是配置文件中DataSource的名字。这个数据源必须包含非CMT连接。 # nonManagedTXDataSource: myDS ### 与org.quartz.jobStore.dontSetAutoCommitFalse属性一样,只是它适用于nonManagedTXDataSource。 # dontSetNonManagedTXConnectionAutoCommitFalse: false ### 当设置为“true”时,该属性告诉Quartz在非托管JDBC连接上调用setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED)。这有助于防止某些数据库(如DB2)在高负载和“长时间”事务下出现锁超时。 # txIsolationLevelReadCommitted: false ### 不同数据库方言驱动代理 # driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate ### 与spring.quartz.properties.org.quartz.dataSource对应 # dataSource: myDS ### 表前缀不同,同一个数据库可以创建多个数据表 # tablePrefix: QRTZ_ ### 设置为true时,JDBCJobStore,JobDataMaps中的值都是字符串,因此这样可以以名字-值对存储,而不是存储更加复杂的对象(序列化形式BLOB) # useProperties: false ### Scheduler可以忍受未被调度的时间与下一次执行的时间的阈值,如果超出这个阈值,就不会被重新调用(单位毫秒)。默认值为60秒。 # misfireThreshold: 60000 ### 设置为“true”以开启集群特性。如果有多个Quartz实例使用同一组数据库表,这个属性必须设置为“true”。 # isClustered: true ### 设置当前实例check in集群中其它实例的频率(毫秒)。影响检测到故障实例的速度。 # clusterCheckinInterval: 15000 ### JobStore每次可以执行的最大misfired的触发器数.如果设置很大的话,同时处理多个trigger会引发数据表长时间锁定,触发其它的trigger(还没有失败)的性能就会受到限制。 # maxMisfiresToHandleAtATime: 20 ### 将这个参数设置为true,就是告诉Quartz不要调用DataSource获取的连接的setAutoCommit(false)方法。(默认false) # dontSetAutoCommitFalse: false ### 必须是一个字符串,在LOCKS表中选择一行,然后再这一行放一把锁。“{0}”由上面的配置的TABLE_PREFIX在运行时替换,而“{1}”由scheduler的名字替换。 # selectWithLockSQL: "SELECT * FROM {0}LOCKS WHERE SCHED_NAME = {1} AND LOCK_NAME = ? FOR UPDATE" ### 值“true”告诉Quartz(当使用JobStoreTX或CMT时)在JDBC连接上调用setTransactionlsolation(Connection.TRANSACTION_SERIALIZABLE)。这有助于防止某些数据库在高负载和“长时间”事务下的锁定超时。 # txIsolationLevelSerializable: false ### 是否在数据库锁内获取下一个要触发的trigger。在之前的Quartz版本中,为避免死锁必须用它,但是现在不再是必要了,默认值为false。 ### 在Quartz 2.1.1中,如果batchTriggerAcquisitionMaxCount大于1,且使用了JDBC JobStore,那么默认值就是true。 # acquireTriggersWithinLock: false ### 这是一个高级配置特性,大多数用户不应该使用它。默认情况下,Quartz会选择最合适的Semaphore实现。 # lockHandler: # class: ### 由“|”分割的属性(和它们的值),在初始化时,传递给DriverDelegate。 # driverDelegateInitString: threadPool: ### 使用ThreadPool的实现的名字 class: org.quartz.simpl.SimpleThreadPool ### 可以是任意的正整数。实际上只有1到100非常实用。 threadCount: 15 ### 1-10之间,默认5 # threadPriority: 5 ### 自定义线程池可以通过反射设置属性 # somePropOfFooThreadPool: someValue ### 特定于 SimpleThreadPool 的属性: ### 线程池中线程名字的前缀,最后附加一个数字。 threadNamePrefix: MyQuartzPool ### 可以设为true,那么线程池中创建的线程都是守护线程。 # makeThreadsDaemons: false ### 初始化线程池时,新创建的线程是否应该继承初始化线程的线程组。 # threadsInheritGroupOfInitializingThread: true ### 新创建的 Quartz 线程是否应该继承初始化线程的上下文类加载器(Context ClassLoader) # threadsInheritContextClassLoaderOfInitializingThread: false ### 通过配置文件配置监听器主要包括指定一个名字,然后指定类名,以及其它需要设置的属性。 ### 这个类必须有一个无参数构造器,且属性是分别设置的。只支持基本数据类型(包括String)。 ### 配置全局 TriggerListener triggerListener: myGlobalTriggerListener: class: com.example.demo.listener.global.DefaultGlobalTriggerListener # propName: propValue ### 配置全局 JobListener jobListener: myGlobalJobListener: class: com.example.demo.listener.global.DefaultGlobalJobListener # propName: propValue plugin: ### 此插件会捕获Trigger事件,相当于监听器 # triggHistory: # class: org.quartz.plugins.history.LoggingTriggerHistoryPlugin # triggerFiredMessage: 'Trigger {1}.{0} fired job {6}.{5} at: {4, date, HH:mm:ss MM/dd/yyyy}' # triggerCompleteMessage: 'Trigger {1}.{0} completed firing job {6}.{5} at {4, date, HH:mm:ss MM/dd/yyyy}.' ### 此插件从XML文件中读取job和trigger,并将它们添加到scheduler中。它也可以删除已有的数据 # jobInitializer: # class: org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin # fileNames: job/my_job_data.xml # failOnFileNotFound: true # wrapInUserTransaction: false # scanInterval: 120 ### shutdown-hook 插件捕获 JVM 终止的事件,并在调度程序上调用 shutdown。 # shutdownhook: # class: org.quartz.plugins.management.ShutdownHookPlugin # cleanShutdown: true
提示
官方文档链接:Quartz 配置参考
2.2.3 运行 xugu-quartz 项目
2.2.3.1 运行路径
在项目路径
xugu-quartz2.3.2/src/main/java/com/example/demo/QuartzDemoApplication.java
中运行主启动类。图 2.4 xugu-quartz2.3.2项目运行路径
第一次运行,需要创建所需表结构,默认以
QRTZ_
开头。测试方法存放于
xugu-quartz2.3.2/src/main/java/com/example/demo/controller/QuartzDemoController.java
目录文件中,通过 HTTP 请求调用。图 2.5 xugu-quartz2.3.2测试入口
按照
QuartzDemoController.java
中注释信息引导,依次测试创建触发器和任务、暂停和执行任务以及删除任务等。
2.2.3.2 创建/删除任务
通过 Post 请求接口
http://localhost:8080/task/simpleJob
调用com.example.demo.controller.QuartzDemoController#createScheduleSimpleJob
方法创建简单任务group2.job2
。图 2.6 使用Apifox测试xugu-quartz创建简单任务
等待任务执行,触发器生命周期监听器
DefaultGlobalTriggerListener.java
在控制台打印group2.job2
执行信息。图 2.7 简单任务与触发器日志记录
logback-spring.xml
中设置日志级别为debug
,重启应用。图 2.8 xugu-quartz2.3.2日志级别变更
通过 Delete 请求接口
http://localhost:8080/task/deleteJob
调用com.example.demo.controller.QuartzDemoController#deleteScheduleJob
方法删除任务group2.job2
。图 2.9 使用Apifox测试xugu-quartz删除任务
调度器生命周期监听器
DefaultGlobalSchedulerListener.java
在控制台打印group2.job2
执行信息图 2.10 监听调度器日志记录
2.2.3.3 使用 RMI 进行远程作业调度介绍
远程客户端配置信息
xugu-quartz2.3.2/src/main/resources/quartz.properties
。properties### 提供给com.example.demo.client.RemoteClientExample使用 ### 远程需要配置RMI org.quartz.scheduler.instanceName=MyScheduler ### 如果想要连接到远端提供服务的scheduler,那么将org.quartz.scheduler.rmi.proxy标志设置为true。 ### 在同一个配置文件中,将org.quartz.scheduler.rmi.export和org.quartz.scheduler.rmi.proxy都设置为true是没有意义的。(两者默认false) org.quartz.scheduler.rmi.proxy=true org.quartz.scheduler.rmi.registryHost=localhost org.quartz.scheduler.rmi.registryPort=1099
远程客户端创建任务。
图 2.11 远程客户端使用
三、常见问题&解决办法
启动项目失败,报错:相关表不存在
- 手动执行
xugu-quartz2.3.2/sql/tables_xugu.sql
脚本文件
- 手动执行
Spring Boot 中管理了 Quartz 的版本,使用其它版本时,必须指定 quartz 的版本号