添加 maven 依赖

在 pom.xml 中添加 quartz 对应的依赖

1
2
3
4
5
6
7
8
9
10
11
12
<dependencies>
<!-- alibaba 的 druid 数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
</dependencies>

首先启动类中添加 @EnableScheduling

1
2
3
4
5
6
7
8
9
@SpringBootApplication
@EnableScheduling
public class MyApplication{

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

}

添加 application.yml 的配置

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
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver
druid:
url: jdbc:mysql://localhost:3306/qrtz?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false
username: root
password: root
initial-size: 10
max-active: 100
min-idle: 10
max-wait: 60000
pool-prepared-statements: true
max-pool-prepared-statement-per-connection-size: 20
time-between-eviction-runs-millis: 60000
min-evictable-idle-time-millis: 300000
validation-query: SELECT 1 FROM DUAL
test-while-idle: true
test-on-borrow: false
test-on-return: false
stat-view-servlet:
enabled: true
url-pattern: /druid/*
login-username: admin
login-password: admin
filter:
stat:
log-slow-sql: true
slow-sql-millis: 1000
merge-sql: true
wall:
config:
multi-statement-allow: true
quartz:
defaultJobGroupName: HVNOBUG_JOB_GROUP
defaultTriggerGroupName: HVNOBUG_TRIGGER_GROUP
properties:
org:
quartz:
scheduler:
instanceName: clusteredScheduler
instanceId: AUTO
jobStore:
dataSource: qrtz
class: org.quartz.impl.jdbcjobstore.JobStoreTX
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
tablePrefix: QRTZ_
isClustered: true
clusterCheckinInterval: 10000
useProperties: false
threadPool:
class: org.quartz.simpl.SimpleThreadPool
threadCount: 10
threadPriority: 5
threadsInheritContextClassLoaderOfInitializingThread: true
job-store-type: jdbc
jdbc:
initialize-schema: never
datasource:
qrtz:
connection-provider:
class: com.hvnobug.quartz.demo.config.DruidConnectionProvider

创建 DruidConnectionProvider

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
public class DruidConnectionProvider implements ConnectionProvider, ApplicationContextAware {

private static ApplicationContext applicationContext;

private DruidDataSource dataSource;

@Override
public Connection getConnection() throws SQLException {
return dataSource.getConnection();
}

@Override
public void shutdown() {
dataSource.close();
}

@Override
public void initialize() {
dataSource = (DruidDataSource) applicationContext.getBean(DataSource.class);
}

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
DruidConnectionProvider.applicationContext = applicationContext;
}
}

创建 QuartzService

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
@Service
public class QuartzService {

@Autowired
public QuartzService(Scheduler scheduler) {
this.scheduler = scheduler;
}

private final Scheduler scheduler;

@Value("${spring.quartz.defaultJobGroupName}")
private String jobGroupName;

@Value("${spring.quartz.defaultTriggerGroupName}")
private String triggerGroupName;

public void addJob(String jobName, Class<? extends Job> cls, String time) {
addJob(jobName, cls, time, null);
}

public void addJob(String jobName, Class<? extends Job> cls, String time, Map<String, Object> parameter) {
addJob(jobName, jobGroupName, jobName, triggerGroupName, cls, time, parameter);
}

public void addJob(String jobName, String jobGroupName,
String triggerName, String triggerGroupName, Class<? extends Job> jobClass,
String time) {
addJob(jobName, jobGroupName, triggerName, triggerGroupName, jobClass, time, null);
}

public void addJob(String jobName, String jobGroupName,
String triggerName, String triggerGroupName, Class<? extends Job> jobClass,
String time, Map<String, Object> parameter) {
try {
JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).build();
if (parameter != null && !parameter.isEmpty())
jobDetail.getJobDataMap().put("parameterList", parameter);
CronTrigger trigger = TriggerBuilder
.newTrigger()
.withIdentity(triggerName, triggerGroupName)
.withSchedule(CronScheduleBuilder.cronSchedule(time))
.build();
scheduler.scheduleJob(jobDetail, trigger);
if (!scheduler.isShutdown()) {
scheduler.start();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}

public void modifyJobTime(String jobName, String time) {
try {
TriggerKey triggerKey = TriggerKey.triggerKey(jobName, triggerGroupName);
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
if (trigger == null) {
return;
}
String oldTime = trigger.getCronExpression();
if (!oldTime.equalsIgnoreCase(time)) {
JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
Class<? extends Job> objJobClass = jobDetail.getJobClass();
removeJob(jobName);
addJob(jobName, objJobClass, time);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}

public void modifyJobTime(String triggerName, String triggerGroupName, String time) {
try {
TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
if (trigger == null) {
return;
}
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(trigger.getCronExpression());
String oldTime = trigger.getCronExpression();
if (!oldTime.equalsIgnoreCase(time)) {
trigger = trigger.getTriggerBuilder()
.withIdentity(triggerKey)
.withSchedule(scheduleBuilder)
.withSchedule(CronScheduleBuilder.cronSchedule(time))
.build();
scheduler.rescheduleJob(triggerKey, trigger);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}

public void removeJob(String jobName) {
removeJob(jobName, jobGroupName, jobName, triggerGroupName);
}


public void removeJob(String jobName, String triggerName) {
removeJob(jobName, jobGroupName, triggerName, triggerGroupName);
}


public void removeJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName) {
try {
TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
scheduler.pauseTrigger(triggerKey);
scheduler.unscheduleJob(triggerKey);
scheduler.deleteJob(jobKey);
} catch (Exception e) {
throw new RuntimeException(e);
}
}

public void startJobs() {
try {
scheduler.start();
} catch (Exception e) {
throw new RuntimeException(e);
}
}

public void shutdownJobs() {
try {
if (!scheduler.isShutdown()) {
scheduler.shutdown();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

创建 Job

1
2
3
4
5
6
7
8
public class DemoJob extends QuartzJobBean {

@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {

System.out.println(String.format("now is %d", System.currentTimeMillis()));
}
}

启动 Job

1
2
3
4
5
@Autowired
QuartzService quartzService;

// 每五秒执行一次
quartzService.addJob("demoJob",DemoJob.class,"1/5 * * * * ?");

此时我们可以创建一个 web 页面,通过调用 QuartzService 来实现动态定时任务