您的位置:首页 > 编程语言 > Java开发

使用Spring + quartz实现定时任务调度

2018-02-28 17:28 761 查看
需求如下:用户可以设置定时发送短信.

一.环境准备

1.maven导入

<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>
1
2
3
4
5
6
7
8
9
10

2.数据库建立quartz表

网上找.注意替换 
ENGINE=InnoDB

3.classpath下创建配置文件:

quartz.properties
# Configure Main Scheduler Properties
org.quartz.scheduler.instanceName=MyTestQuartz
org.quartz.scheduler.instanceId=AUTO
org.quartz.scheduler.skipUpdateCheck=true

# Configure ThreadPool
org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount=40
org.quartz.threadPool.threadPriority=4

# Configure JobStore
#org.quartz.jobStore.class=org.quartz.simpl.RAMJobStore//保存在内存
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.dataSource=QRTZ_DS
//默认前缀 可以按需修改
org.quartz.jobStore.tablePrefix=QRTZ_
org.quartz.jobStore.isClustered=true

#config datasource
org.quartz.dataSource.QRTZ_DS.driver=com.mysql.jdbc.Driver
org.quartz.dataSource.QRTZ_DS.URL=jdbc:mysql://10.1.1.1:3306/testdb?createDatabaseIfNotExist=true&autoReconnect=true&useUnicode=true&characterEncoding=utf8
org.quartz.dataSource.QRTZ_DS.user=root
org.quartz.dataSource.QRTZ_DS.password=root
org.quartz.dataSource.QRTZ_DS.maxConnections=100

# Configure Plugins
org.quartz.plugin.triggHistory.class=org.quartz.plugins.history.LoggingJobHistoryPlugin
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

二.Spring配置

applicationContext.quartz.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> 
<bean name="schedulerFactoryBean" lazy-init="false"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="configLocation" value="classpath:quartz.properties" />
</bean>

<bean id="quartzService"
class="com.wlqq.mcs.admin.timer.quartz.service.impl.QuartzServiceImpl">
<property name="sched" ref="schedulerFactoryBean" />
</bean>

</beans>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

三.代码清单

目录结构如下图所示 


1.QuartzService.java
package xxx;

import java.text.ParseException;
import java.util.Date;
import java.util.concurrent.TimeUnit;

import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.SchedulerException;

public interface QuartzService {

/**
* 添加按间隔执行任务
* @param jobName 任务名称
* @param jobGroup 任务组名称
* @param triggerName 触发器名称
* @param triggerGroup 触发器组名称
* @param job 任务实例
* @param newJobDataMap 状态参数值
* @param interval 时间间隔
* @param timeUnit 时间单位
* @return
* @throws SchedulerException
* @throws ParseException
*/
Date addIntervalJob(String jobName, String jobGroup, String triggerName,
String triggerGroup, Job job, JobDataMap newJobDataMap,
Integer interval, TimeUnit timeUnit) throws SchedulerException, ParseException;

/**
* 添加按间隔执行任务
* @param job 任务实例
* @param newJobDataMap 状态参数值
* @param interval 时间间隔
* @param timeUnit 时间单位
* @return
* @throws SchedulerException
* @throws ParseException
*/
Date addIntervalJob(Job job, JobDataMap newJobDataMap,
Integer interval, TimeUnit timeUnit) throws SchedulerException, ParseException;

/**
* 修改按间隔执行任务
* @param jobName 任务名称
* @param jobGroup 任务组名称
* @param triggerName 触发器名称
* @param triggerGroup 触发器组名称
* @param job 任务实例
* @param newJobDataMap 状态参数值
* @param interval 时间间隔
* @param timeUnit 时间单位
* @return
* @throws SchedulerException
* @throws ParseException
*/
Date modifyIntervalJob(String jobName, String jobGroup, String triggerName,
String triggerGroup, Job job, JobDataMap newJobDataMap,
Integer interval, TimeUnit timeUnit) throws SchedulerException, ParseException;

/**
* 修改按间隔执行任务时间间隔
* @param triggerName 触发器名称
* @param triggerGroup 触发器组名称
* @param interval 时间间隔
* @param timeUnit 时间单位
* @return
* @throws SchedulerException
* @throws ParseException
*/
Date modifyJobInterval(String triggerName, String triggerGroup,
Integer interval, TimeUnit timeUnit) throws SchedulerException, ParseException;

/**
* 添加计划任务
* @param jobName 任务名称
* @param jobGroup 任务组名称
* @param triggerName 触发器名称
* @param triggerGroup 触发器组名称
* @param job 任务实例
* @param newJobDataMap 状态参数值
* @param cronExpression cron执行表达式
* @return
* @throws SchedulerException
* @throws ParseException
*/
Date addCronJob(String jobName, String jobGroup, String triggerName,
String triggerGroup, Job job, JobDataMap newJobDataMap, String cronExpression)
throws SchedulerException, ParseException;

/**
* 添加计划任务
* @param job 任务实例
* @param newJobDataMap 状态参数值
* @param cronExpression cron执行表达式
* @return
* @throws SchedulerException
* @throws ParseException
*/
public Date addCronJob(Job job, JobDataMap newJobDataMap,String cronExpression)
throws SchedulerException, ParseException;

/**
* 修改计划任务
*
* @param jobName
* @param jobGroup
* @param triggerName
* @param triggerGroup
* @param job
* @param cronExpression
* @return
* @throws SchedulerException
* @throws ParseException
*/
Date modifyCronJob(String jobName, String jobGroup, String triggerName,
String triggerGroup, Job job, JobDataMap newJobDataMap, String cronExpression)
throws SchedulerException, ParseException;

/**
* 修改计划任务的触发时间
*
* @param triggerName
* @param triggerGroupName
* @param cronExpression
* @throws SchedulerException
* @throws ParseException
*/
Date modifyCronJobTime(String triggerName, String triggerGroupName,
String cronExpression) throws SchedulerException, ParseException;

/**
* 移除任务
*
* @param jobName
* @param jobGroup
* @param triggerName
* @param triggerGroupName
* @throws SchedulerException
*/
boolean removeJob(String jobName, String jobGroup,
String triggerName, String triggerGroupName)
throws SchedulerException;

/**
* 暂停任务
*
* @param jobName
* @param jobGroup
* @return
* @throws SchedulerException
*/
void pauseJob(String jobName, String jobGroup,
String triggerName, String triggerGroupName)
throws SchedulerException;

/**
* 恢复任务
*
* @param jobName
* @param jobGroup
* @return
* @throws SchedulerException
*/
void resumeJob(String jobName, String jobGroup,
String triggerName, String triggerGroupName)
throws SchedulerException;

}
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
2.QuartzServiceImpl.java
package xxx;

import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;
import java.text.ParseException;
import java.util.Date;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import org.quartz.CronScheduleBuilder;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.ScheduleBuilder;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerKey;

import xxx.QuartzService;

public class QuartzServiceImpl implements QuartzService{
private Scheduler sched;

public void setSched(Scheduler sched) {
this.sched = sched;
}

private Date addJob(String jobName, String jobGroup, String triggerName,
String triggerGroup, Job job, JobDataMap newJobDataMap,
ScheduleBuilder scheduleBuilder) throws SchedulerException, ParseException  {
if (scheduleBuilder == null) {
return null;
}
JobBuilder builder = newJob(job.getClass());
builder.setJobData(newJobDataMap);
JobDetail jobDetail = builder.withIdentity(jobName, jobGroup).build();
// 触发器
Trigger trigger = newTrigger().withIdentity(triggerName, triggerGroup)
.withSchedule(scheduleBuilder)
.build();
Date date = sched.scheduleJob(jobDetail, trigger);
// 启动
if (!sched.isShutdown()) {
sched.start();
}
return date;
}

private Date modifyJobScheduler(String triggerName, String triggerGroupName,
ScheduleBuilder scheduleBuilder) throws SchedulerException, ParseException {
if (scheduleBuilder == null) {
return null;
}
TriggerKey key = new TriggerKey(triggerName, triggerGroupName);
Trigger trigger = sched.getTrigger(key);
if (trigger != null) {
trigger.getTriggerBuilder()
.withSchedule(scheduleBuilder)
.build();
return sched.rescheduleJob(key, trigger);
}
return null;
}

private SimpleScheduleBuilder intervalScheduleBuilder(Integer interval, TimeUnit timeUnit) {
SimpleScheduleBuilder simpleScheduleBuilder = SimpleScheduleBuilder.simpleSchedule().repeatForever();

switch (timeUnit) {
case MINUTES:
simpleScheduleBuilder.withIntervalInMinutes(interval);
break;
case HOURS:
simpleScheduleBuilder.withIntervalInHours(interval);
break;
case DAYS:
simpleScheduleBuilder.withIntervalInHours(interval * 24);
break;
default:
return null;
}
return simpleScheduleBuilder;
}

@Override
public Date addIntervalJob(String jobName, String jobGroup, String triggerName, String triggerGroup,
Job job, JobDataMap newJobDataMap,
Integer interval, TimeUnit timeUnit) throws SchedulerException, ParseException {

return addJob(jobName, jobGroup, triggerName, triggerGroup, job, newJobDataMap,
intervalScheduleBuilder(interval, timeUnit));
}

@Override
public Date addIntervalJob(Job job, JobDataMap newJobDataMap,
Integer interval, TimeUnit timeUnit) throws SchedulerException, ParseException {
String id=UUID.randomUUID().toString().replaceAll("-", "");
return addIntervalJob(id, id, id, id, job, newJobDataMap, interval, timeUnit);
}

@Override
public Date modifyIntervalJob(String jobName, String jobGroup, String triggerName, String triggerGroup,
Job job, JobDataMap newJobDataMap,
Integer interval, TimeUnit timeUnit) throws SchedulerException, ParseException {
removeJob(jobName, jobGroup, triggerName, triggerGroup);
return addIntervalJob(jobName, jobGroup, triggerName, triggerGroup, job, newJobDataMap, interval, timeUnit);
}

@Override
public Date modifyJobInterval(String triggerName, String triggerGroup,
Integer interval, TimeUnit timeUnit) throws SchedulerException, ParseException {
return modifyJobScheduler(triggerName, triggerGroup, intervalScheduleBuilder(interval, timeUnit));
}

/**
* 添加任务
*
* @param jobName
*            任务名称
* @param jobGroup
*            任务组名称
* @param triggerName
*            触发器名称
* @param triggerGroup
*            触发器组名称
* @param job
*            任务实例
* @param cronExpression
*            cron表达式
* @throws SchedulerException
* @throws ParseException
*/
public Date addCronJob(String jobName, String jobGroup, String triggerName,
String triggerGroup, Job job, JobDataMap newJobDataMap,
String cronExpression) throws SchedulerException, ParseException {
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
return addJob(jobName, jobGroup, triggerName, triggerGroup, job, newJobDataMap, cronScheduleBuilder);
}

@Override
public Date addCronJob(Job job, JobDataMap newJobDataMap, String cronExpression)
throws SchedulerException, ParseException {
String id=UUID.randomUUID().toString().replaceAll("-", "");
return addCronJob(id, id, id, id, job, newJobDataMap, cronExpression);
}

/**
* 修改任务
*
* @param jobName
* @param jobGroup
* @param triggerName
* @param triggerGroup
* @param job
* @param cronExpression
* @return
* @throws SchedulerException
* @throws ParseException
*/
public Date modifyCronJob(String jobName, String jobGroup, String triggerName,
String triggerGroup, Job job,JobDataMap newJobDataMap, String cronExpression)
throws SchedulerException, ParseException {
removeJob(jobName, jobGroup, triggerName, triggerGroup);
return addCronJob(jobName, jobGroup, triggerName, triggerGroup, job, newJobDataMap,
cronExpression);
}

/**
* 修改一个任务的触发时间
*
* @param triggerName
* @param triggerGroupName
* @param cronExpression
* @throws SchedulerException
* @throws ParseException
*/
public Date modifyCronJobTime(String triggerName, String triggerGroupName,
String cronExpression) throws SchedulerException, ParseException {
return modifyJobScheduler(triggerName, triggerGroupName,
CronScheduleBuilder.cronSchedule(cronExpression));
}

/**
* 移除任务
*
* @param jobName
* @param jobGroup
* @param triggerName
* @param triggerGroupName
* @throws SchedulerException
*/
public boolean removeJob(String jobName, String jobGroup,
String triggerName, String triggerGroupName)
throws SchedulerException {
TriggerKey key = new TriggerKey(triggerName, triggerGroupName);
sched.pauseTrigger(key);// 停止触发器
sched.unscheduleJob(key);// 移除触发器

JobKey jobKey = new JobKey(jobName, jobGroup);
return sched.deleteJob(jobKey);// 删除任务
}

/**
* 暂停任务
*
* @param jobName
* @param jobGroup
* @param triggerName
* @param triggerGroupName
* @throws SchedulerException
*/
public void pauseJob(String jobName, String jobGroup, String triggerName,
String triggerGroupName) throws SchedulerException {
TriggerKey key = new TriggerKey(triggerName, triggerGroupName);
sched.pauseTrigger(key);// 停止触发器

JobKey jobKey = new JobKey(jobName, jobGroup);
sched.pauseJob(jobKey);// 停止任务
}

/**
* 恢复任务
*
* @param jobName
* @param jobGroup
* @param triggerName
* @param triggerGroupName
* @throws SchedulerException
*/
public void resumeJob(String jobName, String jobGroup, String triggerName,
String triggerGroupName) throws SchedulerException {
TriggerKey key = new TriggerKey(triggerName, triggerGroupName);
sched.resumeTrigger(key);// 重启触发器

JobKey jobKey = new JobKey(jobName, jobGroup);
sched.resumeJob(jobKey);// 重启任务
}
}
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
3.MassSmsJob.java (群发短信job)
package xxx.quartz.job;

import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;

import xxx.commons.exceptions.BusinessException;
import xxx.httpcommons.util.SpringContextUtil;
import xxx.service.SmsMassService;

/**
* 群发短信job
* @author Mingchenchen
*
*/
public class MassSmsJob implements Job{
public static final String SMS_MASS_JOB_GROUP = "smsMassJob"; // jobGroup
public static final String SMS_MASS_TRIGGER_GROUP = "smsMassTrigger"; // triggerGroup

@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
JobDataMap datamap = context.getJobDetail().getJobDataMap();

String smsMassUuid = datamap.getString("uuid");
String title = datamap.getString("title");
String message = datamap.getString("message");
String phones = datamap.getString("phones");

try {
//此处就是定时任务实际执行的逻辑
SmsMassService smsMassService = SpringContextUtil.getBean(SmsMassService.class);
smsMassService.sendSms(smsMassUuid, title, message, phones);
} catch (BusinessException e) {
e.printStackTrace();
}
}

}

//业务逻辑
public void sendSms(String smsMassUuid, String title,
String message, String phones){
//调用sms群发短信
//TODO

//修改数据库标志位为已经发送
smsMassDao.setSended(smsMassUuid);
}
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
4.CronExpressionUtils.java
package xxx.quartz.utils;

import java.util.Calendar;
import java.util.Date;

public class CronExpressionUtils {

/**
* 根据一个时间解析成cron表达式
* @param date
* @return
*/
public static String getCronExpressionByDate(Date date){
String cronExpression = "";

Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH) + 1; //注意从0开始
int day = calendar.get(Calendar.DAY_OF_MONTH);
int hour = calendar.get(Calendar.HOUR_OF_DAY);
int minute = calendar.get(Calendar.MINUTE);
int second = calendar.get(Calendar.SECOND);

// "30 10 1 20 10 ? 2011" 2011年10月20号1点10分30秒触发任务,?是第几周 不指定
cronExpression = second + " " + minute + " " + hour + " "
+ day + " " + month + " ? " + year;
return cronExpression;
}
}
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
5.业务逻辑service调用 SmsMassServiceImpl.java
@Value("${sms.mass.interval.minite:10}")
private int smsMassInterval; //群发短信的间隔,默认是10分钟
@Autowired
private SmsMassDao smsMassDao;
@Autowired
private QuartzService quartzService;

/**
* 创建定时任务
* @param uuid
* @param title
* @param message
* @param sendTime
* @param phones
* @throws BusinessException
*/
private void createSmsMassCronJob(SmsMassRecord record) throws BusinessException{
MassSmsJob job = new MassSmsJob();
JobDataMap dataMap = new JobDataMap();
dataMap.put("uuid", record.getUuid());
dataMap.put("title", record.getTitle());
dataMap.put("message", record.getMessage());
dataMap.put("phones", record.getPhones());

String jobName = record.getUuid();
String jobGroup = MassSmsJob.SMS_MASS_JOB_GROUP;
String triggerName = record.getUuid();
String triggerGroup = MassSmsJob.SMS_MASS_TRIGGER_GROUP;

Date date = record.getSendTime();
String cronExpression = CronExpressionUtils.getCronExpressionByDate(date);
try {
quartzService.addCronJob(jobName, jobGroup, triggerName,
triggerGroup, job, dataMap, cronExpression);
} catch (SchedulerException | ParseException e) {
e.printStackTrace();
throw new BusinessException(ResultCode.SYSTEM_EXCEPTION.code(), ResultCode.SYSTEM_EXCEPTION.message());
}
}
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
其他地方需要调用SpringContextUtil.getBean(QuartzService.class);即可
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  spring quartz