在之前已經講解了如果配置靜態的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手動開關就算是實現了,謝謝各位小伙伴們的觀看~