Quartz定時(shí)任務(wù)管理方式(動(dòng)態(tài)添加、停止、恢復(fù)、刪除定時(shí)任務(wù))
Quartz定時(shí)任務(wù)框架經(jīng)常用于系統(tǒng)后臺(tái)業(yè)務(wù)異步處理。平常我們使用時(shí),主要是通過(guò)手工編寫(xiě)配置代碼文件方式添加修改定時(shí)任務(wù),然后重啟系統(tǒng)。
有時(shí)候我們需要根據(jù)業(yè)務(wù)運(yùn)營(yíng)需要,動(dòng)態(tài)添加修改定時(shí)任務(wù),比如添加新的定時(shí)任務(wù)、修改任務(wù)執(zhí)行時(shí)間、暫停定時(shí)任務(wù)、刪除定時(shí)任務(wù)等,并且監(jiān)控定時(shí)任務(wù)狀態(tài),而又不想重啟系統(tǒng),這時(shí)就需要系統(tǒng)具備動(dòng)態(tài)管理定時(shí)任務(wù)的功能。
Quartz提供了一系列組件,支持動(dòng)態(tài)管理定時(shí)任務(wù)的功能。
Quartz定時(shí)任務(wù)主要由Scheduler、JobDetail、CronTrigger、Cron組成,實(shí)現(xiàn)動(dòng)態(tài)管理定時(shí)任務(wù),主要就是通過(guò)管理上述對(duì)象來(lái)實(shí)現(xiàn)的。
1、數(shù)據(jù)庫(kù)設(shè)計(jì)
主要將我們平時(shí)配置的任務(wù)計(jì)劃放入數(shù)據(jù)庫(kù)中保存。在啟動(dòng)任務(wù)是,從數(shù)據(jù)庫(kù)中查找任務(wù)計(jì)劃信息,并動(dòng)態(tài)配置進(jìn)去即可。
DROP TABLE IF EXISTS `cc_task_info`; CREATE TABLE `cc_task_info` ( `TID` int(11) NOT NULL AUTO_INCREMENT, `TASK_ANME` varchar(50) NOT NULL, `TASK_CODE` varchar(50) NOT NULL, `JOB_CLASS` varchar(200) NOT NULL, `JOB_GROUP` varchar(50) NOT NULL, `CRON` varchar(50) NOT NULL, `DEL_STATUS` varchar(2) DEFAULT '1' NULL, `CRT_TIME` datetime DEFAULT NULL, PRIMARY KEY (`TID`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='定時(shí)任務(wù)管理表'; DROP TABLE IF EXISTS `cc_task_record`; CREATE TABLE `cc_task_record` ( `RID` int(11) NOT NULL AUTO_INCREMENT, `TASK_CODE` varchar(50) NOT NULL, `RUN_TIME` datetime NOT NULL, `RUN_CODE` char(1) NOT NULL, `RUN_MSG` varchar(100) NULL, PRIMARY KEY (`RID`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='定時(shí)任務(wù)運(yùn)行記錄表'; DROP TABLE IF EXISTS `cc_task_status`; CREATE TABLE `cc_task_status` ( `TASK_CODE` varchar(50) NOT NULL, `TASK_STATUS` varchar(10) NOT NULL, `LST_SUCC_TIME` datetime NOT NULL, `LST_TIME` datetime NOT NULL, PRIMARY KEY (`TASK_CODE`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='定時(shí)任務(wù)運(yùn)行狀態(tài)表';
2、定時(shí)任務(wù)管理
定時(shí)任務(wù)管理主要是通過(guò)Scheduler的方法來(lái)實(shí)現(xiàn)。Scheduler提供了一系列方法來(lái)管理定時(shí)任務(wù)的執(zhí)行狀態(tài)。
主要包括:
- scheduleJob():添加定時(shí)任務(wù)
- rescheduleJob():修改定時(shí)任務(wù)
- pauseJob():暫停定時(shí)任務(wù)執(zhí)行
- resumeJob():恢復(fù)定時(shí)任務(wù)執(zhí)行
- deleteJob():刪除定時(shí)任務(wù)執(zhí)行
針對(duì)上述方法,我們只需要傳入對(duì)應(yīng)參數(shù)即可。
這里我建了一個(gè)QuartzService來(lái)管理定時(shí)任務(wù),供業(yè)務(wù)層調(diào)用。
詳細(xì)代碼如下:
/** * 定時(shí)任務(wù)管理服務(wù) */ @Service public class QuartzService { public static String SCHEDULER_OPR_START = "start"; public static String SCHEDULER_OPR_PAUSE = "pause"; public static String SCHEDULER_OPR_RESUME = "resume"; public static String SCHEDULER_OPR_REMOVE = "remove"; @Autowired private Scheduler scheduler; /** * 啟動(dòng)任務(wù) */ public void startJob(String taskCode, String taskAnme, String cron, String jobGroup, String className) throws Exception{ Class<Job> jobClass = null; try { jobClass = (Class<Job>) Class.forName(className);//獲取任務(wù)執(zhí)行類(lèi) } catch (ClassNotFoundException e) { throw new Exception("任務(wù)類(lèi)不存在"); } //創(chuàng)建job,指定job名稱(chēng)和分組 JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(taskCode, jobGroup).build(); //創(chuàng)建表達(dá)式工作計(jì)劃 CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(cron); //創(chuàng)建觸發(fā)器 CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(taskCode, jobGroup) .withSchedule(cronScheduleBuilder).build(); scheduler.scheduleJob(jobDetail, cronTrigger); } /** * 修改定時(shí)任務(wù)執(zhí)行時(shí)間 * @param taskCode * @param jobGroup * @param cron 新的時(shí)間 * @throws Exception */ public void modifyJob(String taskCode, String jobGroup, String cron) throws Exception{ TriggerKey triggerKey = new TriggerKey(taskCode, jobGroup); CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey); String oldCron = trigger.getCronExpression(); if(!oldCron.equals(cron)){ CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(taskCode, jobGroup) .withSchedule(CronScheduleBuilder.cronSchedule(cron)).build(); Date date = scheduler.rescheduleJob(triggerKey, cronTrigger); if(date == null){ throw new Exception("修改定時(shí)任務(wù)執(zhí)行時(shí)間報(bào)錯(cuò)"); } } } /** * 暫停某個(gè)定時(shí)任務(wù)(任務(wù)恢復(fù)后,暫停時(shí)間段內(nèi)未執(zhí)行的任務(wù)會(huì)繼續(xù)執(zhí)行,如暫停時(shí)間段內(nèi)有2次,則會(huì)執(zhí)行2次) * @param taskCode * @param jobGroup * @throws Exception */ public void pauseJob(String taskCode, String jobGroup) throws Exception{ JobKey jobKey = new JobKey(taskCode, jobGroup); JobDetail jobDetail = scheduler.getJobDetail(jobKey); if(jobDetail == null){ return; } scheduler.pauseJob(jobKey); } /** * 恢復(fù)某個(gè)定時(shí)任務(wù) * @param taskCode * @param jobGroup * @throws Exception */ public void resumeJob(String taskCode, String jobGroup) throws Exception{ JobKey jobKey = new JobKey(taskCode, jobGroup); JobDetail jobDetail = scheduler.getJobDetail(jobKey); if(jobDetail == null){ return; } scheduler.resumeJob(jobKey); } /** * 刪除某個(gè)定時(shí)任務(wù) * @param taskCode * @param jobGroup * @throws Exception */ public void deleteJob(String taskCode, String jobGroup) throws Exception{ JobKey jobKey = new JobKey(taskCode, jobGroup); JobDetail jobDetail = scheduler.getJobDetail(jobKey); if(jobDetail == null){ return; } scheduler.deleteJob(jobKey); } }
3、編寫(xiě)任務(wù)類(lèi)JOB
任務(wù)類(lèi)JOB就是定時(shí)任務(wù)具體要處理的系統(tǒng)業(yè)務(wù)邏輯,需要實(shí)現(xiàn)Job接口。
在任務(wù)啟動(dòng)時(shí),通過(guò)jobClass傳入JobDetail。
public class DemoJob implements Job { @Override public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { String taskCode = jobExecutionContext.getJobDetail().getKey().getName(); System.out.println("執(zhí)行定時(shí)任務(wù):" + taskCode); } }
4、配置Scheduler
在Configuration中配置Scheduler實(shí)例,并啟動(dòng)。
@Configuration public class QuartzConfig { @Bean public Scheduler scheduler(){ Scheduler scheduler = null; SchedulerFactory factory = new StdSchedulerFactory(); try { scheduler = factory.getScheduler(); } catch (SchedulerException e) { e.printStackTrace(); } if(scheduler != null){ try { //啟動(dòng)定時(shí)任務(wù) scheduler.start(); } catch (SchedulerException e) { e.printStackTrace(); } } return scheduler; } }
5、編寫(xiě)API接口
通過(guò)Controller提供API接口,這里我的TaskService調(diào)用了QartzService的對(duì)應(yīng)接口,并做了一個(gè)寫(xiě)數(shù)據(jù)庫(kù)讀寫(xiě)操作,主要記錄定時(shí)任務(wù)狀態(tài)、執(zhí)行記錄信息的等。
@RestController @RequestMapping("/api/task") public class TaskController { @Autowired private TaskService service; @RequestMapping("/start") public Object start(int id){ try { service.startJob(id); return RtnData.ok(); } catch (Exception e) { return RtnData.fail(e.getMessage()); } } @RequestMapping("/pause") public Object pause(int id){ try { service.pauseJob(id); return RtnData.ok(); } catch (Exception e) { return RtnData.fail(e.getMessage()); } } @RequestMapping("/resume") public Object resume(int id){ try { service.resumeJob(id); return RtnData.ok(); } catch (Exception e) { return RtnData.fail(e.getMessage()); } } @RequestMapping("/remove") public Object remove(int id){ try { service.deleteJob(id); return RtnData.ok(); } catch (Exception e) { return RtnData.fail(e.getMessage()); } } }
6、接口測(cè)試
先在數(shù)據(jù)庫(kù)中將DemoJob添加到任務(wù)管理表中,然后使用postman調(diào)用api進(jìn)行任務(wù)啟動(dòng)、修改、暫停、恢復(fù)、刪除等操作,觀察系統(tǒng)后臺(tái)日志打印情況查看效果。
數(shù)據(jù)庫(kù)初始化如下:
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- 如何對(duì)quartz定時(shí)任務(wù)設(shè)置結(jié)束時(shí)間
- SpringBoot中使用Quartz設(shè)置定時(shí)任務(wù)的實(shí)例詳解
- Springboot集成Quartz實(shí)現(xiàn)定時(shí)任務(wù)代碼實(shí)例
- SpringBoot集成quartz實(shí)現(xiàn)定時(shí)任務(wù)
- Springboot整合quartz實(shí)現(xiàn)多個(gè)定時(shí)任務(wù)實(shí)例
- SpringBoot+Quartz實(shí)現(xiàn)定時(shí)任務(wù)的代碼模版分享
相關(guān)文章
基于JTable的列寬與內(nèi)容自適應(yīng)的實(shí)現(xiàn)方法
本篇文章是對(duì)JTable的列寬與內(nèi)容自適應(yīng)的實(shí)現(xiàn)方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05mybatis數(shù)組和集合的長(zhǎng)度判斷及插入方式
這篇文章主要介紹了mybatis數(shù)組和集合的長(zhǎng)度判斷及插入方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01詳解Spring Boot 2.0.2+Ajax解決跨域請(qǐng)求的問(wèn)題
這篇文章主要介紹了詳解Spring Boot 2.0.2+Ajax解決跨域請(qǐng)求的問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03基于SpringBoot實(shí)現(xiàn)大文件分塊上傳功能
這篇文章主要介紹了基于SpringBoot實(shí)現(xiàn)大文件分塊上傳功能,實(shí)現(xiàn)原理其實(shí)很簡(jiǎn)單,核心就是客戶端把大文件按照一定規(guī)則進(jìn)行拆分,比如20MB為一個(gè)小塊,分解成一個(gè)一個(gè)的文件塊,然后把這些文件塊單獨(dú)上傳到服務(wù)端,需要的朋友可以參考下2024-09-09用Java程序判斷是否是閏年的簡(jiǎn)單實(shí)例
下面小編就為大家?guī)?lái)一篇用Java程序判斷是否是閏年的實(shí)現(xiàn)方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-06-06