SpringBoot技术实践-整合Quartz任务调度 一、

一、Quartz任务调度

1.1 Quartz

  1. Quartz是一个定时任务框架,基础核心使用可以参考官网
  2. Quartz源码:github.com/quartz-sche…
  3. Quartz官网地址:www.quartz-scheduler.org/documentati…
  4. 项目源码地址:gitee.com/tianxincoor…

1.2 Scheduler

  1. Scheduler为quartz中的调度器,Quartz通过调度器来注册、暂停、删除Trigger和JobDetail
  2. Scheduler拥有SchedulerContext,顾名思义就是上下文,通过SchedulerContext可以获取到触发器和任务的一些信息

1.3 Trigger

  1. Trigger为触发器,通过cron表达式或日历指定任务执行的周期
  2. 系统时间走到触发器指定的时间时,触发器就会触发任务的执行

1.4 JobDetail

  1. Job接口是真正需要执行的任务
  2. JobDetail核心调度实现了Job类的任务类,Trigger和Scheduler实际用到的都是JobDetail

1.5 Job

  1. 完成任务的最小实现类,如果需要被定时调度的类都需要实现此接口

二、SpringBoot整合

2.1 环境准备

  1. 新建SpringBoot项目,SpringBoot基于2.2.0.RELEASE,完整pom如下
    • 核心依赖为spring-boot-starter-quartz、
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
xml复制代码<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.codecoord</groupId>
<artifactId>springboot-quartz</artifactId>
<version>1.0</version>
<name>springboot-quartz</name>

<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- 公共依赖 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>

<!-- quartz依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.6</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
  1. 配置数据源相关链接
    • quartz需要单据的数据库,所以需要单据创建一个库来给quartz使用,此处为quartz_config
    • 其他相关配置可以参考官网:官网配置参考
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
yaml复制代码server:
port: 8888
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/source?useSSL=false
username: root
password: tianxin
# 定时配置
quartz:
# 相关属性配置
properties:
org:
quartz:
# 数据源
dataSource:
globalJobDataSource:
# URL必须大写
URL: jdbc:mysql://127.0.0.1:3306/quartz_config?useUnicode=true&characterEncoding=utf-8&useSSL=false
driver: com.mysql.cj.jdbc.Driver
maxConnections: 5
username: root
password: tianxin
# 必须指定数据源类型
provider: hikaricp
scheduler:
instanceName: globalScheduler
# 实例id
#instanceId: AUTO
type: com.alibaba.druid.pool.DruidDataSource
jobStore:
# 数据源
dataSource: globalJobDataSource
# JobStoreTX将用于独立环境,提交和回滚都将由这个类处理
class: org.quartz.impl.jdbcjobstore.JobStoreTX
# 驱动配置
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
# 表前缀
tablePrefix: QRTZ_
# 线程池配置
threadPool:
class: org.quartz.simpl.SimpleThreadPool
# 线程数
threadCount: 10
# 优先级
threadPriority: 5
  1. 数据表结构如下,在github中有对应的表结构信息
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
sql复制代码drop database quartz_config;
create database quartz_config default character set utf8mb4;
use quartz_config;

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)
);
  1. 上述步骤完成后,quartz&SpringBoot整合基础环境完成,完整项目结构如下

image.png

2.2 代码示例

新建启动类SpringBootQuartz

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
java复制代码package com.codecoord.springboot.quartz;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
* SpringBootQuartz
*
* @author tianxincoord@163.com
* @date 2021/7/20
*/
@SpringBootApplication
public class SpringBootQuartz {

public static void main(String[] args) {
SpringApplication.run(SpringBootQuartz.class, args);
}
}

新建实体类,用于接收基础任务信息

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
java复制代码package com.codecoord.springboot.quartz.domain;

/**
* 任务明细
*
* @author tianxincoord@163.com
* @date 2021/7/20
*/
public class JobInfo {
/**
* 任务名称
*/
private String jobName;
/**
* 任务组
*/
private String jobGroup;
/**
* 触发器名称
*/
private String triggerName;
/**
* 触发器组
*/
private String triggerGroup;
/**
* cron表达式
*/
private String cron;
/**
* 类名
*/
private String className;
/**
* 状态
*/
private String status;
/**
* 下一次执行时间
*/
private String nextTime;
/**
* 上一次执行时间
*/
private String prevTime;
/**
* 配置信息(data)
*/
private String config;

public String getJobName() {
return jobName;
}

public void setJobName(String jobName) {
this.jobName = jobName;
}

public String getJobGroup() {
return jobGroup;
}

public void setJobGroup(String jobGroup) {
this.jobGroup = jobGroup;
}

public String getTriggerName() {
return triggerName;
}

public void setTriggerName(String triggerName) {
this.triggerName = triggerName;
}

public String getTriggerGroup() {
return triggerGroup;
}

public void setTriggerGroup(String triggerGroup) {
this.triggerGroup = triggerGroup;
}

public String getCron() {
return cron;
}

public void setCron(String cron) {
this.cron = cron;
}

public String getClassName() {
return className;
}

public void setClassName(String className) {
this.className = className;
}

public String getStatus() {
return status;
}

public void setStatus(String status) {
this.status = status;
}

public String getNextTime() {
return nextTime;
}

public void setNextTime(String nextTime) {
this.nextTime = nextTime;
}

public String getPrevTime() {
return prevTime;
}

public void setPrevTime(String prevTime) {
this.prevTime = prevTime;
}

public String getConfig() {
return config;
}

public void setConfig(String config) {
this.config = config;
}
}

新建任务类,用于调度任务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
java复制代码package com.codecoord.springboot.quartz.job;

import java.time.LocalDateTime;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.stereotype.Component;

/**
* 计划提醒
*
* @author tianxincoord@163.com
* @date 2021/7/20
*/
@Component
@DisallowConcurrentExecution
public class PlanRemindJob implements Job {

@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
System.out.println("PlanRemindJob正在执行..." + LocalDateTime.now());
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
java复制代码package com.codecoord.springboot.quartz.job;

import java.time.LocalDateTime;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.stereotype.Component;

/**
* 时间日提醒
*
* @author tianxincoord@163.com
* @date 2021/7/20
*/
@Component
@DisallowConcurrentExecution
public class TimeEventJob implements Job {

@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
System.out.println("TimeEventJob正在执行..." + LocalDateTime.now());
}
}

新建核心处理类,处理任务的添加、删除、暂停等操作

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
java复制代码package com.codecoord.springboot.quartz.handler;

import com.alibaba.fastjson.JSONObject;
import com.codecoord.springboot.quartz.domain.JobInfo;
import java.util.List;
import java.util.Objects;
import javax.annotation.Resource;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.springframework.stereotype.Component;

/**
* job处理器
*
* @author tianxincoord@163.com
* @date 2021/7/20
*/
@Component
public class JobHandler {
@Resource
private Scheduler scheduler;

/**
* 添加任务
*/
@SuppressWarnings("unchecked")
public void addJob(JobInfo jobInfo) throws SchedulerException, ClassNotFoundException {
Objects.requireNonNull(jobInfo, "任务信息不能为空");

// 生成job key
JobKey jobKey = JobKey.jobKey(jobInfo.getJobName(), jobInfo.getJobGroup());
// 当前任务不存在才进行添加
if (!scheduler.checkExists(jobKey)) {
Class<Job> jobClass = (Class<Job>)Class.forName(jobInfo.getClassName());
// 任务明细
JobDetail jobDetail = JobBuilder
.newJob(jobClass)
.withIdentity(jobKey)
.withIdentity(jobInfo.getJobName(), jobInfo.getJobGroup())
.withDescription(jobInfo.getJobName())
.build();
// 配置信息
jobDetail.getJobDataMap().put("config", jobInfo.getConfig());
// 定义触发器
TriggerKey triggerKey = TriggerKey.triggerKey(jobInfo.getTriggerName(), jobInfo.getTriggerGroup());
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity(triggerKey)
.withSchedule(CronScheduleBuilder.cronSchedule(jobInfo.getCron()))
.build();
scheduler.scheduleJob(jobDetail, trigger);
} else {
throw new SchedulerException(jobInfo.getJobName() + "任务已存在,无需重复添加");
}
}

/**
* 任务暂停
*/
public void pauseJob(String jobGroup, String jobName) throws SchedulerException {
JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
if (scheduler.checkExists(jobKey)) {
scheduler.pauseJob(jobKey);
}
}

/**
* 继续任务
*/
public void continueJob(String jobGroup, String jobName) throws SchedulerException {
JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
if (scheduler.checkExists(jobKey)) {
scheduler.resumeJob(jobKey);
}
}

/**
* 删除任务
*/
public boolean deleteJob(String jobGroup, String jobName) throws SchedulerException {
JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
if (scheduler.checkExists(jobKey)) {
return scheduler.deleteJob(jobKey);
}
return false;
}

/**
* 获取任务信息
*/
public JobInfo getJobInfo(String jobGroup, String jobName) throws SchedulerException {
JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
if (!scheduler.checkExists(jobKey)) {
return null;
}
List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
if (Objects.isNull(triggers)) {
throw new SchedulerException("未获取到触发器信息");
}
TriggerKey triggerKey = triggers.get(0).getKey();
Trigger.TriggerState triggerState = scheduler.getTriggerState(triggerKey);
JobDetail jobDetail = scheduler.getJobDetail(jobKey);

JobInfo jobInfo = new JobInfo();
jobInfo.setJobName(jobGroup);
jobInfo.setJobGroup(jobName);
jobInfo.setTriggerName(triggerKey.getName());
jobInfo.setTriggerGroup(triggerKey.getGroup());
jobInfo.setClassName(jobDetail.getJobClass().getName());
jobInfo.setStatus(triggerState.toString());

if (Objects.nonNull(jobDetail.getJobDataMap())) {
jobInfo.setConfig(JSONObject.toJSONString(jobDetail.getJobDataMap()));
}

CronTrigger theTrigger = (CronTrigger) triggers.get(0);
jobInfo.setCron(theTrigger.getCronExpression());
return jobInfo;
}
}

新建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
java复制代码package com.codecoord.springboot.quartz.controller;

import com.codecoord.springboot.quartz.domain.JobInfo;
import com.codecoord.springboot.quartz.handler.JobHandler;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import javax.annotation.Resource;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerKey;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
* Quartz控制器
*
* @author tianxincoord@163.com
* @date 2021/7/20
*/
@RestController
@RequestMapping("/job")
public class QuartzController {

@Resource
private JobHandler jobHandler;
@Resource
private Scheduler scheduler;

/**
* http://localhost:8888/job/all
*/
@RequestMapping("/all")
public List<JobInfo> list() throws SchedulerException {
List<JobInfo> jobInfos = new ArrayList<>();
List<String> triggerGroupNames = scheduler.getTriggerGroupNames();
for (String triggerGroupName : triggerGroupNames) {
Set<TriggerKey> triggerKeySet = scheduler
.getTriggerKeys(GroupMatcher.triggerGroupEquals(triggerGroupName));
for (TriggerKey triggerKey : triggerKeySet) {
Trigger trigger = scheduler.getTrigger(triggerKey);
JobKey jobKey = trigger.getJobKey();
JobInfo jobInfo = jobHandler.getJobInfo(jobKey.getGroup(), jobKey.getName());
jobInfos.add(jobInfo);
}
}
return jobInfos;
}

/**
* http://localhost:8888/job/add
*
* {
* "className": "com.codecoord.springboot.quartz.job.PlanRemindJob",
* "config": "配置信息,例如存储json",
* "cron": "0/3 * * * * ?",
* "jobGroup": "STANDARD_JOB_GROUP",
* "jobName": "计划任务通知任务",
* "triggerGroup": "STANDARD_TRIGGER_GROUP",
* "triggerName": "计划任务通知触发器"
* }
*
* {
* "className": "com.codecoord.springboot.quartz.job.TimeEventJob",
* "config": "配置信息,例如存储json",
* "cron": "0/10 * * * * ?",
* "jobGroup": "STANDARD_JOB_GROUP",
* "jobName": "时间通知任务",
* "triggerGroup": "STANDARD_TRIGGER_GROUP",
* "triggerName": "时间通知触发器"
* }
*/
@PostMapping("/add")
public JobInfo addJob(@RequestBody JobInfo jobInfo) throws SchedulerException, ClassNotFoundException {
jobHandler.addJob(jobInfo);
return jobInfo;
}

/**
* http://localhost:8888/job/pause?jobGroup=STANDARD_JOB_GROUP&jobName=计划任务通知任务
* http://localhost:8888/job/pause?jobGroup=STANDARD_JOB_GROUP&jobName=时间通知任务
*/
@RequestMapping("/pause")
public void pauseJob(@RequestParam("jobGroup") String jobGroup, @RequestParam("jobName") String jobName)
throws SchedulerException {
jobHandler.pauseJob(jobGroup, jobName);
}

/**
* http://localhost:8888/job/continue?jobGroup=STANDARD_JOB_GROUP&jobName=计划任务通知任务
* http://localhost:8888/job/continue?jobGroup=STANDARD_JOB_GROUP&jobName=时间通知任务
*/
@RequestMapping("/continue")
public void continueJob(@RequestParam("jobGroup") String jobGroup, @RequestParam("jobName") String jobName)
throws SchedulerException {
jobHandler.continueJob(jobGroup, jobName);
}

/**
* http://localhost:8888/job/delete?jobGroup=STANDARD_JOB_GROUP&jobName=计划任务通知任务
* http://localhost:8888/job/delete?jobGroup=STANDARD_JOB_GROUP&jobName=时间通知任务
*/
@RequestMapping("/delete")
public boolean deleteJob(@RequestParam("jobGroup") String jobGroup, @RequestParam("jobName") String jobName)
throws SchedulerException {
return jobHandler.deleteJob(jobGroup, jobName);
}
}

三、Quartz测试

  1. 通过POSTMAN/apiPost等工具添加任务,请求数据都在对应接口上
  2. 观察对应任务是否有进行执行以及数据库中是否有对应任务,例如下面3张表
1
2
3
4
5
sql复制代码use quartz_config;

select * from QRTZ_CRON_TRIGGERS;
select * from QRTZ_TRIGGERS;
select * from QRTZ_JOB_DETAILS;

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%