Skip to content

适用虚谷数据库版本

v12.9



适用虚谷数据库版本

v12.9


quartz 使用手册

📄字数 10.6K
👁️阅读量 加载中...

本文将介绍在 spring-boot-web 应用中如何使用原生 quartz v2.3.2 连接 XuguDB,测试动态控制定时任务的启动、添加、修改、暂停、重启、删除等操作,以及配置文件中各个属性配置是否兼容。
spring-boot-starter-quartz 是 Spring Boot 官方提供的 Starter,它基于 Quartz 官方版本进行了封装和扩展,本文不做讨论。

框架名称适配起始版本官网地址源框架下载地址XuguDB框架下载demo程序地址
quartz1.8.0quartz官网quartz源码版本发布xugu-quartz

提示

其他支持版本可详见版本发布列表

一、使用说明

目前已支持版本中使用 quartz 连接 XuguDB,只需执行数据库初始化文件 tables_xugu.sql,程序中代码无需变更。

虚谷对 quartz 提供了两种获取方式,在线获取数据库执行 SQL 文件和源码 install 进行本地 maven 仓库部署。

1.1 在线获取数据库执行 SQL 文件

quartz框架的接口功能是支持虚谷数据库通过JDBC建立连接,只需要改动其初始化sql脚本即可。

  1. V2.3.0 ~ V2.3.2 版本中,数据库执行文件 tables_xugu.sql 存放在 .\quartz-core\src\main\resources\org\quartz\impl\jdbcjobstore\ 目录中。

    在线获取V2.3.0~V2.3.2数据库执行文件图 1.1 在线获取V2.3.0~V2.3.2数据库执行文件
  2. V2.2.0 ~ V2.2.3 版本中,数据库执行文件 tables_xugu.sql 存放在 .\distribution\src\main\assembly\root\docs\dbTables\ 目录下。

    在线获取V2.2.0~V2.2.3数据库执行文件图 1.2 在线获取V2.2.0~V2.2.3数据库执行文件
  3. V1.8.0 ~ V2.1.7 版本中,数据库执行文件 tables_xugu.sql 存放在 .\docs\dbTables\ 目录下。

    在线获取V1.8.0~V2.1.7数据库执行文件图 1.3 在线获取V1.8.0~V2.1.7数据库执行文件

1.2 V2.3.0 ~ V2.3.2 本地 maven 仓库部署

低版本不支持源码 install 进行本地 maven 仓库部署,最低版本要求 V2.3.0

  1. 访问虚谷数据库开放源代码仓库,选择所需版本分支。

    虚谷quartz仓库分支选择图 1.4 虚谷quartz仓库分支选择
  2. 直接下载当前分支源码(本地未安装 Git)。

    虚谷quartz分支代码下载图 1.5 虚谷quartz分支代码下载
  3. 使用命令 mvn clean install -Dmaven.test.skip=true 本地 Maven 仓库部署,出现 BUILD SUCCESS 即执行成功。

    maven本地部署quartz图 1.6 maven本地部署quartz

二、连接示例

2.1 前提条件

  • 计算机已安装 JDK 1.8Maven
  • 计算机已安装 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 中

  1. 参考 IntelliJ IDEA 官方文档,导入项目。

    1. 启动 IntelliJ IDEA。 如果欢迎屏幕打开,请选择左侧栏目中项目(Projects)-> 右侧选项打开(Open)。 否则,请转到左上角主菜单的 文件(File)-> 打开(Open)。
    2. 在打开的对话框中,选择下载的源代码、库目录下的二级目录 xugu-quartz2.3.2,然后点击 Select Folder 打开。
  2. 项目结构设置。

    1. 更改项目 SDK 设置:参考 SDK | IntelliJ IDEA 文档,请点击右上角工具栏上的齿轮⚙设置按钮并选择项目结构按钮(Project Structure...)。 或者,前往 文件(File)-> 项目结构(Project Structure...) 或按 Ctrl+Alt+Shift+S

      xugu-quartz2.3.2项目JDK设置图 2.1 xugu-quartz2.3.2项目JDK设置
    2. 项目 Maven 设置:参考 Maven | IntelliJ IDEA 文档,文件 -> 设置 -> 构建、执行、部署 -> 构建工具 -> Maven。

      xugu-quartz2.3.2项目Maven设置图 2.2 xugu-quartz2.3.2项目Maven设置
  3. 检查 pom.xml 依赖设置。

    xugu-quartz2.3.2依赖设置图 2.3 xugu-quartz2.3.2依赖设置

    提示

    quartz-2.3.2.jar 来自步骤1.2 本地 Maven 仓库部署,亦可直接引用本地 Maven 仓库。

2.2.2 修改 xugu-quartz 项目中数据库连接信息

  1. 执行示例项目中 xugu-quartz2.3.2/sql/ 目录中 createDatabase.sql,创建数据库。

    sql
    -- 在SYSTEM下执行
    CREATE DATABASE `quartz` CHARACTER SET 'utf8_general_ci' TIME ZONE 'GMT+08:00';
  2. 可选择执行 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

  3. 修改 xugu-quartz2.3.2/src/main/resources/application.yml 文件中的数据库连接信息。

    yaml
    server:
      # 程序的 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 运行路径
  1. 在项目路径 xugu-quartz2.3.2/src/main/java/com/example/demo/QuartzDemoApplication.java 中运行主启动类。

    xugu-quartz2.3.2项目运行路径图 2.4 xugu-quartz2.3.2项目运行路径
  2. 第一次运行,需要创建所需表结构,默认以 QRTZ_ 开头。

  3. 测试方法存放于 xugu-quartz2.3.2/src/main/java/com/example/demo/controller/QuartzDemoController.java 目录文件中,通过 HTTP 请求调用。

    xugu-quartz2.3.2测试入口图 2.5 xugu-quartz2.3.2测试入口
  4. 按照 QuartzDemoController.java 中注释信息引导,依次测试创建触发器和任务、暂停和执行任务以及删除任务等。

2.2.3.2 创建/删除任务
  1. 通过 Post 请求接口 http://localhost:8080/task/simpleJob
    调用 com.example.demo.controller.QuartzDemoController#createScheduleSimpleJob 方法创建简单任务 group2.job2

    使用Apifox测试xugu-quartz创建简单任务图 2.6 使用Apifox测试xugu-quartz创建简单任务
  2. 等待任务执行,触发器生命周期监听器 DefaultGlobalTriggerListener.java 在控制台打印 group2.job2 执行信息。

    简单任务与触发器日志记录图 2.7 简单任务与触发器日志记录
  3. logback-spring.xml 中设置日志级别为 debug,重启应用。

    xugu-quartz2.3.2日志级别变更图 2.8 xugu-quartz2.3.2日志级别变更
  4. 通过 Delete 请求接口 http://localhost:8080/task/deleteJob
    调用 com.example.demo.controller.QuartzDemoController#deleteScheduleJob 方法删除任务 group2.job2

    使用Apifox测试xugu-quartz删除任务图 2.9 使用Apifox测试xugu-quartz删除任务
  5. 调度器生命周期监听器 DefaultGlobalSchedulerListener.java 在控制台打印 group2.job2 执行信息

    监听调度器日志记录图 2.10 监听调度器日志记录
2.2.3.3 使用 RMI 进行远程作业调度介绍
  1. 远程客户端配置信息 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. 远程客户端创建任务。

    远程客户端使用图 2.11 远程客户端使用

三、常见问题&解决办法

  1. 启动项目失败,报错:相关表不存在

    • 手动执行 xugu-quartz2.3.2/sql/tables_xugu.sql 脚本文件
  2. Spring Boot 中管理了 Quartz 的版本,使用其它版本时,必须指定 quartz 的版本号