生產(chǎn)環(huán)境一般都是多節(jié)點(diǎn)高可用,Springboot本身自帶有定時(shí)任務(wù)功能,但我們項(xiàng)目需求要求能對(duì)定時(shí)任務(wù)進(jìn)行增,刪,改,查。所以考慮引進(jìn)Quartz,引入Quartz就需要考慮分布式集群,所以就有了這篇文章。
數(shù)據(jù)庫(kù)腳本
Quartz數(shù)據(jù)庫(kù)有11張表,既支持Mysql,也支持Oracle
Mysql
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
|
/* Navicat MySQL Data Transfer Source Server : 10.19.34.3_ehr_admin Source Server Version : 50639 Source Host : 10.19.34.3:3306 Source Database : attend_base_dev Target Server Type : MYSQL Target Server Version : 50639 File Encoding : 65001 Date : 2020-08-28 16:29:36 */ -- SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for `qrtz_CALENDARS` -- ---------------------------- -- DROP TABLE IF EXISTS `qrtz_CALENDARS`; CREATE TABLE `qrtz_CALENDARS` ( `SCHED_NAME` varchar (120) NOT NULL COMMENT '計(jì)劃名稱' , `CALENDAR_NAME` varchar (200) NOT NULL , `CALENDAR` blob NOT NULL , PRIMARY KEY (`SCHED_NAME`,`CALENDAR_NAME`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT= '日歷信息' ; -- ---------------------------- -- Records of qrtz_CALENDARS -- ---------------------------- -- ---------------------------- -- Table structure for `qrtz_FIRED_TRIGGERS` -- ---------------------------- -- DROP TABLE IF EXISTS `qrtz_FIRED_TRIGGERS`; CREATE TABLE `qrtz_FIRED_TRIGGERS` ( `SCHED_NAME` varchar (120) NOT NULL COMMENT '計(jì)劃名稱' , `ENTRY_ID` varchar (95) NOT NULL COMMENT '組標(biāo)識(shí)' , `TRIGGER_NAME` varchar (200) NOT NULL COMMENT '觸發(fā)器名稱' , `TRIGGER_GROUP` varchar (200) NOT NULL COMMENT '觸發(fā)器組' , `INSTANCE_NAME` varchar (200) NOT NULL COMMENT '當(dāng)前實(shí)例的名稱' , `FIRED_TIME` bigint (13) NOT NULL COMMENT '當(dāng)前執(zhí)行時(shí)間' , `SCHED_TIME` bigint (13) NOT NULL COMMENT '計(jì)劃時(shí)間' , `PRIORITY` int (11) NOT NULL COMMENT '權(quán)重' , `STATE` varchar (16) NOT NULL COMMENT '狀態(tài):WAITING:等待 \r\nPAUSED:暫停 \r\nACQUIRED:正常執(zhí)行 \r\nBLOCKED:阻塞 \r\nERROR:錯(cuò)誤' , `JOB_NAME` varchar (200) DEFAULT NULL COMMENT '作業(yè)名稱' , `JOB_GROUP` varchar (200) DEFAULT NULL COMMENT '作業(yè)組' , `IS_NONCONCURRENT` varchar (1) DEFAULT NULL COMMENT '是否并行' , `REQUESTS_RECOVERY` varchar (1) DEFAULT NULL COMMENT '是否要求喚醒' , PRIMARY KEY (`SCHED_NAME`,`ENTRY_ID`), KEY `IDX_qrtz_FT_TRIG_INST_NAME` (`SCHED_NAME`,`INSTANCE_NAME`), KEY `IDX_qrtz_FT_INST_JOB_REQ_RCVRY` (`SCHED_NAME`,`INSTANCE_NAME`,`REQUESTS_RECOVERY`), KEY `IDX_qrtz_FT_J_G` (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`), KEY `IDX_qrtz_FT_JG` (`SCHED_NAME`,`JOB_GROUP`), KEY `IDX_qrtz_FT_T_G` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`), KEY `IDX_qrtz_FT_TG` (`SCHED_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT= '保存已經(jīng)觸發(fā)的觸發(fā)器狀態(tài)信息' ; -- ---------------------------- -- Records of qrtz_FIRED_TRIGGERS -- ---------------------------- -- ---------------------------- -- Table structure for `qrtz_JOB_DETAILS` -- ---------------------------- -- DROP TABLE IF EXISTS `qrtz_JOB_DETAILS`; CREATE TABLE `qrtz_JOB_DETAILS` ( `SCHED_NAME` varchar (120) NOT NULL COMMENT '計(jì)劃名稱' , `JOB_NAME` varchar (200) NOT NULL COMMENT '集群中job的名字' , `JOB_GROUP` varchar (200) NOT NULL COMMENT '集群中job的所屬組的名字' , `DESCRIPTION` varchar (250) DEFAULT NULL COMMENT '描述' , `JOB_CLASS_NAME` varchar (250) NOT NULL COMMENT '作業(yè)程序類(lèi)名' , `IS_DURABLE` varchar (1) NOT NULL COMMENT '是否持久' , `IS_NONCONCURRENT` varchar (1) NOT NULL COMMENT '是否并行' , `IS_UPDATE_DATA` varchar (1) NOT NULL COMMENT '是否更新' , `REQUESTS_RECOVERY` varchar (1) NOT NULL COMMENT '是否要求喚醒' , `JOB_DATA` blob, PRIMARY KEY (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`), KEY `IDX_qrtz_J_REQ_RECOVERY` (`SCHED_NAME`,`REQUESTS_RECOVERY`), KEY `IDX_qrtz_J_GRP` (`SCHED_NAME`,`JOB_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT= 'job 詳細(xì)信息' ; -- ---------------------------- -- Records of qrtz_JOB_DETAILS -- ---------------------------- -- ---------------------------- -- Table structure for `qrtz_LOCKS` -- ---------------------------- -- DROP TABLE IF EXISTS `qrtz_LOCKS`; CREATE TABLE `qrtz_LOCKS` ( `SCHED_NAME` varchar (120) NOT NULL COMMENT '計(jì)劃名稱' , `LOCK_NAME` varchar (40) NOT NULL COMMENT '鎖名稱' , PRIMARY KEY (`SCHED_NAME`,`LOCK_NAME`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT= '存儲(chǔ)程序的悲觀鎖的信息(假如使用了悲觀鎖) ' ; -- ---------------------------- -- Records of qrtz_LOCKS -- ---------------------------- -- Table structure for `qrtz_PAUSED_TRIGGER_GRPS` -- ---------------------------- -- DROP TABLE IF EXISTS `qrtz_PAUSED_TRIGGER_GRPS`; CREATE TABLE `qrtz_PAUSED_TRIGGER_GRPS` ( `SCHED_NAME` varchar (120) NOT NULL COMMENT '計(jì)劃名稱' , `TRIGGER_GROUP` varchar (200) NOT NULL COMMENT '觸發(fā)器組' , PRIMARY KEY (`SCHED_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT= '存放暫停掉的觸發(fā)器' ; -- ---------------------------- -- Records of qrtz_PAUSED_TRIGGER_GRPS -- ---------------------------- -- ---------------------------- -- Table structure for `qrtz_SCHEDULER_STATE` -- ---------------------------- -- DROP TABLE IF EXISTS `qrtz_SCHEDULER_STATE`; CREATE TABLE `qrtz_SCHEDULER_STATE` ( `SCHED_NAME` varchar (120) NOT NULL COMMENT '計(jì)劃名稱' , `INSTANCE_NAME` varchar (200) NOT NULL COMMENT '實(shí)例名稱' , `LAST_CHECKIN_TIME` bigint (13) NOT NULL COMMENT '最后的檢查時(shí)間' , `CHECKIN_INTERVAL` bigint (13) NOT NULL COMMENT '檢查間隔' , PRIMARY KEY (`SCHED_NAME`,`INSTANCE_NAME`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT= '調(diào)度器狀態(tài)' ; -- ---------------------------- -- Records of qrtz_SCHEDULER_STATE -- ---------------------------- -- Table structure for `qrtz_TRIGGERS` -- ---------------------------- -- DROP TABLE IF EXISTS `qrtz_TRIGGERS`; CREATE TABLE `qrtz_TRIGGERS` ( `SCHED_NAME` varchar (120) NOT NULL COMMENT '計(jì)劃名稱' , `TRIGGER_NAME` varchar (200) NOT NULL COMMENT '觸發(fā)器名稱' , `TRIGGER_GROUP` varchar (200) NOT NULL COMMENT '觸發(fā)器組' , `JOB_NAME` varchar (200) NOT NULL COMMENT '作業(yè)名稱' , `JOB_GROUP` varchar (200) NOT NULL COMMENT '作業(yè)組' , `DESCRIPTION` varchar (250) DEFAULT NULL COMMENT '描述' , `NEXT_FIRE_TIME` bigint (13) DEFAULT NULL COMMENT '下次執(zhí)行時(shí)間' , `PREV_FIRE_TIME` bigint (13) DEFAULT NULL COMMENT '前一次' , `PRIORITY` int (11) DEFAULT NULL COMMENT '優(yōu)先權(quán)' , `TRIGGER_STATE` varchar (16) NOT NULL COMMENT '觸發(fā)器狀態(tài)' , `TRIGGER_TYPE` varchar (8) NOT NULL COMMENT '觸發(fā)器類(lèi)型' , `START_TIME` bigint (13) NOT NULL COMMENT '開(kāi)始時(shí)間' , `END_TIME` bigint (13) DEFAULT NULL COMMENT '結(jié)束時(shí)間' , `CALENDAR_NAME` varchar (200) DEFAULT NULL COMMENT '日歷名稱' , `MISFIRE_INSTR` smallint (2) DEFAULT NULL COMMENT '失敗次數(shù)' , `JOB_DATA` blob, PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`), KEY `IDX_qrtz_T_J` (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`), KEY `IDX_qrtz_T_JG` (`SCHED_NAME`,`JOB_GROUP`), KEY `IDX_qrtz_T_C` (`SCHED_NAME`,`CALENDAR_NAME`), KEY `IDX_qrtz_T_G` (`SCHED_NAME`,`TRIGGER_GROUP`), KEY `IDX_qrtz_T_STATE` (`SCHED_NAME`,`TRIGGER_STATE`), KEY `IDX_qrtz_T_N_STATE` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`,`TRIGGER_STATE`), KEY `IDX_qrtz_T_N_G_STATE` (`SCHED_NAME`,`TRIGGER_GROUP`,`TRIGGER_STATE`), KEY `IDX_qrtz_T_NEXT_FIRE_TIME` (`SCHED_NAME`,`NEXT_FIRE_TIME`), KEY `IDX_qrtz_T_NFT_ST` (`SCHED_NAME`,`TRIGGER_STATE`,`NEXT_FIRE_TIME`), KEY `IDX_qrtz_T_NFT_MISFIRE` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`), KEY `IDX_qrtz_T_NFT_ST_MISFIRE` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`,`TRIGGER_STATE`), KEY `IDX_qrtz_T_NFT_ST_MISFIRE_GRP` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`,`TRIGGER_GROUP`,`TRIGGER_STATE`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT= '觸發(fā)器' ; -- ---------------------------- -- Records of qrtz_TRIGGERS -- ---------------------------- -- Table structure for `qrtz_SIMPLE_TRIGGERS` -- ---------------------------- -- DROP TABLE IF EXISTS `qrtz_SIMPLE_TRIGGERS`; CREATE TABLE `qrtz_SIMPLE_TRIGGERS` ( `SCHED_NAME` varchar (120) NOT NULL COMMENT '計(jì)劃名稱' , `TRIGGER_NAME` varchar (200) NOT NULL COMMENT '觸發(fā)器名稱' , `TRIGGER_GROUP` varchar (200) NOT NULL COMMENT '觸發(fā)器組' , `REPEAT_COUNT` bigint (7) NOT NULL COMMENT '重復(fù)次數(shù)' , `REPEAT_INTERVAL` bigint (12) NOT NULL COMMENT '重復(fù)間隔' , `TIMES_TRIGGERED` bigint (10) NOT NULL COMMENT '觸發(fā)次數(shù)' , PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT= '簡(jiǎn)單的觸發(fā)器' ; -- ---------------------------- -- Records of qrtz_SIMPLE_TRIGGERS -- ---------------------------- -- ---------------------------- -- Table structure for `qrtz_SIMPROP_TRIGGERS` -- ---------------------------- -- DROP TABLE IF EXISTS `qrtz_SIMPROP_TRIGGERS`; CREATE TABLE `qrtz_SIMPROP_TRIGGERS` ( `SCHED_NAME` varchar (120) NOT NULL COMMENT '計(jì)劃名稱' , `TRIGGER_NAME` varchar (200) NOT NULL COMMENT '觸發(fā)器名稱' , `TRIGGER_GROUP` varchar (200) NOT NULL COMMENT '觸發(fā)器組' , `STR_PROP_1` varchar (512) DEFAULT NULL , `STR_PROP_2` varchar (512) DEFAULT NULL , `STR_PROP_3` varchar (512) DEFAULT NULL , `INT_PROP_1` int (11) DEFAULT NULL , `INT_PROP_2` int (11) DEFAULT NULL , `LONG_PROP_1` bigint (20) DEFAULT NULL , `LONG_PROP_2` bigint (20) DEFAULT NULL , `DEC_PROP_1` decimal (13,4) DEFAULT NULL , `DEC_PROP_2` decimal (13,4) DEFAULT NULL , `BOOL_PROP_1` varchar (1) DEFAULT NULL , `BOOL_PROP_2` varchar (1) DEFAULT NULL , PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT= '存儲(chǔ)CalendarIntervalTrigger和DailyTimeIntervalTrigger兩種類(lèi)型的觸發(fā)器' ; -- ---------------------------- -- Records of qrtz_SIMPROP_TRIGGERS -- ---------------------------- -- ---------------------------- -- Table structure for `qrtz_BLOB_TRIGGERS` -- ---------------------------- -- DROP TABLE IF EXISTS `qrtz_BLOB_TRIGGERS`; CREATE TABLE `qrtz_BLOB_TRIGGERS` ( `SCHED_NAME` varchar (120) NOT NULL COMMENT '計(jì)劃名' , `TRIGGER_NAME` varchar (200) NOT NULL COMMENT '觸發(fā)器名稱' , `TRIGGER_GROUP` varchar (200) NOT NULL COMMENT '觸發(fā)器組' , `BLOB_DATA` blob, PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`), KEY `SCHED_NAME` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT= '以Blob 類(lèi)型存儲(chǔ)的觸發(fā)器' ; -- ---------------------------- -- Records of qrtz_BLOB_TRIGGERS -- ---------------------------- -- ---------------------------- -- Table structure for `qrtz_CRON_TRIGGERS` -- ---------------------------- -- DROP TABLE IF EXISTS `qrtz_CRON_TRIGGERS`; CREATE TABLE `qrtz_CRON_TRIGGERS` ( `SCHED_NAME` varchar (120) NOT NULL COMMENT '計(jì)劃名稱' , `TRIGGER_NAME` varchar (200) NOT NULL COMMENT '觸發(fā)器名稱' , `TRIGGER_GROUP` varchar (200) NOT NULL COMMENT '觸發(fā)器組' , `CRON_EXPRESSION` varchar (120) NOT NULL COMMENT '時(shí)間表達(dá)式' , `TIME_ZONE_ID` varchar (80) DEFAULT NULL COMMENT '時(shí)區(qū)ID nvarchar 80' , PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT= '定時(shí)觸發(fā)器' ; -- ---------------------------- -- Records of qrtz_CRON_TRIGGERS -- ---------------------------- Oracle create table QRTZ_CALENDARS ( sched_name VARCHAR2(120) not null , calendar_name VARCHAR2(200) not null , calendar BLOB not null ); alter table QRTZ_CALENDARS add constraint PK_QRTZ_CALENDARS primary key (SCHED_NAME, CALENDAR_NAME); 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 INTEGER not null , state VARCHAR2(16) not null , job_name VARCHAR2(200), job_group VARCHAR2(200), is_nonconcurrent VARCHAR2(1), requests_recovery VARCHAR2(1) ); alter table QRTZ_FIRED_TRIGGERS add constraint PK_QRTZ_FIRED_TRIGGERS primary key (SCHED_NAME, ENTRY_ID); 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), 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 ); alter table QRTZ_JOB_DETAILS add constraint PK_QRTZ_JOB_DETAILS primary key (SCHED_NAME, JOB_NAME, JOB_GROUP); create table QRTZ_LOCKS ( sched_name VARCHAR2(120) not null , lock_name VARCHAR2(40) not null ); alter table QRTZ_LOCKS add constraint PK_QRTZ_LOCKS primary key (SCHED_NAME, LOCK_NAME); create table QRTZ_PAUSED_TRIGGER_GRPS ( sched_name VARCHAR2(120) not null , trigger_group VARCHAR2(200) not null ); alter table QRTZ_PAUSED_TRIGGER_GRPS add constraint PK__TRIGGER_GRPS primary key (SCHED_NAME, TRIGGER_GROUP); 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 ); alter table QRTZ_SCHEDULER_STATE add constraint PK_QRTZ_SCHEDULER_STATE primary key (SCHED_NAME, INSTANCE_NAME); 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), next_fire_time NUMBER(13), prev_fire_time NUMBER(13), priority INTEGER , trigger_state VARCHAR2(16) not null , trigger_type VARCHAR2(8) not null , start_time NUMBER(13) not null , end_time NUMBER(13), calendar_name VARCHAR2(200), misfire_instr NUMBER(2), job_data BLOB ); alter table QRTZ_TRIGGERS add constraint PK_QRTZ_TRIGGERS primary key (SCHED_NAME, TRIGGER_NAME, TRIGGER_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 ); alter table QRTZ_SIMPLE_TRIGGERS add constraint PK_QRTZ_SIMPLE_TRIGGERS primary key (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), str_prop_2 VARCHAR2(512), str_prop_3 VARCHAR2(512), int_prop_1 INTEGER , int_prop_2 INTEGER , long_prop_1 NUMBER, long_prop_2 NUMBER, dec_prop_1 NUMBER(13,4), dec_prop_2 NUMBER(13,4), bool_prop_1 VARCHAR2(1), bool_prop_2 VARCHAR2(1) ); alter table QRTZ_SIMPROP_TRIGGERS add constraint PK_QRTZ_SIMPROP_TRIGGERS primary key (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 ); alter table QRTZ_BLOB_TRIGGERS add constraint PK_QRTZ_BLOB_TRIGGERS primary key (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(200) not null , time_zone_id VARCHAR2(80) ); alter table QRTZ_CRON_TRIGGERS add constraint PK_QRTZ_CRON_TRIGGERS primary key (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP); delete from QRTZ_JOB_DETAILS; delete from QRTZ_CRON_TRIGGERS; delete from QRTZ_BLOB_TRIGGERS; delete from QRTZ_CALENDARS; delete from QRTZ_FIRED_TRIGGERS; delete from QRTZ_LOCKS; delete from QRTZ_PAUSED_TRIGGER_GRPS; delete from QRTZ_SCHEDULER_STATE; delete from QRTZ_SIMPLE_TRIGGERS; delete from QRTZ_SIMPROP_TRIGGERS; delete from QRTZ_TRIGGERS; |
Maven
我這里后臺(tái)使用的是Springboot2.1
1
2
3
4
|
< dependency > < groupId >org.springframework.boot</ groupId > < artifactId >spring-boot-starter-quartz</ artifactId > </ dependency > |
application.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
quartz: #quartz相關(guān)屬性配置 properties: org: quartz: scheduler: instanceName: clusteredScheduler #調(diào)度器的實(shí)例名 instanceId: AUTO #調(diào)度器編號(hào)自動(dòng)生成 jobStore: class : org.quartz.impl.jdbcjobstore.JobStoreTX driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate tablePrefix: qrtz_ #數(shù)據(jù)庫(kù)表名前綴 isClustered: true #開(kāi)啟分布式部署 clusterCheckinInterval: 10000 #分布式節(jié)點(diǎn)有效性檢查時(shí)間間隔,單位:秒 useProperties: false threadPool: class : org.quartz.simpl.SimpleThreadPool #自帶的線程池實(shí)現(xiàn)類(lèi) threadCount: 10 #開(kāi)啟 10 個(gè)線程 threadPriority: 5 #工作者線程的優(yōu)先級(jí) threadsInheritContextClassLoaderOfInitializingThread: true #數(shù)據(jù)庫(kù)方式 job-store-type: jdbc |
Bean
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
import org.quartz.JobDataMap; import java.util.Date; /** * @program: QuartzBean * @description: * @author: Yuwl * @create: 2020-06-02 18:36 **/ public class QuartzBean { /** 任務(wù)id */ private String id; /** 任務(wù)名稱 */ private String jobName; /** 任務(wù)組 */ private String jobGroup; /** 任務(wù)執(zhí)行類(lèi) */ private String jobClass; /** 任務(wù)狀態(tài) 啟動(dòng)還是暫停*/ private Integer status; /** * 任務(wù)開(kāi)始時(shí)間 */ private Date startTime; /** * 任務(wù)循環(huán)間隔-單位:分鐘 */ private Integer interval; /** * 任務(wù)結(jié)束時(shí)間 */ private Date endTime; /** 任務(wù)運(yùn)行時(shí)間表達(dá)式 */ private String cronExpression; private JobDataMap jobDataMap; public String getId() { return id; } public void setId(String id) { this .id = id; } public String getJobName() { return jobName; } public void setJobName(String jobName) { this .jobName = jobName; } public String getJobClass() { return jobClass; } public void setJobClass(String jobClass) { this .jobClass = jobClass; } public Integer getStatus() { return status; } public void setStatus(Integer status) { this .status = status; } public String getCronExpression() { return cronExpression; } public void setCronExpression(String cronExpression) { this .cronExpression = cronExpression; } public Date getStartTime() { return startTime; } public void setStartTime(Date startTime) { this .startTime = startTime; } public Integer getInterval() { return interval; } public void setInterval(Integer interval) { this .interval = interval; } public Date getEndTime() { return endTime; } public void setEndTime(Date endTime) { this .endTime = endTime; } public JobDataMap getJobDataMap() { return jobDataMap; } public void setJobDataMap(JobDataMap jobDataMap) { this .jobDataMap = jobDataMap; } public String getJobGroup() { return jobGroup; } public void setJobGroup(String jobGroup) { this .jobGroup = jobGroup; } } |
Service
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
|
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import com.ruoyi.framework.quartz.QuartzBean; import org.quartz.*; import org.quartz.impl.matchers.GroupMatcher; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; import java.util.Set; /** * @program: QuartzJobService * @description: * @author: Yuwl * @create: 2020-07-21 17:00 **/ @Service public class QuartzJobService { @Autowired private Scheduler scheduler; /** * 創(chuàng)建定時(shí)任務(wù)Simple * quartzBean.getInterval()==null表示單次提醒, * 否則循環(huán)提醒(quartzBean.getEndTime()!=null) * @param quartzBean */ public void createScheduleJobSimple(QuartzBean quartzBean) throws Exception{ //獲取到定時(shí)任務(wù)的執(zhí)行類(lèi) 必須是類(lèi)的絕對(duì)路徑名稱 //定時(shí)任務(wù)類(lèi)需要是job類(lèi)的具體實(shí)現(xiàn) QuartzJobBean是job的抽象類(lèi)。 Class<? extends Job> jobClass = (Class<? extends Job>) Class.forName(quartzBean.getJobClass()); // 構(gòu)建定時(shí)任務(wù)信息 JobDetail jobDetail = JobBuilder.newJob(jobClass) .withIdentity(quartzBean.getJobName(), ObjectUtils.isNotEmpty(quartzBean.getJobGroup()) ?quartzBean.getJobGroup(): null ) .setJobData(quartzBean.getJobDataMap()) .build(); // 設(shè)置定時(shí)任務(wù)執(zhí)行方式 SimpleScheduleBuilder simpleScheduleBuilder = null ; if (quartzBean.getInterval() == null ) { //單次 simpleScheduleBuilder = SimpleScheduleBuilder.simpleSchedule(); } else { //循環(huán) simpleScheduleBuilder = SimpleScheduleBuilder.repeatMinutelyForever(quartzBean.getInterval()); } // 構(gòu)建觸發(fā)器trigger Trigger trigger = null ; if (quartzBean.getInterval() == null ) { //單次 trigger = TriggerBuilder.newTrigger() .withIdentity(quartzBean.getJobName(),ObjectUtils.isNotEmpty(quartzBean.getJobGroup()) ?quartzBean.getJobGroup(): null ) .withSchedule(simpleScheduleBuilder) .startAt(quartzBean.getStartTime()) .build(); } else { //循環(huán) trigger = TriggerBuilder.newTrigger() .withIdentity(quartzBean.getJobName(),ObjectUtils.isNotEmpty(quartzBean.getJobGroup()) ?quartzBean.getJobGroup(): null ) .withSchedule(simpleScheduleBuilder) .startAt(quartzBean.getStartTime()) .endAt(quartzBean.getEndTime()) .build(); } scheduler.scheduleJob(jobDetail, trigger); } /** * 創(chuàng)建定時(shí)任務(wù)Cron * 定時(shí)任務(wù)創(chuàng)建之后默認(rèn)啟動(dòng)狀態(tài) * @param quartzBean 定時(shí)任務(wù)信息類(lèi) * @throws Exception */ public void createScheduleJobCron(QuartzBean quartzBean) throws Exception{ //獲取到定時(shí)任務(wù)的執(zhí)行類(lèi) 必須是類(lèi)的絕對(duì)路徑名稱 //定時(shí)任務(wù)類(lèi)需要是job類(lèi)的具體實(shí)現(xiàn) QuartzJobBean是job的抽象類(lèi)。 Class<? extends Job> jobClass = (Class<? extends Job>) Class.forName(quartzBean.getJobClass()); // 構(gòu)建定時(shí)任務(wù)信息 JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(quartzBean.getJobName()).setJobData(quartzBean.getJobDataMap()).build(); // 設(shè)置定時(shí)任務(wù)執(zhí)行方式 CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(quartzBean.getCronExpression()); // 構(gòu)建觸發(fā)器trigger CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(quartzBean.getJobName()).withSchedule(scheduleBuilder).build(); scheduler.scheduleJob(jobDetail, trigger); } /** * 根據(jù)任務(wù)名稱暫停定時(shí)任務(wù) * @param jobName 定時(shí)任務(wù)名稱 * @param jobGroup 任務(wù)組(沒(méi)有分組傳值null) * @throws Exception */ public void pauseScheduleJob(String jobName,String jobGroup) throws Exception{ JobKey jobKey = JobKey.jobKey(jobName,ObjectUtils.isNotEmpty(jobGroup) ?jobGroup: null ); scheduler.pauseJob(jobKey); } /** * 根據(jù)任務(wù)名稱恢復(fù)定時(shí)任務(wù) * @param jobName 定時(shí)任務(wù)名 * @param jobGroup 任務(wù)組(沒(méi)有分組傳值null) * @throws SchedulerException */ public void resumeScheduleJob(String jobName,String jobGroup) throws Exception { JobKey jobKey = JobKey.jobKey(jobName,ObjectUtils.isNotEmpty(jobGroup) ?jobGroup: null ); scheduler.resumeJob(jobKey); } /** * 根據(jù)任務(wù)名稱立即運(yùn)行一次定時(shí)任務(wù) * @param jobName 定時(shí)任務(wù)名稱 * @param jobGroup 任務(wù)組(沒(méi)有分組傳值null) * @throws SchedulerException */ public void runOnce(String jobName,String jobGroup) throws Exception{ JobKey jobKey = JobKey.jobKey(jobName,ObjectUtils.isNotEmpty(jobGroup) ?jobGroup: null ); scheduler.triggerJob(jobKey); } /** * 更新定時(shí)任務(wù)Simple * @param quartzBean 定時(shí)任務(wù)信息類(lèi) * @throws SchedulerException */ public void updateScheduleJobSimple(QuartzBean quartzBean) throws Exception { //獲取到對(duì)應(yīng)任務(wù)的觸發(fā)器 TriggerKey triggerKey = TriggerKey.triggerKey(quartzBean.getJobName(), ObjectUtils.isNotEmpty(quartzBean.getJobGroup()) ?quartzBean.getJobGroup(): null ); // 設(shè)置定時(shí)任務(wù)執(zhí)行方式 SimpleScheduleBuilder simpleScheduleBuilder = null ; if (quartzBean.getInterval() == null ) { //單次 simpleScheduleBuilder = SimpleScheduleBuilder.simpleSchedule(); } else { //循環(huán) simpleScheduleBuilder = SimpleScheduleBuilder.repeatMinutelyForever(quartzBean.getInterval()); } // 構(gòu)建觸發(fā)器trigger Trigger trigger = null ; if (quartzBean.getInterval() == null ) { //單次 trigger = TriggerBuilder.newTrigger() .withIdentity(quartzBean.getJobName(), ObjectUtils.isNotEmpty(quartzBean.getJobGroup()) ?quartzBean.getJobGroup(): null ) .withSchedule(simpleScheduleBuilder) .startAt(quartzBean.getStartTime()) .build(); } else { //循環(huán) TriggerBuilder.newTrigger() .withIdentity(quartzBean.getJobName(), ObjectUtils.isNotEmpty(quartzBean.getJobGroup()) ?quartzBean.getJobGroup(): null ) .withSchedule(simpleScheduleBuilder) .startAt(quartzBean.getStartTime()) .endAt(quartzBean.getEndTime()) .build(); } //重置對(duì)應(yīng)的job scheduler.rescheduleJob(triggerKey, trigger); } /** * 更新定時(shí)任務(wù)Cron * @param quartzBean 定時(shí)任務(wù)信息類(lèi) * @throws SchedulerException */ public void updateScheduleJobCron(QuartzBean quartzBean) throws Exception { //獲取到對(duì)應(yīng)任務(wù)的觸發(fā)器 TriggerKey triggerKey = TriggerKey.triggerKey(quartzBean.getJobName()); //設(shè)置定時(shí)任務(wù)執(zhí)行方式 CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(quartzBean.getCronExpression()); //重新構(gòu)建任務(wù)的觸發(fā)器trigger CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey); trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build(); //重置對(duì)應(yīng)的job scheduler.rescheduleJob(triggerKey, trigger); } /** * 根據(jù)定時(shí)任務(wù)名稱從調(diào)度器當(dāng)中刪除定時(shí)任務(wù) * @param jobName 定時(shí)任務(wù)名稱 * @param jobGroup 任務(wù)組(沒(méi)有分組傳值null) * @throws SchedulerException */ public void deleteScheduleJob(String jobName,String jobGroup) throws Exception { JobKey jobKey = JobKey.jobKey(jobName,ObjectUtils.isNotEmpty(jobGroup) ?jobGroup: null ); scheduler.deleteJob(jobKey); } /** * 獲取任務(wù)狀態(tài) * @param jobName * @param jobGroup 任務(wù)組(沒(méi)有分組傳值null) * @return * (" BLOCKED ", " 阻塞 "); * ("COMPLETE", "完成"); * ("ERROR", "出錯(cuò)"); * ("NONE", "不存在"); * ("NORMAL", "正常"); * ("PAUSED", "暫停"); */ public String getScheduleJobStatus(String jobName,String jobGroup) throws Exception { TriggerKey triggerKey = TriggerKey.triggerKey(jobName,ObjectUtils.isNotEmpty(jobGroup) ?jobGroup: null ); Trigger.TriggerState state = scheduler.getTriggerState(triggerKey); return state.name(); } /** * 根據(jù)定時(shí)任務(wù)名稱來(lái)判斷任務(wù)是否存在 * @param jobName 定時(shí)任務(wù)名稱 * @param jobGroup 任務(wù)組(沒(méi)有分組傳值null) * @throws SchedulerException */ public Boolean checkExistsScheduleJob(String jobName,String jobGroup) throws Exception { JobKey jobKey = JobKey.jobKey(jobName,ObjectUtils.isNotEmpty(jobGroup) ?jobGroup: null ); return scheduler.checkExists(jobKey); } /** * 根據(jù)任務(wù)組刪除定時(shí)任務(wù) * @param jobGroup 任務(wù)組 * @throws SchedulerException */ public Boolean deleteGroupJob(String jobGroup) throws Exception { GroupMatcher<JobKey> matcher = GroupMatcher.groupEquals(jobGroup); Set<JobKey> jobkeySet = scheduler.getJobKeys(matcher); List<JobKey> jobkeyList = new ArrayList<JobKey>(); jobkeyList.addAll(jobkeySet); return scheduler.deleteJobs(jobkeyList); } /** * 根據(jù)任務(wù)組批量刪除定時(shí)任務(wù) * @param jobkeyList * @throws SchedulerException */ public Boolean batchDeleteGroupJob(List<JobKey> jobkeyList) throws Exception { return scheduler.deleteJobs(jobkeyList); } /** * 根據(jù)任務(wù)組批量查詢出jobkey * @param jobGroup 任務(wù)組 * @throws SchedulerException */ public void batchQueryGroupJob(List<JobKey> jobkeyList,String jobGroup) throws Exception { GroupMatcher<JobKey> matcher = GroupMatcher.groupEquals(jobGroup); Set<JobKey> jobkeySet = scheduler.getJobKeys(matcher); jobkeyList.addAll(jobkeySet); } } |
Job
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
package com.quartz.demo.job import org.quartz.JobDataMap; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.quartz.JobKey; import org.springframework.scheduling.quartz.QuartzJobBean; import org.springframework.stereotype.Component; import java.util.Date; /** * @program: job * @description: * @author: Yuwl * @create: 2020-06-02 18:07 **/ @Component public class MyTask extends QuartzJobBean { @Override protected void executeInternal(JobExecutionContext context) throws JobExecutionException { JobKey jobKey = context.getJobDetail().getKey(); JobDataMap map = context.getJobDetail().getJobDataMap(); String userId = map.getString( "userId" ); System.out.println( "SimpleJob says: " + jobKey + ", userId: " + userId + " executing at " + new Date()); } } |
Controller
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import com.ruoyi.common.utils.DateUtils; import com.ruoyi.framework.quartz.QuartzBean; import com.ruoyi.framework.quartz.service.QuartzJobService; import org.quartz.JobDataMap; import org.quartz.SchedulerException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.text.ParseException; import java.util.Date; /** * @program: JobController * @description: * @author: Yuwl * @create: 2020-07-21 17:08 **/ @RestController @RequestMapping ( "/api/quartz/" ) public class JobController { @Autowired private QuartzJobService quartzJobService; //創(chuàng)建&啟動(dòng) @GetMapping ( "startSimpleJob" ) public String startSimpleJob() throws SchedulerException, ClassNotFoundException, ParseException { QuartzBean quartzBean = new QuartzBean(); quartzBean.setJobClass( "com.quartz.demo.job.MyTask" ); quartzBean.setJobName( "job1" ); JobDataMap map = new JobDataMap(); map.put( "userId" , "123456" ); quartzBean.setJobDataMap(map); Date now = new Date(); quartzBean.setStartTime(DateUtils.addSeconds(now, 10 )); quartzBean.setInterval( 10 ); quartzBean.setEndTime(DateUtils.addMinutes(now, 1 )); try { quartzJobService.createScheduleJobSimple(quartzBean); } catch (Exception e) { e.printStackTrace(); } return "startJob Success!" ; } /** * 創(chuàng)建cron Job * @param quartzBean * @return */ @RequestMapping ( "/createCronJob" ) @ResponseBody public String createJob(QuartzBean quartzBean) { try { //進(jìn)行測(cè)試所以寫(xiě)死 quartzBean.setJobClass( "com.quartz.demo.job.MyTask" ); quartzBean.setJobName( "job1" ); quartzBean.setCronExpression( "*/5 * * * * ?" ); quartzJobService.createScheduleJobCron(quartzBean); } catch (Exception e) { return "創(chuàng)建失敗" ; } return "創(chuàng)建成功" ; } /** * 暫停job * @return */ @RequestMapping (value = { "/pauseJob/{jobName}" , "/pauseJob/{jobName}/{jobGroup}" }) @ResponseBody public String pauseJob( @PathVariable ( "jobName" ) String jobName, @PathVariable (required = false ) String jobGroup) { try { quartzJobService.pauseScheduleJob(jobName,ObjectUtils.isNotEmpty(jobGroup) ?jobGroup: null ); } catch (Exception e) { return "暫停失敗" ; } return "暫停成功" ; } @RequestMapping (value = { "/resume/{jobName}" , "/resume/{jobName}/{jobGroup}" }) @ResponseBody public String resume( @PathVariable ( "jobName" ) String jobName, @PathVariable (required = false ) String jobGroup) { try { quartzJobService.resumeScheduleJob(jobName,ObjectUtils.isNotEmpty(jobGroup) ?jobGroup: null ); } catch (Exception e) { return "啟動(dòng)失敗" ; } return "啟動(dòng)成功" ; } @RequestMapping (value = { "/delete/{jobName}" , "/delete/{jobName}/{jobGroup}" }) public String delete( @PathVariable ( "jobName" ) String jobName, @PathVariable (required = false ) String jobGroup) { try { quartzJobService.deleteScheduleJob(jobName,ObjectUtils.isNotEmpty(jobGroup) ?jobGroup: null ); } catch (Exception e) { return "刪除失敗" ; } return "刪除成功" ; } @RequestMapping (value = { "/check/{jobName}" , "/check/{jobName}/{jobGroup}" }) public String check( @PathVariable ( "jobName" ) String jobName, @PathVariable (required = false ) String jobGroup) { try { if (quartzJobService.checkExistsScheduleJob(jobName,ObjectUtils.isNotEmpty(jobGroup) ?jobGroup: null )){ return "存在定時(shí)任務(wù):" +jobName; } else { return "不存在定時(shí)任務(wù):" +jobName; } } catch (Exception e) { return "查詢?nèi)蝿?wù)失敗" ; } } @RequestMapping (value = { "/status/{jobName}" , "/status/{jobName}/{jobGroup}" }) @ResponseBody public String status( @PathVariable ( "jobName" ) String jobName, @PathVariable (required = false ) String jobGroup) { try { return quartzJobService.getScheduleJobStatus(jobName,ObjectUtils.isNotEmpty(jobGroup) ?jobGroup: null ); } catch (Exception e) { return "獲取狀態(tài)失敗" ; } //return "獲取狀態(tài)成功"; } } |
測(cè)試
http://localhost:8080/api/quartz/startSimpleJob
到此這篇關(guān)于Springboot2.x+Quartz分布式集群的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Springboot2.x Quartz分布式集群內(nèi)容請(qǐng)搜索服務(wù)器之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持服務(wù)器之家!
原文鏈接:https://blog.51cto.com/14942009/2536639