Spring+Quartz 实现手动开关定时器

Spring+Quartz 实现手动开关定时器


在之前已经讲解了如果配置静态的quartz定时器(传送门:quartz定时器 ),不知道 各位小伙伴有没有成功呢,这次分享的是动态增删停止恢复定时器; 这里通过在页面传几个参数就可以控制定时器的启用关闭,而不用修改配置文件,是不是更方便了呢。不说废话,下面开始。


需要的jar包


在上个quartz中,我们用的是quartz-all-1.6.0.jar这个包,这次我们不用这个包,用的新特新2.0之后的包,需要下载quartz-2.2.1.jar、quartz-jobs-2.2.1.jar;


applocationContext.xml中配置


在applicationContext.xml中最后面加上下面这段代码即可:


1
2
3
4
5
<!-- 这句话是为了实现在job中使用注解,注入service -->
<bean id="jobFactory" class="com.reassure.quartz.JobFactory"></bean>
<bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="jobFactory" ref="jobFactory"></property>
</bean>

创建QuartzJob继承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
package com.reassure.quartz;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import com.reassure.sys.entity.ScheduleJob;
/**
* 通过注解实现有状态的job
* @author Administrator
*
*/
@DisallowConcurrentExecution
public class QuartzJob implements Job{
@Override
public void execute(JobExecutionContext job) throws JobExecutionException {
ScheduleJob scheduleJob = (ScheduleJob)job.getMergedJobDataMap().get("scheduleJob");
String name=scheduleJob.getJobName();
System.out.println("定时器"+name+"正在运行。。。。。");
}
}

在这里用到的jScheduleJob是自己创建的一个实体,里面存放的是一个定时任务的各个属性,原来我是准备存在数据库的,后面发现没有必要,
如果各位小伙伴有需要,就可以创建一个表,动态读取数据库。


创建ScheduleJob实体


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.reassure.sys.entity;
public class ScheduleJob {
/** 任务名称 */
private String jobName;
/** 任务分组 */
private String jobGroup;
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;
}
@Override
public String toString() {
return "ScheduleJob [jobName=" + jobName + ", jobGroup=" + jobGroup + "]";
}
}

创建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
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
package com.reassure.sys.controller;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.reassure.quartz.QuartzJob;
import com.reassure.sys.entity.ScheduleJob;
@Controller
@RequestMapping(value="quartz")
public class QuartzController {
@Autowired
private Scheduler scheduler;
/**
* 进入定时器管理界面
* @param jobName
* @param jobGroup
* @return
*/
@RequestMapping("/quartzPage")
public String quartzPage(String jobName,String jobGroup){
return "backstageViews/quartz/quartz";
}
/**
* 任务创建与更新(未存在的就创建,已存在的则更新)
* @param request
* @param response
* @param scheduleJob
* @param model
* @return
*/
@RequestMapping(value="/startQuartz")
@ResponseBody
public Map<String,Object> updateQuartz(HttpServletRequest request,String jobName,String jobGroup){
Map<String,Object> map = new HashMap<>();
ScheduleJob job = new ScheduleJob();
job.setJobGroup(jobGroup.trim());
job.setJobName(jobName.trim());
System.out.println(jobName+","+jobGroup);
try {
//获取触发器标识
TriggerKey triggerKey = TriggerKey.triggerKey(jobName.trim(), jobGroup.trim());
//获取触发器trigger
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
if(null==trigger){//不存在任务
//创建任务
JobDetail jobDetail = JobBuilder.newJob(QuartzJob.class)
.withIdentity(jobName.trim(), jobGroup.trim())
.build();
jobDetail.getJobDataMap().put("scheduleJob", job);
//表达式调度构建器
//这里的时间也可以通过页面传送过来。具体怎么写请看上一篇quartz介绍
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("0/10 * * * * ?");
//按新的cronExpression表达式构建一个新的trigger
trigger = TriggerBuilder.newTrigger()
.withIdentity(job.getJobName(), job.getJobGroup())
.withSchedule(scheduleBuilder)
.build();
scheduler.scheduleJob(jobDetail, trigger);
}else{//存在任务
// Trigger已存在,那么更新相应的定时设置
//表达式调度构建器
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("0/5 * * * *");
//按新的cronExpression表达式重新构建trigger
trigger = trigger.getTriggerBuilder()
.withIdentity(triggerKey)
.withSchedule(scheduleBuilder)
.build();
//按新的trigger重新设置job执行
scheduler.rescheduleJob(triggerKey, trigger);
}
} catch (SchedulerException e) {
e.printStackTrace();
}
map.put("msg", "success");
map.put("code", 200);
return map;
}
/**
* 删除任务
* @param request
* @param response
* @param scheduleJob
* @param model
* @return
*/
@RequestMapping(value="/removeQuartz")
public void deleteQuartz(HttpServletRequest request,String jobName,String jobGroup){
JobKey jobKey = JobKey.jobKey(jobName.trim(), jobGroup.trim());
System.out.println("删除"+jobName.trim()+"任务");
try {
scheduler.deleteJob(jobKey);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* 暂停任务
* @param request
* @param response
* @param job
* @param model
* @return
*/
@RequestMapping(value="/pauseQuartz")
public void pauseQuartz(HttpServletRequest request,String jobName,String jobGroup){
ScheduleJob job = new ScheduleJob();
job.setJobGroup(jobGroup);
job.setJobName(jobName);
System.out.println(jobName+","+jobGroup);
JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
try {
scheduler.pauseJob(jobKey);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* 恢复任务
* @param request
* @param response
* @param scheduleJob
* @param model
* @return
*/
@RequestMapping(value="/resumeQuartz")
public void resumeQuartz(HttpServletRequest request,String jobName,String jobGroup){
ScheduleJob job = new ScheduleJob();
job.setJobGroup(jobGroup);
job.setJobName(jobName);
System.out.println(jobName+","+jobGroup);
JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
try {
scheduler.resumeJob(jobKey);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
}

quartz这里是通过名字辨别每个定时器的,你开启了一个name叫aaa的定时器,那么关闭的时候,传aaa这个名字就可以关闭了。
到这里,如果你不需要在定时器里面用到spring的注入,那么就可以把applicationContext配置的文件改成:


1
<bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" />

然后就可以用了,当然在定时器里面用不到注入的应该很少,所以我们还得加入一段代码实现这个功能。


创建JobFactory


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.reassure.quartz;
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.scheduling.quartz.AdaptableJobFactory;
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;
}
}

将刚才applicationContext.xml的代码改回最开始说的。然后写一个jsp页面,当然,如果闲麻烦就可以直接在浏览器地址栏上面访问,
比如我这里是:localhost:8080/[项目名]/quartz/startQuartz?jobName=aaa&jobGroup=1”,
然后这个叫aaa的定时器就启动了,定时时间我已经硬编码写在了controller里面,根据需要可以修改,也可以直接在页面上面传值过来;
删除任务就是:localhost:8080/[项目名]/quartz/removeQuartz?jobName=aaa&jobGroup=1”。
到这里quartz手动开关就算是实现了,谢谢各位小伙伴们的观看~

文章目录
  1. 1. 需要的jar包
  2. 2. applocationContext.xml中配置
  3. 3. 创建QuartzJob继承Job
  4. 4. 创建ScheduleJob实体
  5. 5. 创建controller
  6. 6. 创建JobFactory
,