適用於:
動態修改定時任務,根據數據庫的定時任務進行任務的激活和暫停,帶參定時任務,指定時間和執行次數的定時任務等。
1、概述
在開發中有的時候需要去手動禁止和啟用定時任務,修改定時任務的cron表達式然后再讓其動態生效,之前有過SSM的類似的業務的開發但是忘記寫下來了。。。只好重新溫習了一次,加上最近比較流行springBoot所以升級了一下用springBoot來完成.
2、關聯技術
SpringBoot、Quartz、mysql、thymeleaf (好像就這么多)
3、涉及核心API 類
4、具體流程
1)首先去手動創建一個調度器工廠對象-SchedulerFactoryBean;其實應該不用手動創建的但是為了顧及到業務的復雜性所以還是創建一個好用。
2)繼承job,實現方法execute。此處手寫的原因是因為我們需要對定時任務的功能進行擴展,比如文中提到的參數注入和執行日志記錄.注意jobExecutionContext.getMergedJobDataMap() 它可以獲得 JobDataMap這個是Job實例化的一些信息,可以用於定時任務的帶參。如下:
1 import com.study.www.enums.ConfigEnum; 2 import com.study.www.model.Config; 3 import com.study.www.model.Logger; 4 import com.study.www.model.mapper.LoggerRepository; 5 import com.study.www.utils.TaskUtils; 6 import org.quartz.DisallowConcurrentExecution; 7 import org.quartz.Job; 8 import org.quartz.JobExecutionContext; 9 import org.quartz.JobExecutionException; 10 import org.springframework.scheduling.annotation.Async; 11 import org.springframework.stereotype.Component; 12 13 import java.util.ArrayList; 14 import java.util.List; 15 16 17 //當上一個任務未結束時下一個任務需進行等待 18 @DisallowConcurrentExecution 19 @Component 20 public class MyJob implements Job { 21 22 //注意此處的 Dao 直接 @Autowired 注入是獲取不到的,我們可以通過Spring容器去進行手動注入 23 static LoggerRepository loggerRepository; 24 //定時任務日志落地 25 static List<Logger> loggers=new ArrayList<>(); 26 //每10條日志進行一下落地 27 private final static Integer SIZE=9; 28 29 //execute會根據cron的規則進行執行 30 @Override 31 public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { 32 Config config = (Config) jobExecutionContext.getMergedJobDataMap().get(ConfigEnum.SCHEDULEJOB.getCode()); 33 Long beginTime=null; 34 if (config.getIsLogger()){ 35 beginTime=System.currentTimeMillis(); 36 } 37 TaskUtils.invokMethod(config); 38 if (beginTime != null) { 39 //手動注入 Dao 40 if (MyJob.loggerRepository == null){ 41 MyJob.loggerRepository = SpringUtils.getBean("loggerRepository"); 42 } 43 saveSysLog(beginTime,config); 44 } 45 } 46 47 48 @Async 49 void saveSysLog(Long beginTime, Config config) { 50 Logger logger = new Logger(); 51 logger.setBeginTime(beginTime); 52 logger.setEndTime(System.currentTimeMillis()); 53 logger.setClassPath(config.getClassPath()); 54 logger.setMethName(config.getMethodName()); 55 logger.setName(config.getName()); 56 logger.setGroupName(config.getGroup()); 57 logger.setTime(System.currentTimeMillis()-beginTime); 58 logger.setParams(config.getReqParms()); 59 if (loggers.size() > SIZE) { 60 synchronized (MyJob.class) { 61 loggerRepository.save(loggers); 62 loggers.clear(); 63 } 64 }else{ 65 loggers.add(logger); 66 } 67 } 68 69 }
3)獲取到調度器-Scheduler和JobBuilder以及TriggerBuilder
4)實現動態新增、刪除定時任務的方法.此處的 trigger 觸發機制有兩種 一種是Cron 一種是 選擇時間和時間間隔的。因為有一種業務情況為客戶去手動選擇時間進行定時任務發送。
5)創建對定時任務的方法進行反射執行的方法。如下:
提示: 頁面用戶修改Cron 表達式如果需要對Cron表達式進行校驗可以使用如下方法。
提示: 如果定時任務的帶參為不固定的比如是另外的一個請求等,可以修改 步驟 5中的規則。例如可以在Config 中加個用來進行參數類型判斷的字段,然后參數為 一個http請求這樣可以做到在定時任務中進行一個請求后再任務的執行。
若時間充裕推薦這封博客其對Quartz將的更加詳細,配合示例看可以有着事半功倍的效果。http://ifeve.com/quartz-tutorial-using-quartz/
代碼例子:
碼雲:https://gitee.com/zhuyanpengWorld/springboots/blob/master/quartz.rar