SpringBoot中实现quartz定时任务
Quartz整合到SpringBoot(持久化到數據庫)
背景
最近完成了一個小的后臺管理系統的權限部分,想著要擴充點東西,并且剛好就完成了一個自動疫情填報系統,但是使用的定時任務是靜態的,非常不利于擴展和調控,就想到了用Quartz實現。
Quartz簡介
Quartz是一個優秀的任務調度框架,有靜態任務調度和動態任務調度兩種類型。靜態任務調度是編寫好代碼,然后在啟動的時候,將任務保存在內內存中,也就是下面的RAMJobStore,實現相對簡單;動態任務調度主要是持久化到數據庫,即下面的JDBC作業存儲,實現方式相對復雜一點,但是可操作性更強。
- RAMJobStore :RAM也就是內存,默認情況下Quartz會將任務調度存在內存中,這種方式性能是最好的,因為內存的速度是最快的。不好的地方就是數據缺乏持久性,但程序崩潰或者重新發布的時候,所有運行信息都會丟失
- JDBC作業存儲:存到數據庫之后,可以做單點也可以做集群,當任務多了之后,可以統一進行管理。關閉或者重啟服務器,運行的信息都不會丟失。缺點就是運行速度快慢取決于連接數據庫的快慢。
Quartz相關概念
-
Scheduler:調度器,進行任務調度;quartz的大腦
-
Job:業務job,亦可稱業務組件;定時任務的具體執行業務需要實現此接口,調度器會調用此接口的execute方法完成我們的定時業務
-
JobDetail:用來定義業務Job的實例,我們可以稱之為quartz job,很多時候我們談到的job指的是JobDetail
-
Trigger:觸發器,用來定義一個指定的Job何時被執行
-
JobBuilder:Job構建器,用來定義或創建JobDetail的實例;JobDetail限定了只能是Job的實例
-
TriggerBuilder:觸發器構建器,用來定義或創建觸發器的實例
RAMJobStore的實現
整體流程
-
首先需要創建任務(Job),比如取消訂單、定時發送短信郵件之類的,這是我們的任務主體,也是寫業務邏輯的地方。
-
創建任務調度器(Scheduler),這是用來調度任務的,主要用于啟動、停止、暫停、恢復等操作,也就是那幾個api的用法。
-
創建任務明細(JobDetail),最開始我們編寫好任務(Job)后,只是寫好業務代碼,并沒有觸發,這里需要用JobDetail來和之前創建的任務(Job)關聯起來,便于執行。
-
創建觸發器(Trigger),觸發器是來定義任務的規則的,比如幾點執行,幾點結束,幾分鐘執行一次等等。這里觸發器主要有兩大類(SimpleTrigger和CronTrigger)。
-
根據Scheduler來啟動JobDetail與Trigger
導入依賴
<!--quartz定時調度依賴-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
創建Job
要求: 需實現Job接口,并且這個接口就一個execute()方法需要重寫,方法內容就是具體的業務邏輯。如果是動態任務呢,比如取消訂單,每次執行都是不同的訂單號。這個時候就需要在創建任務(JobDetail)或者創建觸發器(Trigger)的那里傳入參數,然后在這里通過JobExecutionContext來獲取參數進行處理,
/*** @author Mr.zhou* @version 1.0* @date 2020/11/17 17:52*/
public class TestJob implements Job {@Overridepublic void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {System.err.println("Hello quartz, " + jobExecutionContext.getJobDetail().getJobDataMap().getString("message"));System.err.println("Hello quartz, " + jobExecutionContext.getMergedJobDataMap().getString("work"));System.err.println();}
}
創建任務調度器
這里我們用的是SpringBoot,SpringBoot會自動幫我們裝配任務調度器,在使用的時候,直接注入即可。
@Resource
private Scheduler scheduler;
如果沒用使用SpringBoot,那么就需要手動創建了。通常優秀的框架,創建某些核心類都會使用工廠模式或者構建者模式,值得學習。
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getScheduler();
創建任務明細:JobDetail
// 創建任務詳情
JobDetail jobDetail = JobBuilder.newJob(TestJob.class)// 添加參數.usingJobData("message", "米西米西滑不拉幾")// 添加認證信息,共有三種認證方式.withIdentity(orderNum).build();
創建觸發器:Trigger
SimpleSchedule策略
// 創建觸發器
Trigger trigger = TriggerBuilder.newTrigger()// 添加參數.usingJobData("work", "我在寫代碼,你呢?")// 認證信息.withIdentity(orderNum)// 開始時間.startAt(start)// 執行策率,有SimpleSchedule和CronSchedule兩種.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(5).repeatForever()).build();
CronSchedule策略
// 創建觸發器
Trigger trigger = TriggerBuilder.newTrigger()// 添加參數.usingJobData("work", "我在寫代碼,你呢?")// 認證信息.withIdentity(orderNum)// 開始時間.startNow()// 執行策率,有SimpleSchedule和CronSchedule兩種.withSchedule(CronScheduleBuilder.cronSchedule("*/5 * * * * *")).build();
注意:.startNow()和.startAt()這里有個坑,這兩個方法是對同一個成員變量進行修改的 也就是說startAt和startNow同時調用的時候任務開始的時間是按后面調用的方法為主的,誰寫在后面用誰。看看這里的源碼:
啟動任務
上面都已經將工作完成了,接下來就是啟動任務了
// 啟動定時任務
scheduler.scheduleJob(jobDetail, trigger);
if (!scheduler.isShutdown()) {scheduler.start();
}
實現任務的常規操作
上面已經介紹了怎么去定義一個任務,并成功啟動,下面就簡單介紹任務的啟動、暫停、恢復、以及刪除等操作。
@RestController
@RequestMapping("/quartz")
public class QuartzController {@Resourceprivate Scheduler scheduler;/*** 啟動一個定時任務* @param orderNum 編號* @return 結果* @throws SchedulerException 異常*/@PostMapping("/start")public R quartz(@RequestParam("orderNum") String orderNum) throws SchedulerException {// 當前時間10秒之后Date start = new Date(System.currentTimeMillis() + 10 * 1000);// 創建任務詳情JobDetail jobDetail = JobBuilder.newJob(TestJob.class)// 添加參數.usingJobData("message", "米西米西滑不拉幾")// 添加認證信息,共有三種認證方式.withIdentity(orderNum).build();// 創建觸發器Trigger trigger = TriggerBuilder.newTrigger()// 添加參數.usingJobData("work", "我在寫代碼,你呢?")// 認證信息.withIdentity(orderNum)// 開始時間.startAt(start)// 執行策率,有SimpleSchedule和CronSchedule兩種.withSchedule(CronScheduleBuilder.cronSchedule("*/5 * * * * ?")).build();// 啟動定時任務scheduler.scheduleJob(jobDetail, trigger);if (!scheduler.isShutdown()) {scheduler.start();}System.err.println("定時任務啟動成功");return R.ok();}/*** 任務關閉* @param oderNum 標識* @return 結果* @throws SchedulerException 異常*/@PostMapping("/shutdown")public R shutdown(@RequestParam("orderNum") String oderNum) throws SchedulerException {scheduler.pauseTrigger(TriggerKey.triggerKey(oderNum));return R.ok();}/*** 任務恢復* @param oderNum 標識* @return 結果* @throws SchedulerException 異常*/@PostMapping("/resume")public R resume(@RequestParam("orderNum") String oderNum) throws SchedulerException {scheduler.resumeTrigger(TriggerKey.triggerKey(oderNum));return R.ok();}/*** 任務刪除* @param oderNum 標識* @return 結果* @throws SchedulerException 異常*/@PostMapping("/del")public R del(@RequestParam("/oderNum") String oderNum) throws SchedulerException {scheduler.pauseTrigger(TriggerKey.triggerKey(oderNum));scheduler.unscheduleJob(TriggerKey.triggerKey(oderNum));scheduler.deleteJob(JobKey.jobKey(oderNum));return R.ok();}}
結果示例
由于我項目已經集成了Swagger文檔,所以我就直接在這上面進行接口測試了
-
開啟任務
-
任務啟動之后的輸出效果
到這里,應該就清楚了Quartz和SpringBoot整合,大致流程,了解了RAMJobStore如何實現,那么數據庫持久化的實現也應該有了基本思路了。
JDBC作業存儲實現
大致流程
- 創建SpringBoot工程,并且加入Web和Quartz依賴
- 下載Quartz官方提供的數據庫腳本,注意版本,并將其導入到自己項目的數據庫中
- 添加Quartz配置
總結
以上是生活随笔為你收集整理的SpringBoot中实现quartz定时任务的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vim中tab键8空格换4空格
- 下一篇: C++核心编程(一)