Spring4+Quartz2集群下動(dòng)態(tài)創(chuàng)建編輯Job

quartz實(shí)現(xiàn)原理與集群原理自行百度,本文提供quartz2.2.1版本集群環(huán)境動(dòng)態(tài)創(chuàng)建、調(diào)度、暫停、恢復(fù)、刪除Job方法。

1.quartz集群依賴數(shù)據(jù)庫腳本

quartz集群依賴數(shù)據(jù)庫腳本

2.quartz簡單監(jiān)控表


quartz監(jiān)控表

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


監(jiān)控列表


Job新建頁面

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;

}

9.多個(gè)節(jié)點(diǎn)時(shí)間必須同步

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容