Laughing
spring boot quartz持久化存储
09/29
本文最后更新于2024年03月20日,已超过183天没有更新。如果文章内容或图片资源失效,请留言反馈,我会及时处理,谢谢!
在spring boot quartz定时任务基本使用及介绍的博文中,我们简单介绍了quartz的基础概念及简单的使用,细心的童鞋可以发现,那个demo虽然能用,但是存在一个问题:一旦应用停止,计划任务变失效了。如何解决应用停止或者重启不会丢失计划任务信息,便是我们这篇博文要讨论的问题。
Quartz提供两种基本作业存储类型:
- RAMJobStore :RAM也就是内存,默认情况下Quartz会将任务调度存在内存中,这种方式性能是最好的,因为内存的速度是最快的。不好的地方就是数据缺乏持久性,但程序崩溃或者重新发布的时候,所有运行信息都会丢失。
JDBC作业存储:存到数据库之后,可以做单点也可以做集群,当任务多了之后,可以统一进行管理。关闭或者重启服务器,运行的信息都不会丢失。缺点就是运行速度快慢取决于连接数据库的快慢。
Quartz初始化表
MySQL
# # Quartz seems to work best with the driver mm.mysql-2.0.7-bin.jar # # PLEASE consider using mysql with innodb tables to avoid locking issues # # In your Quartz properties file, you'll need to set # org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate # 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;
Oracle
-- -- A hint submitted by a user: Oracle DB MUST be created as "shared" and the -- job_queue_processes parameter must be greater than 2 -- However, these settings are pretty much standard after any -- Oracle install, so most users need not worry about this. -- -- Many other users (including the primary author of Quartz) have had success -- runing in dedicated mode, so only consider the above as a hint ;-) -- delete from qrtz_fired_triggers; delete from qrtz_simple_triggers; delete from qrtz_simprop_triggers; delete from qrtz_cron_triggers; delete from qrtz_blob_triggers; delete from qrtz_triggers; delete from qrtz_job_details; delete from qrtz_calendars; delete from qrtz_paused_trigger_grps; delete from qrtz_locks; delete from qrtz_scheduler_state; drop table qrtz_calendars; drop table qrtz_fired_triggers; drop table qrtz_blob_triggers; drop table qrtz_cron_triggers; drop table qrtz_simple_triggers; drop table qrtz_simprop_triggers; drop table qrtz_triggers; drop table qrtz_job_details; drop table qrtz_paused_trigger_grps; drop table qrtz_locks; drop table qrtz_scheduler_state; CREATE TABLE qrtz_job_details ( SCHED_NAME VARCHAR2(120) NOT NULL, JOB_NAME VARCHAR2(200) NOT NULL, JOB_GROUP VARCHAR2(200) NOT NULL, DESCRIPTION VARCHAR2(250) NULL, JOB_CLASS_NAME VARCHAR2(250) NOT NULL, IS_DURABLE VARCHAR2(1) NOT NULL, IS_NONCONCURRENT VARCHAR2(1) NOT NULL, IS_UPDATE_DATA VARCHAR2(1) NOT NULL, REQUESTS_RECOVERY VARCHAR2(1) NOT NULL, JOB_DATA BLOB NULL, CONSTRAINT QRTZ_JOB_DETAILS_PK PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP) ); CREATE TABLE qrtz_triggers ( SCHED_NAME VARCHAR2(120) NOT NULL, TRIGGER_NAME VARCHAR2(200) NOT NULL, TRIGGER_GROUP VARCHAR2(200) NOT NULL, JOB_NAME VARCHAR2(200) NOT NULL, JOB_GROUP VARCHAR2(200) NOT NULL, DESCRIPTION VARCHAR2(250) NULL, NEXT_FIRE_TIME NUMBER(13) NULL, PREV_FIRE_TIME NUMBER(13) NULL, PRIORITY NUMBER(13) NULL, TRIGGER_STATE VARCHAR2(16) NOT NULL, TRIGGER_TYPE VARCHAR2(8) NOT NULL, START_TIME NUMBER(13) NOT NULL, END_TIME NUMBER(13) NULL, CALENDAR_NAME VARCHAR2(200) NULL, MISFIRE_INSTR NUMBER(2) NULL, JOB_DATA BLOB NULL, CONSTRAINT QRTZ_TRIGGERS_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), CONSTRAINT QRTZ_TRIGGER_TO_JOBS_FK 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 VARCHAR2(120) NOT NULL, TRIGGER_NAME VARCHAR2(200) NOT NULL, TRIGGER_GROUP VARCHAR2(200) NOT NULL, REPEAT_COUNT NUMBER(7) NOT NULL, REPEAT_INTERVAL NUMBER(12) NOT NULL, TIMES_TRIGGERED NUMBER(10) NOT NULL, CONSTRAINT QRTZ_SIMPLE_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), CONSTRAINT QRTZ_SIMPLE_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) ); CREATE TABLE qrtz_cron_triggers ( SCHED_NAME VARCHAR2(120) NOT NULL, TRIGGER_NAME VARCHAR2(200) NOT NULL, TRIGGER_GROUP VARCHAR2(200) NOT NULL, CRON_EXPRESSION VARCHAR2(120) NOT NULL, TIME_ZONE_ID VARCHAR2(80), CONSTRAINT QRTZ_CRON_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), CONSTRAINT QRTZ_CRON_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) ); CREATE TABLE qrtz_simprop_triggers ( SCHED_NAME VARCHAR2(120) NOT NULL, TRIGGER_NAME VARCHAR2(200) NOT NULL, TRIGGER_GROUP VARCHAR2(200) NOT NULL, STR_PROP_1 VARCHAR2(512) NULL, STR_PROP_2 VARCHAR2(512) NULL, STR_PROP_3 VARCHAR2(512) NULL, INT_PROP_1 NUMBER(10) NULL, INT_PROP_2 NUMBER(10) NULL, LONG_PROP_1 NUMBER(13) NULL, LONG_PROP_2 NUMBER(13) NULL, DEC_PROP_1 NUMERIC(13,4) NULL, DEC_PROP_2 NUMERIC(13,4) NULL, BOOL_PROP_1 VARCHAR2(1) NULL, BOOL_PROP_2 VARCHAR2(1) NULL, CONSTRAINT QRTZ_SIMPROP_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), CONSTRAINT QRTZ_SIMPROP_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) ); CREATE TABLE qrtz_blob_triggers ( SCHED_NAME VARCHAR2(120) NOT NULL, TRIGGER_NAME VARCHAR2(200) NOT NULL, TRIGGER_GROUP VARCHAR2(200) NOT NULL, BLOB_DATA BLOB NULL, CONSTRAINT QRTZ_BLOB_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), CONSTRAINT QRTZ_BLOB_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) ); CREATE TABLE qrtz_calendars ( SCHED_NAME VARCHAR2(120) NOT NULL, CALENDAR_NAME VARCHAR2(200) NOT NULL, CALENDAR BLOB NOT NULL, CONSTRAINT QRTZ_CALENDARS_PK PRIMARY KEY (SCHED_NAME,CALENDAR_NAME) ); CREATE TABLE qrtz_paused_trigger_grps ( SCHED_NAME VARCHAR2(120) NOT NULL, TRIGGER_GROUP VARCHAR2(200) NOT NULL, CONSTRAINT QRTZ_PAUSED_TRIG_GRPS_PK PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP) ); CREATE TABLE qrtz_fired_triggers ( SCHED_NAME VARCHAR2(120) NOT NULL, ENTRY_ID VARCHAR2(95) NOT NULL, TRIGGER_NAME VARCHAR2(200) NOT NULL, TRIGGER_GROUP VARCHAR2(200) NOT NULL, INSTANCE_NAME VARCHAR2(200) NOT NULL, FIRED_TIME NUMBER(13) NOT NULL, SCHED_TIME NUMBER(13) NOT NULL, PRIORITY NUMBER(13) NOT NULL, STATE VARCHAR2(16) NOT NULL, JOB_NAME VARCHAR2(200) NULL, JOB_GROUP VARCHAR2(200) NULL, IS_NONCONCURRENT VARCHAR2(1) NULL, REQUESTS_RECOVERY VARCHAR2(1) NULL, CONSTRAINT QRTZ_FIRED_TRIGGER_PK PRIMARY KEY (SCHED_NAME,ENTRY_ID) ); CREATE TABLE qrtz_scheduler_state ( SCHED_NAME VARCHAR2(120) NOT NULL, INSTANCE_NAME VARCHAR2(200) NOT NULL, LAST_CHECKIN_TIME NUMBER(13) NOT NULL, CHECKIN_INTERVAL NUMBER(13) NOT NULL, CONSTRAINT QRTZ_SCHEDULER_STATE_PK PRIMARY KEY (SCHED_NAME,INSTANCE_NAME) ); CREATE TABLE qrtz_locks ( SCHED_NAME VARCHAR2(120) NOT NULL, LOCK_NAME VARCHAR2(40) NOT NULL, CONSTRAINT QRTZ_LOCKS_PK PRIMARY KEY (SCHED_NAME,LOCK_NAME) ); create index idx_qrtz_j_req_recovery on qrtz_job_details(SCHED_NAME,REQUESTS_RECOVERY); create index idx_qrtz_j_grp on qrtz_job_details(SCHED_NAME,JOB_GROUP); create index idx_qrtz_t_j on qrtz_triggers(SCHED_NAME,JOB_NAME,JOB_GROUP); create index idx_qrtz_t_jg on qrtz_triggers(SCHED_NAME,JOB_GROUP); create index idx_qrtz_t_c on qrtz_triggers(SCHED_NAME,CALENDAR_NAME); create index idx_qrtz_t_g on qrtz_triggers(SCHED_NAME,TRIGGER_GROUP); create index idx_qrtz_t_state on qrtz_triggers(SCHED_NAME,TRIGGER_STATE); create index idx_qrtz_t_n_state on qrtz_triggers(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE); create index idx_qrtz_t_n_g_state on qrtz_triggers(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE); create index idx_qrtz_t_next_fire_time on qrtz_triggers(SCHED_NAME,NEXT_FIRE_TIME); create index idx_qrtz_t_nft_st on qrtz_triggers(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME); create index idx_qrtz_t_nft_misfire on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME); create index idx_qrtz_t_nft_st_misfire on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE); create index idx_qrtz_t_nft_st_misfire_grp on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE); create index idx_qrtz_ft_trig_inst_name on qrtz_fired_triggers(SCHED_NAME,INSTANCE_NAME); create index idx_qrtz_ft_inst_job_req_rcvry on qrtz_fired_triggers(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY); create index idx_qrtz_ft_j_g on qrtz_fired_triggers(SCHED_NAME,JOB_NAME,JOB_GROUP); create index idx_qrtz_ft_jg on qrtz_fired_triggers(SCHED_NAME,JOB_GROUP); create index idx_qrtz_ft_t_g on qrtz_fired_triggers(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP); create index idx_qrtz_ft_tg on qrtz_fired_triggers(SCHED_NAME,TRIGGER_GROUP);
postgresql
-- Thanks to Patrick Lightbody for submitting this... -- -- In your Quartz properties file, you'll need to set -- org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.PostgreSQLDelegate DROP TABLE IF EXISTS qrtz_fired_trigger`s; 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_cron_triggers; DROP TABLE IF EXISTS qrtz_simprop_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 BOOL NOT NULL, IS_NONCONCURRENT BOOL NOT NULL, IS_UPDATE_DATA BOOL NOT NULL, REQUESTS_RECOVERY BOOL NOT NULL, JOB_DATA BYTEA 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 NULL, PREV_FIRE_TIME BIGINT NULL, PRIORITY INTEGER NULL, TRIGGER_STATE VARCHAR(16) NOT NULL, TRIGGER_TYPE VARCHAR(8) NOT NULL, START_TIME BIGINT NOT NULL, END_TIME BIGINT NULL, CALENDAR_NAME VARCHAR(200) NULL, MISFIRE_INSTR SMALLINT NULL, JOB_DATA BYTEA 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 NOT NULL, REPEAT_INTERVAL BIGINT NOT NULL, TIMES_TRIGGERED BIGINT 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(120) 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 BOOL NULL, BOOL_PROP_2 BOOL 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 BYTEA 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 BYTEA 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 NOT NULL, SCHED_TIME BIGINT NOT NULL, PRIORITY INTEGER NOT NULL, STATE VARCHAR(16) NOT NULL, JOB_NAME VARCHAR(200) NULL, JOB_GROUP VARCHAR(200) NULL, IS_NONCONCURRENT BOOL NULL, REQUESTS_RECOVERY BOOL 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 NOT NULL, CHECKIN_INTERVAL BIGINT 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) ); create index idx_qrtz_j_req_recovery on qrtz_job_details(SCHED_NAME,REQUESTS_RECOVERY); create index idx_qrtz_j_grp on qrtz_job_details(SCHED_NAME,JOB_GROUP); create index idx_qrtz_t_j on qrtz_triggers(SCHED_NAME,JOB_NAME,JOB_GROUP); create index idx_qrtz_t_jg on qrtz_triggers(SCHED_NAME,JOB_GROUP); create index idx_qrtz_t_c on qrtz_triggers(SCHED_NAME,CALENDAR_NAME); create index idx_qrtz_t_g on qrtz_triggers(SCHED_NAME,TRIGGER_GROUP); create index idx_qrtz_t_state on qrtz_triggers(SCHED_NAME,TRIGGER_STATE); create index idx_qrtz_t_n_state on qrtz_triggers(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE); create index idx_qrtz_t_n_g_state on qrtz_triggers(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE); create index idx_qrtz_t_next_fire_time on qrtz_triggers(SCHED_NAME,NEXT_FIRE_TIME); create index idx_qrtz_t_nft_st on qrtz_triggers(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME); create index idx_qrtz_t_nft_misfire on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME); create index idx_qrtz_t_nft_st_misfire on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE); create index idx_qrtz_t_nft_st_misfire_grp on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE); create index idx_qrtz_ft_trig_inst_name on qrtz_fired_triggers(SCHED_NAME,INSTANCE_NAME); create index idx_qrtz_ft_inst_job_req_rcvry on qrtz_fired_triggers(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY); create index idx_qrtz_ft_j_g on qrtz_fired_triggers(SCHED_NAME,JOB_NAME,JOB_GROUP); create index idx_qrtz_ft_jg on qrtz_fired_triggers(SCHED_NAME,JOB_GROUP); create index idx_qrtz_ft_t_g on qrtz_fired_triggers(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP); create index idx_qrtz_ft_tg on qrtz_fired_triggers(SCHED_NAME,TRIGGER_GROUP); commit;
其余的配置文件,大家可以去官网下载
配置依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
配置文件quartz.properties
###################jdbcJobStore############################
org.quartz.scheduler.instanceName=MyScheduler
org.quartz.scheduler.instanceId=AUTO
org.quartz.threadPool.threadCount=3
# 所有的quartz数据例如job和Trigger的细节信息被保存在内存或数据库中,有两种实现:JobStoreTX(自己管理事务)
#和JobStoreCMT(application server管理事务,即全局事务JTA)
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
# 类似于Hibernate的dialect,用于处理DB之间的差异,StdJDBCDelegate能满足大部分的DB
org.quartz.jobStore.driverDelegateClass =org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#数据库表的前缀
org.quartz.jobStore.tablePrefix=QRTZ_
#配置数据源的名称
org.quartz.jobStore.dataSource=myDS
#为了指示JDBCJobStore所有的JobDataMaps中的值都是字符串,并且能以“名字-值”对的方式存储而不是以复杂对象的序列化形式存储在BLOB字段中,应该设置为true(缺省方式)
org.quartz.jobStore.useProperties = true
# 检入到数据库中的频率(毫秒)。检查是否其他的实例到了应当检入的时候未检入这能指出一个失败的实例,
#且当前Scheduler会以此来接管执行失败并可恢复的Job通过检入操作,Scheduler也会更新自身的状态记录
org.quartz.jobStore.clusterCheckinInterval=20000
# 是否集群、负载均衡、容错,如果应用在集群中设置为false会出错
org.quartz.jobStore.isClustered=false
#misfire时间设置
org.quartz.jobStore.misfireThreshold=60000
# 连接超时重试连接的间隔。使用 RamJobStore时,该参数并没什么用【默认15000】【非必须】
#org.quartz.scheduler.dbFailureRetryInterval = 15000
#下面是数据库链接相关的配置
org.quartz.dataSource.myDS.driver=com.mysql.jdbc.Driver
org.quartz.dataSource.myDS.URL=jdbc:mysql://localhost:3306/quartz?characterEncoding=utf8&useUnicode=true&useSSL=false&serverTimezone=UTC
org.quartz.dataSource.myDS.user=root
org.quartz.dataSource.myDS.password=root
org.quartz.dataSource.myDS.maxConnections=5
使用
定义Job类
package org.lisen.quartzjdbc.scheduler;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @author laughing
* @date 2020/9/29
* @site https://www.lisen.org
*/
public class PrintService implements Job {
private final Logger logger = LoggerFactory.getLogger(PrintService.class);
/**
* 执行
* @param jobExecutionContext
* @throws JobExecutionException
*/
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
logger.info(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
}
}
创建计划任务
/**
* @author laughing
* @date 2020/9/29
* @site https://www.lisen.org
*/
@RestController
public class QuartzController {
@RequestMapping("/quartzJdbc")
public String quartzJdbc() throws SchedulerException {
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger","triGroup")
.startNow()
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(1)
.withRepeatCount(0))
.build();
JobDetail job = JobBuilder.newJob(PrintService.class)
.usingJobData("JobKey","JobValue")
.withIdentity("Job","JobGroup")
.withDescription("打印任务")
.build();
scheduler.scheduleJob(job, trigger);
scheduler.pauseAll();
return "success";
}
}
版权属于:
香草物语
本文链接:
https://www.xiangcaowuyu.net/java/spring-boot-quartz-persistent-storage.html(转载时请注明本文出处及文章链接)
作品采用:
[…] 承接 上一篇,我们继续探究bootstrap-select的一些更深层次的用法 […]
{!{data:image/webp;base64,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}!}