quartz定时任务SpringBoot配置

Quartz是Java领域最著名的开源任务调度工具。Quartz提供了极为广泛的特性如持久化任务,集群和分布式任务
官方文档 http://www.quartz-scheduler.org/documentation/quartz-2.1.x/quick-start.html

添加maven依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.3.13.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.3.13.RELEASE</version>
</dependency>

解决Job 中bean 无法注入的问题

1.建一个JobFactory然后 把其设置为 SchedulerFactoryBean 的 JobFactory。其目的是因为我在具体的Job 中 需要Spring 注入一些Service。
所以我们要自定义一个jobfactory, 让其在具体job 类实例化时 使用Spring 的API 来进行依赖注入。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.AdaptableJobFactory;
import org.springframework.stereotype.Component;
@Configuration
@Component
public class JobFactory extends AdaptableJobFactory {
@Autowired
private AutowireCapableBeanFactory capableBeanFactory;

@Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
//调用父类的方法
Object jobInstance = super.createJobInstance(bundle);
//进行注入
capableBeanFactory.autowireBean(jobInstance);
return jobInstance;
}
}

2.新建一个配置类把 SchedulerFactoryBean 设置为自定义的 JobFactory 并用它产生 Scheduler

1
2
3
4
5
6
7
8
9
10
11
12
13
@Autowired
private JobFactory jobFactory;

@Bean(name="schedulerFactoryBean")
public SchedulerFactoryBean getSchedulerFactoryBean() {
SchedulerFactoryBean factoryBean = new SchedulerFactoryBean();
factoryBean.setJobFactory(jobFactory);
//factoryBean.setDataSource(datasource);
return factoryBean;
}
@Bean
public Scheduler scheduler(){
return getSchedulerFactoryBean().getScheduler();

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
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

package com.jianganwei.sfss.manager.impl;


import com.jianganwei.sfss.exception.BusinessException;
import org.apache.commons.lang3.StringUtils;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.*;


/**
*
* Quartz管理器
* @author 李晋科(Jinke Li)
* @version QuartzManager.java, 2018年6月12日 上午00:59:49 李晋科(Jinke Li)
*/
@Component
public class QuartzManager {

private final static Logger LOGGER = LoggerFactory.getLogger(QuartzManager.class);
private static Scheduler scheduler;
private final static String JOB_GROUP_NAME = "OMS_JOBGROUP_NAME";
private final static String TRIGGER_GROUP_NAME = "OMS_TRIGGERGROUP_NAME";
private final static String TRIGGER_REDO_GROUP_NAME = "OMS_TRIGGERREDOGROUP_NAME";

/**
*
* job添加
* @param jobName
* @param objJobClass
* @param time
*/
public static void addJob(String jobName, Class<? extends Job> objJobClass, String time, Date startTime) {
addJob(jobName,objJobClass,time,startTime,null);
}

/**
*
* job添加
* @param jobName
* @param objJobClass
* @param startTime
* @param datas
* @return
*/
public static Date addJob(String jobName, Class<? extends Job> objJobClass, String cronExp, Date startTime, Map<String, Object> datas) {
Date runTime = null;
try {
JobDetail jobDetail = JobBuilder.newJob(objJobClass).withIdentity(jobName, JOB_GROUP_NAME).build();
if(datas != null) {
jobDetail.getJobDataMap().putAll(datas);
}

TriggerBuilder<Trigger> builder = TriggerBuilder.newTrigger()
.withIdentity(jobName, TRIGGER_GROUP_NAME);

if (startTime.getTime() > System.currentTimeMillis()) {
builder.startAt(startTime);
}
if (StringUtils.isNotBlank(cronExp)) {
builder.withSchedule(CronScheduleBuilder.cronSchedule(cronExp));
}
if (StringUtils.isBlank(cronExp)) {
builder.withSchedule(SimpleScheduleBuilder.simpleSchedule());
}

Trigger trigger = builder.build();

runTime = scheduler.scheduleJob(jobDetail, trigger);

if (scheduler.isShutdown()){
scheduler.start();
}
} catch (Exception e) {
LOGGER.error("添加job出错",e);
}

return runTime;
}




/**
*
* job重试调度
* @param jobName
* @param objJobClass
* @param startTime
* @param interval
* @param repeatTimes
* @param datas
* @return
*/
public static Date addRedoJob(String jobName, Class<? extends Job> objJobClass,
Date startTime, int interval, int repeatTimes, Map<String, Object> datas){
Date runTime = null;
JobDetail jobDetail = null;
try {
JobKey jobKey = new JobKey(jobName, JOB_GROUP_NAME);

if(scheduler.checkExists(jobKey)) {
jobDetail = scheduler.getJobDetail(jobKey);
}

if(jobDetail == null) {
jobDetail = JobBuilder.newJob(objJobClass).withIdentity(jobKey).build();
if(datas != null) {
jobDetail.getJobDataMap().putAll(datas);
}
}

SimpleTrigger trigger = TriggerBuilder.newTrigger()
.withIdentity(jobName+"_redo_"+LocalDateTime.now(), TRIGGER_REDO_GROUP_NAME)
.forJob(jobDetail)
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInMinutes(interval).withRepeatCount(repeatTimes))
.startAt(startTime)
.build();

runTime = scheduler.scheduleJob(trigger);
} catch (SchedulerException e) {
LOGGER.error("job重试调度出错",e);
// throw new PcreditTaskEngineException("job重试调度出错",e);
}

return runTime;
}

/**
* 移除所有重试任务
* 有重试任务移除返回true 无返回false
* @param jobKey
*/
public static boolean unScheduleRedo(JobKey jobKey) {
try {
List<? extends Trigger> list = scheduler.getTriggersOfJob(jobKey);
if (null != list) {
for(Trigger trigger: list) {
if(TRIGGER_REDO_GROUP_NAME.equals(trigger.getKey().getGroup())) {
scheduler.unscheduleJob(trigger.getKey());
return true;
}
}
}
} catch (SchedulerException e) {
LOGGER.error("取消重任务失败 jobName{}",jobKey,e);
}
return false;
}

/**
* 取消任务计划(仅)
* @param triggerKey
*/
public static void unScheduleJob(TriggerKey triggerKey) {
try {
scheduler.unscheduleJob(triggerKey);
} catch (SchedulerException e) {
LOGGER.error("取消任务失败 triggerName{}",triggerKey.getName(),e);

}
}


/**
*
* job移除
* @param jobName
*/
public static void removeJob(String jobName) {
try {
scheduler.pauseTrigger(new TriggerKey(jobName, TRIGGER_GROUP_NAME));
scheduler.unscheduleJob(new TriggerKey(jobName, TRIGGER_GROUP_NAME));
scheduler.deleteJob(new JobKey(jobName, JOB_GROUP_NAME));
} catch (Exception e) {
LOGGER.error("移除job抛错",e);
}
}

/**
* 删除所有任务
*/
public static void removeAllJob() {
try {
GroupMatcher<JobKey> matcher = GroupMatcher.groupEquals(JOB_GROUP_NAME);
Set<JobKey> jobkeySet = null;
jobkeySet = scheduler.getJobKeys(matcher);
List<JobKey> jobkeyList = new ArrayList<JobKey>();
jobkeyList.addAll(jobkeySet);
scheduler.deleteJobs(jobkeyList);
} catch (SchedulerException e) {
e.printStackTrace();
}
}

/**
* 检查任务存在
*
* @param jobName
* @return
*/
public static boolean checkJobExists(String jobName){
try {
JobKey jobKey = new JobKey(jobName, JOB_GROUP_NAME);
return scheduler.checkExists(jobKey);
} catch (Exception e) {
LOGGER.error("检查任务出错",e);
throw new BusinessException("100000000","检查任务出错",1);
}

}

/**
* 开启调度
*/
public static void startJobs() {
try {
scheduler.start();
} catch (Exception e) {
LOGGER.error("启动调度出错",e);
}
}

/**
* 关闭调度-关闭后不能重启
*/
public static void shutdownJobs() {
try {
if(!scheduler.isShutdown()) {
scheduler.shutdown();
}
} catch (Exception e) {
LOGGER.error("关闭调度出错",e);
}
}

/**
* Getter method for <tt>scheduler</tt>.
*
* @return value of scheduler
*/
public static Scheduler getScheduler() {
return scheduler;
}

/**
* Setter method for <tt>scheduler</tt>.
*
* @param scheduler value to be assigned to scheduler
*/
public static void setScheduler(Scheduler scheduler) {
QuartzManager.scheduler = scheduler;
}
}

初始化

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
package com.jianganwei.sfss.init;

import com.jianganwei.sfss.manager.impl.QuartzManager;
import com.jianganwei.sfss.schedule.AlarmTaskJob;
import org.quartz.Scheduler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
* TODO
*
* @author 李晋科(Jinke Li)
* @version TaskInitRunner.java, 2018/6/12 16:31 李晋科(Jinke Li)
*/
@Component
@Order(1)
public class TaskInitRunner implements CommandLineRunner {

@Autowired
private Scheduler scheduler;


@Override
public void run(String... args) throws Exception {
QuartzManager.setScheduler(scheduler);
QuartzManager.removeAllJob();
}

}

添加任务

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
package com.jianganwei.sfss.schedule;

import com.jianganwei.sfss.manager.impl.QuartzManager;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
*
* @program: SFSS
* @description: 添加定时任务
* @author: jianganwei
* @create: 2018-09-11 17:32
**/
@Component
@Order(3)
public class TaskAddRunner implements CommandLineRunner {

@Override
public void run(String... strings) throws Exception {
QuartzManager.addJob("oms_alarm" , AlarmTaskJob.class ,"0 30 11 * * ?",new Date());
QuartzManager.addJob("oms_invalid_contract" , InvalidContractJob.class ,"0 0 1 * * ?",new Date());
QuartzManager.addJob("oms_notice_marketing_file_upload" , NoticeMarketingFileUpLoadJob.class ,"0 */5 * * * ?",new Date());
QuartzManager.addJob("oms_contract_use_status",UpdateContractUsegeStatus.class,"0 */10 * * * ?",new Date());
QuartzManager.addJob("active_contracts_side_agreement",ActiveContractSideAgreementJob.class,"0 * */1 * * ?",new Date());
//todo 补充协议定时任务
}
}