在之前已经讲解了如果配置静态的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中最后面加上下面这段代码即可:
<!-- 这句话是为了实现在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
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实体
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
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配置的文件改成:
<bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" />
然后就可以用了,当然在定时器里面用不到注入的应该很少,所以我们还得加入一段代码实现这个功能。
创建JobFactory
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手动开关就算是实现了,谢谢各位小伙伴们的观看~