一. Quartz 持久化之前的准备
一.一 为什么要持久化?
以前写的 Demo,包括 SSM整合 Quartz 框架,都不是持久化的,都是存储在内存里面的。 当程序突然被中断时,如断电,内存超出时,很有可能造成任务的丢失。 可以将调度信息存储到数据库里面,进行持久化,当程序被中断后,再次启动,仍然会保留中断之前的数据,继续执行,而并不是重新开始。
一.二 两种存储类型
Quartz 框架提供了两种任务存储的类型, 分别为 RAMJobStore 和 JobStoreTX
一.三 创建 持久化表
一.三.一 创建持久化表语句
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(100) NOT NULL, JOB_GROUP VARCHAR(100) 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(100) NOT NULL, TRIGGER_GROUP VARCHAR(100) NOT NULL, JOB_NAME VARCHAR(100) NOT NULL, JOB_GROUP VARCHAR(100) 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(100) 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(100) NOT NULL, TRIGGER_GROUP VARCHAR(100) 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(100) NOT NULL, TRIGGER_GROUP VARCHAR(100) NOT NULL, CRON_EXPRESSION VARCHAR(100) 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(100) NOT NULL, TRIGGER_GROUP VARCHAR(100) 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(100) NOT NULL, TRIGGER_GROUP VARCHAR(100) 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(100) 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(100) 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(100) NOT NULL, TRIGGER_GROUP VARCHAR(100) NOT NULL, INSTANCE_NAME VARCHAR(100) 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(100) NULL, JOB_GROUP VARCHAR(100) 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(100) 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;
放置到 老蝴蝶本地 quartz 数据库里面。
运行成功之后
共11个表,表名均以 qrtz_ 为前缀。
一.三.二 表关系
说明,从阿飞云前辈的博客里面复制的。
一.三.三 持久化表解释
说明,从阿飞云前辈的博客里面复制的。
一般项目中配置的都是 Cron 触发器, 需要记录 qrtz_cron_triggers 和 qrtz_job_details, qrtz_triggers 三个常用表。
二. Quartz 框架的持久化
二.一 复制配置信息 quartz.properties
Quartz 框架在运行时,需要一个配置文件 quartz.properties, 里面放置基本的配置信息。
该文件位于 quartz.jar 下面的 org.quartz 包下。
将该文件复制到 src/main/resource 目录下
# Default Properties file for use by StdSchedulerFactory # to create a Quartz Scheduler Instance, if a different # properties file is not explicitly specified. # org.quartz.scheduler.instanceName: DefaultQuartzScheduler org.quartz.scheduler.rmi.export: false org.quartz.scheduler.rmi.proxy: false org.quartz.scheduler.wrapJobExecutionInUserTransaction: false org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool org.quartz.threadPool.threadCount: 10 org.quartz.threadPool.threadPriority: 5 org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true org.quartz.jobStore.misfireThreshold: 60000 org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore
我们可以修改 resource目录下的 quartz.properties 属性文件内容 进行自定义配置。
org.quartz.jobStore.class,指的是 Quartz 的存储类型, 默认是 RAMJobStore, 存储在内存里面。
关于 quartz.properties 配置文件的信息,大家可以看 W3CSchool 关于 Quartz 部分的文章。
二.二 将类型转换成 JobStoreTX
JobStoreTX 全称是: org.quartz.impl.jdbcjobstore.JobStoreTX
# 注释掉内存存储 # org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore #持久化 org.quartz.jobStore.class:org.quartz.impl.jdbcjobstore.JobStoreTX
二.三 配置驱动代理
##驱动代理为 标准的jdbc org.quartz.jobStore.driverDelegateClass:org.quartz.impl.jdbcjobstore.StdJDBCDelegate
StdJDBCDelegate 为标准的jdbc。
二.四 配置数据库表前缀和数据源
#数据库表前缀 org.quartz.jobStore.tablePrefix:qrtz_ #数据源 org.quartz.jobStore.dataSource:yjlDB #JDBC驱动 org.quartz.dataSource.yjlDB.driver:com.mysql.jdbc.Driver org.quartz.dataSource.yjlDB.URL:jdbc:mysql://localhost:3306/quartz org.quartz.dataSource.yjlDB.user:root org.quartz.dataSource.yjlDB.password:您的数据库密码
其中, yjlDB 是数据源名称, 可以任意起一个, 但要与下面的 dataSource.Xxx 保持一致。
注意,这个时候,只是简单的 JavaSE 配置,并没有与 Spring进行整合,
所以数据库直接写在 quartz.properties 属性文件里面。
当与Spring 进行整合之后,直接拿 applicationContext-dao.xml 里面的数据源 dataSource 即可。
当配置 org.quartz.dataSource.yjlDB.maxConnection:10 时会报错,说没有 setMaxConnection() 方法。
这儿就不配置 org.quartz.dataSource.yjlDB.maxConnection 的值了。
二.五 最终 quartz.properties 配置文件内容
org.quartz.scheduler.instanceName: DefaultQuartzScheduler org.quartz.scheduler.rmi.export: false org.quartz.scheduler.rmi.proxy: false org.quartz.scheduler.wrapJobExecutionInUserTransaction: false org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool org.quartz.threadPool.threadCount: 10 org.quartz.threadPool.threadPriority: 5 org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true org.quartz.jobStore.misfireThreshold: 60000 # 注释掉内存存储 # org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore #持久化 org.quartz.jobStore.class:org.quartz.impl.jdbcjobstore.JobStoreTX ##驱动代理为 标准的jdbc org.quartz.jobStore.driverDelegateClass:org.quartz.impl.jdbcjobstore.StdJDBCDelegate #数据库表前缀 org.quartz.jobStore.tablePrefix:qrtz_ #数据 org.quartz.jobStore.dataSource:yjlDB #JDBC驱动 org.quartz.dataSource.yjlDB.driver:com.mysql.jdbc.Driver org.quartz.dataSource.yjlDB.URL:jdbc:mysql://localhost:3306/quartz org.quartz.dataSource.yjlDB.user:root org.quartz.dataSource.yjlDB.password:abc123