quartz實(shí)現(xiàn)原理與集群原理自行百度,本文提供quartz2.2.1版本集群環(huán)境動(dòng)態(tài)創(chuàng)建、調(diào)度、暫停、恢復(fù)、刪除Job方法。
1.quartz集群依賴數(shù)據(jù)庫腳本
2.quartz簡單監(jiān)控表

3.監(jiān)控列表與新建頁面示例


4.quartz.properties示例
org.quartz.scheduler.instanceName = THScheduler?
org.quartz.scheduler.instanceId = AUTO?
?org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool?
org.quartz.threadPool.threadCount = 10?
org.quartz.threadPool.threadPriority = 5?
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true
org.quartz.jobStore.misfireThreshold = 60000?
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTXorg.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate?
org.quartz.jobStore.tablePrefix = QRTZ_?
org.quartz.jobStore.maxMisfiresToHandleAtATime=10?
org.quartz.jobStore.isClustered = true?
?org.quartz.jobStore.clusterCheckinInterval = 20000
5.容器中基本配置 Spring-quartz.xml示例
<bean name="THScheduler?" lazy-init="true" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">?
?????????<property name="dataSource"> <ref bean="dataSource" /> </property>
?????????<property name="applicationContextSchedulerContextKey" value="applicationContext" />
?????????<property name="configLocation" value="classpath:quartz.properties" />?
?????????<!-- overwriteExistingJobs:覆蓋任務(wù)調(diào)度器中同名的jobDetail,避免只修改了CronExpression所造成的不能重新生效情況 -->?
?????????<property name="overwriteExistingJobs" value="true" />?
</bean>
6.quartz管理類示例
/**
* 修改任務(wù)Cron
*/
public void modifyTigger(String name, String group, String cron)throws SchedulerException {
????????Scheduler scheduler = SPRING_CONTEXT.getBean(Scheduler.class);
????????TriggerKey key = TriggerKey.triggerKey(name, group);
????????Trigger.TriggerState triggerState = scheduler.getTriggerState(key);
????????CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(key).withSchedule(CronScheduleBuilder.cronSchedule(cron)).build();
????????scheduler.rescheduleJob(key, trigger);
????????JobKey k =new JobKey(name, group);
????????log.info("修改任務(wù):{}", name);
????????if(!JobDetails.NORMAL.equals(triggerState.name())){
????????????????scheduler.pauseJob(k);
????????}
}
/**
* 添加Job
* @param jobName job名稱
* @param cls? ? job執(zhí)行類
* @param group? 群組名稱
* @param cron? ? cron表達(dá)式
*/
public void addJob(String jobName, Class cls, String group, String cron)throws SchedulerException {
????????Scheduler sched = SPRING_CONTEXT.getBean(Scheduler.class);
????????// 用于描敘Job實(shí)現(xiàn)類及其他的一些靜態(tài)信息,構(gòu)建一個(gè)作業(yè)實(shí)例
? ? ????JobDetail jobDetail = JobBuilder.newJob(cls).withIdentity(jobName, group).build();
????????// 構(gòu)建一個(gè)觸發(fā)器,規(guī)定觸發(fā)的規(guī)則
? ????? Trigger trigger = TriggerBuilder.newTrigger()// 創(chuàng)建一個(gè)新的TriggerBuilder來規(guī)范一個(gè)觸發(fā)器
? ? ? ? ? ? .withIdentity(jobName, group)// 給觸發(fā)器起一個(gè)名字和組名
? ? ? ? ? ? .startNow()// 立即執(zhí)行
? ? ? ? ? ? .withSchedule(CronScheduleBuilder.cronSchedule(cron))// 觸發(fā)器的執(zhí)行時(shí)間
? ? ? ? ? ? .build();// 產(chǎn)生觸發(fā)器
? ? ????// 調(diào)度Job
? ? ????sched.scheduleJob(jobDetail, trigger);
????????log.debug("添加任務(wù):{},{},{}", jobName, cls, cron);
????????if (!sched.isShutdown()) {
????????????????sched.start();
????????}
}
/**
* 暫停一個(gè)任務(wù)
*/
public void pauseJob(String jobName, String jobGroupName)throws Exception {
????????JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
????????Scheduler sched = SPRING_CONTEXT.getBean(Scheduler.class);
????????sched.pauseJob(jobKey);
????????log.info("暫停任務(wù):{}", jobName);
}
/**
* 恢復(fù)一個(gè)任務(wù)
*/
public void resumeJob(String jobName, String jobGroupName)throws Exception {
????????JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
????????Scheduler sched = SPRING_CONTEXT.getBean(Scheduler.class);
????????sched.resumeJob(jobKey);
????????log.info("恢復(fù)任務(wù):{}", jobName);
}
/**
* 移除一個(gè)任務(wù)
*/
public void removeJob(String jobName, String group)throws SchedulerException {
????????Scheduler sched = SPRING_CONTEXT.getBean(Scheduler.class);
????????JobKey jobKey =new JobKey(jobName, group);
????????// 停止觸發(fā)器
? ? ????sched.pauseJob(jobKey);
????????sched.unscheduleJob(new TriggerKey(jobName, group));// 移除觸發(fā)器
? ? ????sched.deleteJob(jobKey);// 刪除任務(wù)
? ????? log.info("移除任務(wù):{}", jobName);
}
/**
* 啟動(dòng)所有定時(shí)任務(wù)
*/
public void startJobs() {
????????try {
????????????????Scheduler sched = SPRING_CONTEXT.getBean(Scheduler.class);
????????????????sched.start();
????????}catch (Exception e) {
????????????????throw new RuntimeException(e);
????????}
}
7.web層示例(QuartzService中的方法均為對(duì)job監(jiān)控表進(jìn)行的單表crud操作)
/**
* Job列表
*/
@RequestMapping(path ="/quartz/list")
public Page findList(HttpServletRequest req){
????????log.info("查詢job列表");
????????return SPRING_CONTEXT.getBean(QuartzService.class).findList(getPageSort(req));
}
/**
* 跳轉(zhuǎn)至job新建頁面
*/
@RequestMapping(path ="/quartz/to/add/{id}")
public ModelAndView toAdd(@PathVariable Long id, HttpServletRequest req){
????????log.info("調(diào)整至新建頁面,jobId為{}", id);
????????ModelAndView m =new ModelAndView();
????????if(id != -1){
????????????????m.addObject("job", SPRING_CONTEXT.getBean(QuartzService.class).findById(id));
????????}
????????m.addObject("id", id);
????????m.setViewName("/dth/quartz/edit.jsp");
????????return m;
}
/**
* 編輯Job
*/
@RequestMapping(path ="/quartz/save")
public String save(JobDetails jobDetails, HttpServletRequest req)throws Exception {
????return -1 == jobDetails.getId() ? addJob(jobDetails, getSessionUser(req)) : updateJob(jobDetails);
}
/**
* 新建
*/
public String addJob(JobDetails jobDetails, User user)throws BusinessException {
????????log.info("新建job,jobId為{}", jobDetails.getId());
? ? ? ? SPRING_CONTEXT.getBean(QuartzService.class).addJob(jobDetails, user);
????????return success("ok");
}
/**
* 修改Cron與備注
*/
public String updateJob(JobDetails jobDetails)throws Exception {
????????log.info("修改Cron與備注,jobId為{}", jobDetails.getId());
? ? ? ? SPRING_CONTEXT.getBean(QuartzService.class).updateJob(jobDetails);
? ? ? ? SPRING_CONTEXT.getBean(QuartzManagerService.class).modifyTigger(jobDetails.getNames(), jobDetails.getGroups(), ????????jobDetails.getCron());
????????return success("ok");
}
/**
* 開始調(diào)度Job
*/
@RequestMapping(path ="/quartz/schedu/{id}")
public String scheduJob(@PathVariable Long id)throws Exception {
????????log.info("開始調(diào)度Job,jobId為{}", id);
????????JobDetails j = SPRING_CONTEXT.getBean(QuartzService.class).findById(id);
????????j.setStatus(JobDetails.NORMAL);
? ? ? ? SPRING_CONTEXT.getBean(QuartzService.class).updateJobStatus(j);
? ? ? ? SPRING_CONTEXT.getBean(QuartzManagerService.class).addJob(j.getNames(), Class.forName(j.getClassName()), j.getGroups(), ????????j.getCron());
????????return success("ok");
}
/**
* 恢復(fù)執(zhí)行Job
*/
@RequestMapping(path ="/quartz/start/{id}")
public String startJob(@PathVariable Long id)throws Exception {
????????log.info("恢復(fù)執(zhí)行Job,jobId為{}", id);
????????JobDetails j = SPRING_CONTEXT.getBean(QuartzService.class).findById(id);
????????j.setStatus(JobDetails.NORMAL);
? ? ? ? SPRING_CONTEXT.getBean(QuartzService.class).updateJobStatus(j);
? ? ? ? SPRING_CONTEXT.getBean(QuartzManagerService.class).resumeJob(j.getNames(), j.getGroups());
????????return success("ok");
}
/**
* 暫停Job
*/
@RequestMapping(path ="/quartz/stop/{id}")
public String stopJob(@PathVariable Long id)throws Exception {
????????log.info("暫停Job,jobId為{}", id);
????????JobDetails j = SPRING_CONTEXT.getBean(QuartzService.class).findById(id);
????????j.setStatus(JobDetails.PAUSED);
? ? ? ? SPRING_CONTEXT.getBean(QuartzService.class).updateJobStatus(j);
? ? ? ? SPRING_CONTEXT.getBean(QuartzManagerService.class).pauseJob(j.getNames(), j.getGroups());
????????return success("ok");
}
/**
* 刪除Job
*/
@RequestMapping(path ="/quartz/delete/{id}")
public String deleteJob(@PathVariable Long id)throws Exception {
????????log.info("刪除Job,jobId為{}", id);
????????JobDetails j = SPRING_CONTEXT.getBean(QuartzService.class).findById(id);
? ? ? ? SPRING_CONTEXT.getBean(QuartzManagerService.class).removeJob(j.getNames(), j.getGroups());
? ? ? ? SPRING_CONTEXT.getBean(QuartzService.class).deleteJob(j);?
????????return success("ok");
}
8.實(shí)時(shí)獲取內(nèi)存中job信息
@RequestMapping(path ="/testQuartz/list")
public List list()throws SchedulerException {
????????List list =new ArrayList<>();
????????Scheduler scheduler = SPRING_CONTEXT.getBean(Scheduler.class);
????????for (String groupName : scheduler.getJobGroupNames()) {
????????????????for (JobKey jobKey : scheduler.getJobKeys(GroupMatcher.jobGroupEquals(groupName))) {
? ? ? ? ? ? ? ? ? ? ? ? ? ?JobDetails j =new JobDetails();
????????????????????????????j.setNames(jobKey.getName());
????????????????????????????j.setGroups(jobKey.getGroup());
????????????????????????????j.setStatus(scheduler.getTriggerState(TriggerKey.triggerKey(jobKey.getName(), jobKey.getGroup())).toString());
????????????????????????????TriggerKey triggerKey =new TriggerKey(jobKey.getName(), jobKey.getGroup());
????????????????????????????CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
????????????????????????????j.setCron(trigger.getCronExpression());
????????????????????????????j.setPreDate(trigger.getPreviousFireTime());
????????????????????????????j.setNextDate(trigger.getNextFireTime());
????????????????????????????JobDetail jobDetail = scheduler.getJobDetail(new JobKey(jobKey.getName(), jobKey.getGroup()));
????????????????????????????Class objJobClass = jobDetail.getJobClass();
????????????????????????????j.setClassName(objJobClass.getName());
????????????????????????????j.setMethodName(objJobClass.getMethods()[0].getName());
????????????????????????????list.add(j);
????????????????????}
????????}
????????return list;
}