SpringBoot集成quartz實現(xiàn)定時任務(wù)
1. 前言
現(xiàn)如今,隨著市場競爭加劇,各個企業(yè)都在不斷尋求提高效率、降低成本的方法,此時使用自動化工具已成為必不可少的選擇。而在眾多的自動化工具中,定時任務(wù)已經(jīng)成為一項必備工具,而Quartz就是一個非常好用的定時任務(wù)框架,它的輕量級、高可靠性、易于使用等特點,使得它成為一個非常受歡迎的定時任務(wù)框架。而在本篇文章中,我們將會介紹如何使用SpringBoot整合Quartz,并將定時任務(wù)寫入庫中(持久化存儲),還可以任意對定時任務(wù)進行如刪除、暫停、恢復(fù)等操作。
那么,具體如何實現(xiàn)呢?這將又會是干貨滿滿的一期,全程無尿點不廢話只抓重點教,具有非常好的學習效果,拿好小板凳準備就坐!希望學習的過程中大家認真聽好好學,學習的途中有任何不清楚或疑問的地方皆可評論區(qū)留言或私信,bug菌將第一時間給予解惑,那么廢話不多說,直接開整!Fighting!!
2. 環(huán)境說明
本地的開發(fā)環(huán)境:
- 開發(fā)工具:IDEA 2021.3
- JDK版本: JDK 1.8
- Spring Boot版本:2.3.1 RELEASE
- Maven版本:3.8.2
3. 整合Quartz
下面實現(xiàn)一個簡單的任務(wù)調(diào)度系統(tǒng),并且將定時任務(wù)的信息持久化入庫,希望可以幫助到大家,Quartz的非持久化使用本文就不贅述了。
3.1 搭建Spring Boot應(yīng)用
首先,我們需要搭建一個Spring Boot項目,如果還不會點這里,此處就不詳細贅述啦。
3.2 添加依賴
在Spring Boot項目中,我們可以使用Quartz Starter來集成Quartz框架。只需要在pom.xml文件中引入以下依賴即可:
<!--集成quartz--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-quartz</artifactId> <version>2.3.12.RELEASE</version> </dependency>
基礎(chǔ)相關(guān)依賴:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--mysql依賴--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.10</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <!--util工具類--> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.8.1</version> </dependency>
3.3 配置Quartz相關(guān)配置文件
然后,我們需要在application.properties文件中配置數(shù)據(jù)源及Quartz相關(guān)配置:
spring: datasource: name: db_quartz driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/db_quartz?useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=UTF8&rewriteBatchedStatements=true username: root password: 123456 #quartz配置 quartz: #數(shù)據(jù)存儲方式 默認是 MEMORY(內(nèi)存方式) job-store-type: jdbc properties: org: quartz: scheduler: #調(diào)度標識名 instanceName: clusteredScheduler #ID設(shè)置為自動獲取 每一個必須不同 instanceId: AUTO jobStore: #數(shù)據(jù)保存方式為持久化 class: org.quartz.impl.jdbcjobstore.JobStoreTX #數(shù)據(jù)庫平臺 driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate #表的前綴 tablePrefix: QRTZ_ #加入集群 isClustered: false #調(diào)度實例失效的檢查時間間隔 clusterCheckinInterval: 10000 #設(shè)置為TRUE不會出現(xiàn)序列化非字符串類到 BLOB 時產(chǎn)生的類版本問題 useProperties: false threadPool: #ThreadPool 實現(xiàn)的類名 class: org.quartz.simpl.SimpleThreadPool #線程數(shù)量 threadCount: 5 #線程優(yōu)先級 threadPriority: 5 #自創(chuàng)建父線程 threadsInheritContextClassLoaderOfInitializingThread: true
其中,job-store-type表示使用的持久化方式,這里選擇了使用jdbc完成任務(wù)持久化入庫。jdbc的相關(guān)配置包括initialize-schema,comment-prefix,use-properties,table-prefix,scheduler-name等,這里不再贅述,具體的我已在代碼中進行了詳細注釋。
3.4 添加Quartz表
接下來,我們需要創(chuàng)建一個數(shù)據(jù)庫表,用于存儲任務(wù)信息。在使用quartz做持久化的時候需要用到quartz的11張表,可以去quartz官網(wǎng)下載對應(yīng)版本的quartz,你進入quartz的官網(wǎng)Quartz Enterprise Job Scheduler,點擊Downloads,若想要現(xiàn)成的,可以去我的github倉庫取https://github.com/luoyong0603/SpringBoot-demos。下載并解壓,打開docs/dbTables里面有對應(yīng)數(shù)據(jù)庫的建表語句。演示截圖如下:
我這選擇的是mysql數(shù)據(jù)庫且使用innodb引擎,對應(yīng)的腳本文件是tables_mysql_innodb.sql,這里大家可以自行去了解下innodb與myisam的區(qū)別。這些表不需要我們做任何操作,是Quartz框架使用的。把創(chuàng)表sql執(zhí)行后,就如下這樣了,總共11張表,示例如下:
接下來對每張表的作用做以下總結(jié),Quartz將Job保存在數(shù)據(jù)庫中所需表的說明:
- QRTZ_CALENDARS:以 Blob 類型存儲 Quartz 的 Calendar 信息
- QRTZ_CRON_TRIGGERS:存儲 Cron Trigger,包括 Cron表達式和時區(qū)信息
- QRTZ_FIRED_TRIGGERS:存儲與已觸發(fā)的 Trigger 相關(guān)的狀態(tài)信息,以及相聯(lián) Job的執(zhí)行信息
- QRTZ_PAUSED_TRIGGER_GRPS:存儲已暫停的 Trigger 組的信息
- QRTZ_SCHEDULER_STATE 存儲少量的有關(guān) Scheduler 的狀態(tài)信息,和別的 Scheduler實例(假如是用于一個集群中)
- QRTZ_LOCKS 存儲程序的悲觀鎖的信息(假如使用了悲觀鎖)
- QRTZ_JOB_DETAILS 存儲每一個已配置的 Job 的詳細信息
- QRTZ_SIMPLE_TRIGGERS 存儲簡單的Trigger,包括重復(fù)次數(shù),間隔,以及已觸的次數(shù)
- QRTZ_BLOG_TRIGGERS Trigger 作為 Blob 類型存儲(用于 Quartz 用戶用 JDBC創(chuàng)建他們自己定制的 Trigger 類型,JobStore 并不知道如何存儲實例的時候)
- QRTZ_TRIGGER_LISTENERS 存儲已配置的 TriggerListener 的信息
- QRTZ_TRIGGERS 存儲已配置的 Trigger 的信息
并對其中的4張常用表進行表結(jié)構(gòu)解讀,輔助大家理解:
表qrtz_job_details: 保存job詳細信息,該表需要用戶根據(jù)實際情況初始化
job_name:集群中job的名字,該名字用戶自己可以隨意定制,無強行要求
job_group:集群中job的所屬組的名字,該名字用戶自己隨意定制,無強行要求
job_class_name:集群中個note job實現(xiàn)類的完全包名,quartz就是根據(jù)這個路徑到classpath找到該job類
is_durable:是否持久化,把該屬性設(shè)置為1,quartz會把job持久化到數(shù)據(jù)庫中
job_data:一個blob字段,存放持久化job對象
表qrtz_triggers: 保存trigger信息
trigger_name: trigger的名字,該名字用戶自己可以隨意定制,無強行要求
trigger_group:trigger所屬組的名字,該名字用戶自己隨意定制,無強行要求
job_name: qrtz_job_details表job_name的外鍵
job_group: qrtz_job_details表job_group的外鍵
trigger_state:當前trigger狀態(tài),設(shè)置為ACQUIRED,如果設(shè)置為WAITING,則job不會觸發(fā)
trigger_cron:觸發(fā)器類型,使用cron表達式
表qrtz_cron_triggers:存儲cron表達式表
trigger_name: qrtz_triggers表trigger_name的外鍵
trigger_group: qrtz_triggers表trigger_group的外鍵
cron_expression:cron表達式
表qrtz_scheduler_state:存儲集群中note實例信息,quartz會定時讀取該表的信息判斷集群中每個實例的當前狀態(tài)
instance_name:之前配置文件中org.quartz.scheduler.instanceId配置的名字,就會寫入該字段,如果設(shè)置為AUTO,quartz會根據(jù)物理機名和當前時間產(chǎn)生一個名字
last_checkin_time:上次檢查時間
checkin_interval:檢查間隔時間
3.5 創(chuàng)建Controller
這里我們創(chuàng)建個QuartzController控制器,用來添加多個操作Quartz的請求方式,例如:刪除定時任務(wù)、暫停定時任務(wù)、查看所有定時任務(wù)等。Swagger示例截圖如下:
示例代碼如下:僅供參考,有想法的也可以拓展或者修改。
@RestController @RequestMapping("/quartz") public class QuartzController { @Autowired private QuartzService quartzService; /** * 新增任務(wù) */ @PostMapping("/insert") @ApiOperation(value = "新增任務(wù)", notes = "新增任務(wù)") public Boolean insertTask(@RequestBody QuartzModel quartzModel) { return quartzService.addJob(quartzModel); } /** * 暫停任務(wù) */ @PostMapping("/pause") @ApiOperation(value = "暫停任務(wù)", notes = "暫停任務(wù)") public Boolean pauseTask(@RequestBody OperationModel operationModel) { return quartzService.pauseJob(operationModel); } /** * 恢復(fù)任務(wù) */ @PostMapping("/resume") @ApiOperation(value = "恢復(fù)任務(wù)", notes = "恢復(fù)任務(wù)") public Boolean resumeTask(@RequestBody OperationModel operationModel) { return quartzService.resumeJob(operationModel); } /** * 刪除任務(wù) */ @PostMapping("/delete") @ApiOperation(value = "刪除任務(wù)", notes = "刪除任務(wù)") public Boolean deleteTask(@RequestBody OperationModel operationModel) { return quartzService.deleteJob(operationModel); } /** * 查看所有定時任務(wù) */ @GetMapping("/query-all-job") @ApiOperation(value = "查看所有定時任務(wù)", notes = "查看所有定時任務(wù)") public List<Map<String, Object>> queryAllJob() { return quartzService.queryAllJob(); } /** * 查看正在運行的任務(wù) */ @GetMapping("/query-all-running-job") @ApiOperation(value = "查看正在執(zhí)行的任務(wù)", notes = "查看正在執(zhí)行的任務(wù)") public List<Map<String, Object>> queryAllRunningJob() { return quartzService.queryAllRunningJob(); } }
3.6 編寫QuartzService接口
這里將被定義所對應(yīng)的接口,用于操作Quartz任務(wù)。
@Service public interface QuartzService { /** * 新增定時任務(wù) */ Boolean addJob(QuartzModel quartzModel); /** * 暫停定時任務(wù) */ Boolean pauseJob(OperationModel operationModel); /** * 繼續(xù)定時任務(wù) */ Boolean resumeJob(OperationModel operationModel); /** * 刪除定時任務(wù) */ Boolean deleteJob(OperationModel operationModel); /** * 查詢所有計劃中的任務(wù)列表 */ List<Map<String, Object>> queryAllJob(); /** * 查看正在運行的任務(wù) */ List<Map<String, Object>> queryAllRunningJob(); }
3.7 實現(xiàn)定時任務(wù)執(zhí)行器
這里我們手動寫任務(wù)執(zhí)行器,目的不僅是為了執(zhí)行定時任務(wù)也想通過區(qū)分定時任務(wù)執(zhí)行不同的邏輯,示例代碼如下,僅供參考:
/** * 定時任務(wù)執(zhí)行器 */ @Slf4j public class TaskDistributor extends QuartzJobBean { /** * 根據(jù)不同的jobDetail攜帶的type參數(shù)區(qū)分,執(zhí)行不同業(yè)務(wù) */ @Override protected void executeInternal(JobExecutionContext context) { synchronized (this) { log.info("開始執(zhí)行定時任務(wù)..............."); try { //獲取job中攜帶的內(nèi)容并轉(zhuǎn)成jobDetailModel對象 JobDetailModel jobDetailModel = (JobDetailModel) context.getJobDetail().getJobDataMap().get("jobDetailModel"); Integer type = jobDetailModel.getType(); String content = jobDetailModel.getContent(); //根據(jù)type執(zhí)行不同的業(yè)務(wù)邏輯 switch (type) { case 1: System.out.println("task1即將被執(zhí)行,content:" + content); //模擬處理邏輯 Thread.sleep(5000); log.info("---------task1定時任務(wù)執(zhí)行結(jié)束----------"); break; case 2: System.out.println("task2即將被執(zhí)行,content:" + content); //模擬處理邏輯 Thread.sleep(5000); log.info("----------task2定時任務(wù)結(jié)束---------"); break; default: log.info("---------定時任務(wù)執(zhí)行開始----------"); log.info("---------定時任務(wù)執(zhí)行結(jié)束----------"); break; } } catch (Throwable t) { log.error(t.getMessage(), t); } log.info("定時任務(wù)執(zhí)行結(jié)束..............."); } } }
3.8 創(chuàng)建QuartzServiceImpl實現(xiàn)類
這里我們將QuartzService接口中的所有接口進行實現(xiàn),示例代碼如下:
@Slf4j @Service public class QuartzServiceImpl implements QuartzService { @Autowired private Scheduler scheduler; /** * 新增定時任務(wù) */ @Override public Boolean addJob(QuartzModel quartzModel) { try { String cron = quartzModel.getCron(); //校驗cron是否有效 boolean valid = CronUtils.isValid(cron); if (!valid) { return false; } JobDetail jobDetail = JobBuilder.newJob(TaskDistributor.class) .withIdentity(quartzModel.getJobName(), quartzModel.getJobGroup()) .build(); // 攜帶job內(nèi)容 此處可以攜帶業(yè)務(wù)所需要的執(zhí)行參數(shù) JobDetailModel jobDetailModel = quartzModel.getJobData(); if (!Objects.isNull(jobDetailModel)) { jobDetail.getJobDataMap().put("jobDetailModel", jobDetailModel); } CronTrigger trigger = TriggerBuilder.newTrigger() .withIdentity(quartzModel.getTriggerName(), quartzModel.getTriggerGroup()) .startNow() .withSchedule(CronScheduleBuilder.cronSchedule(cron)) .build(); //把作業(yè)和觸發(fā)器注冊到任務(wù)調(diào)度中 scheduler.scheduleJob(jobDetail, trigger); //啟用調(diào)度 scheduler.start(); log.info("---------定時任務(wù)成功添加進quartz隊列中!----------"); } catch (Exception e) { e.printStackTrace(); } return true; } /** * 暫停定時任務(wù) */ @Override public Boolean pauseJob(OperationModel operationModel) { try { scheduler.pauseJob(JobKey.jobKey(operationModel.getJobName(), operationModel.getJobGroup())); System.out.println("暫停定時任務(wù)成功"); } catch (Exception e) { e.printStackTrace(); } return true; } /** * 繼續(xù)定時任務(wù) */ @Override public Boolean resumeJob(OperationModel operationModel) { try { scheduler.resumeJob(JobKey.jobKey(operationModel.getJobName(), operationModel.getJobGroup())); System.out.println("恢復(fù)定時任務(wù)成功"); } catch (SchedulerException e) { e.printStackTrace(); } return true; } /** * 刪除定時任務(wù) */ @Override public Boolean deleteJob(OperationModel operationModel) { try { // TriggerKey 定義了trigger的名稱和組別 ,通過任務(wù)名和任務(wù)組名獲取TriggerKey TriggerKey triggerKey = TriggerKey.triggerKey(operationModel.getJobName(), operationModel.getJobGroup()); // 停止觸發(fā)器 scheduler.resumeTrigger(triggerKey); // 移除觸發(fā)器 scheduler.unscheduleJob(triggerKey); scheduler.deleteJob(JobKey.jobKey(operationModel.getJobName(), operationModel.getJobGroup())); System.out.println("刪除定時任務(wù)成功"); } catch (SchedulerException e) { e.printStackTrace(); } return true; } /** * 查看所有定時任務(wù) * * @return */ @Override public List<Map<String, Object>> queryAllJob() { List<Map<String, Object>> jobList = null; try { GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup(); Set<JobKey> jobKeys = scheduler.getJobKeys(matcher); jobList = new ArrayList<Map<String, Object>>(); for (JobKey jobKey : jobKeys) { List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey); for (Trigger trigger : triggers) { jobList.add(this.buildMap(jobKey, trigger)); } } } catch (SchedulerException e) { e.printStackTrace(); } return jobList; } /** * 返回指定的map集合 */ private Map<String, Object> buildMap(JobKey jobKey, Trigger trigger) throws SchedulerException { Map<String, Object> map = new HashMap<>(); map.put("jobName", jobKey.getName()); map.put("jobGroupName", jobKey.getGroup()); map.put("description", "觸發(fā)器:" + trigger.getKey()); Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey()); map.put("jobStatus", triggerState.name()); if (trigger instanceof CronTrigger) { CronTrigger cronTrigger = (CronTrigger) trigger; String cronExpression = cronTrigger.getCronExpression(); map.put("jobTime", cronExpression); } return map; } /** * 獲取所有正在運行的job * * @return */ @Override public List<Map<String, Object>> queryAllRunningJob() { List<Map<String, Object>> jobList = null; try { List<JobExecutionContext> executingJobs = scheduler.getCurrentlyExecutingJobs(); jobList = new ArrayList<Map<String, Object>>(executingJobs.size()); for (JobExecutionContext executingJob : executingJobs) { JobDetail jobDetail = executingJob.getJobDetail(); JobKey jobKey = jobDetail.getKey(); Trigger trigger = executingJob.getTrigger(); jobList.add(this.buildMap(jobKey, trigger)); } } catch (SchedulerException e) { e.printStackTrace(); } return jobList; } }
其中addJob方法將一個定時任務(wù)添加到調(diào)度器中,其中jobName和jobGroupName表示任務(wù)的名稱和分組名稱,triggerName和triggerGroupName表示觸發(fā)器的名稱和分組名稱,jobClass表示任務(wù)的類,cron表示定時任務(wù)執(zhí)行的時間表達式。scheduler.scheduleJob(jobDetail, trigger);目的是把作業(yè)和觸發(fā)器注冊到任務(wù)調(diào)度中。
3.9 接口測試
重啟項目后,我們來進行接口的請求測試,驗證我們所添加的定時任務(wù)是否會執(zhí)行且被新增入庫持久化保存?就讓我們拭目以待吧!
如下我直接通過Swagger在線接口文檔作為測試,測試如下:
3.9.1 添加定時任務(wù)task1
具體請求參數(shù)附上:
{
"cron": "*/10 * * * * ? ",
"jobData": {
"content": "bug菌寫定時任務(wù)(執(zhí)行邏輯1)",
"type": 1
},
"jobGroup": "job_group_task1",
"jobName": "job_name_task1",
"triggerGroup": "trigger_group_task1",
"triggerName": "trigger_task1"
}
3.9.2 添加定時任務(wù)task2
具體請求參數(shù)附上:
{
"cron": "*/20 * * * * ? ",
"jobData": {
"content": "bug菌寫定時任務(wù)(執(zhí)行邏輯2)",
"type": 2
},
"jobGroup": "job_group_task2",
"jobName": "job_name_task2",
"triggerGroup": "trigger_group_task2",
"triggerName": "trigger_task2"
}
3.9.3 測試獲取所有的定時任務(wù)
添加兩個定時任務(wù)后,可以查看一下所有定時任務(wù)列表:
定時任務(wù)成功添加進quartz隊列中!被插入的定時任務(wù)task1被成功執(zhí)行且執(zhí)行的type = 1的業(yè)務(wù)邏輯,打印了" task1即將被執(zhí)行,content:bug菌寫定時任務(wù)(執(zhí)行邏輯1) "
示例截圖如下:
定時任務(wù)成功添加進quartz隊列中!被插入的定時任務(wù)task2被成功執(zhí)行且執(zhí)行的type = 2的業(yè)務(wù)邏輯,打印了" task2即將被執(zhí)行,content:bug菌寫定時任務(wù)(執(zhí)行邏輯2) "
示例截圖如下:
3.9.4 驗證數(shù)據(jù)庫是否被保存定時任務(wù)
我們再來檢查一遍,查驗下我們添加的兩條定時任務(wù)是否被自動插入庫中(持久化)。
在上面的兩個添加任務(wù)的過程中,我們不僅將定時任務(wù)配置在了代碼中,并把將它們持久化到數(shù)據(jù)庫中。因為我們就是希望在應(yīng)用程序重啟后仍然能夠保持任務(wù)狀態(tài),而Quartz就在內(nèi)部直接將它們持久化到數(shù)據(jù)庫中。
在Quartz中,定時任務(wù)數(shù)據(jù)是存儲在三張表中的:
- QRTZ_JOB_DETAILS:保存JobDetail信息
- QRTZ_TRIGGERS:保存Trigger信息
- QRTZ_CRON_TRIGGERS:保存CronTrigger信息
當我們插入定時任務(wù)時,Quartz會自動將任務(wù)數(shù)據(jù)存儲到這三張表中。我們插入了兩個task定時任務(wù)后,我們完全不需要自主手插入定時任務(wù),它會自動幫我們保存入庫,同學們請看:
qrtz_cron_triggers表:
qrtz_job_details表:
qrtz_triggers表:
這樣一來,哪怕是項目重啟,定時任務(wù)也照常執(zhí)行,不會因為沒有被觸發(fā)而停止執(zhí)行定時任務(wù)??梢钥吹皆俅沃貑⒑蟮捻椖縯ask1與task2都自動執(zhí)行,保持了任務(wù)狀態(tài)。
3.9.5 暫停定時任務(wù)
具體請求參數(shù)附上:
{
"jobGroup": "job_group_task1_jg",
"jobName": "job_name_task1_jn"
}
切記,我是為了區(qū)分便在參數(shù)pojo值上手動拼接后綴,比如:
可以看到數(shù)據(jù)入庫的都被添加了對應(yīng)的后綴名。
所以同學們在測試接口的時候,別忘了把后綴加上,或者你們也可以把我的這段去掉。
控制臺查驗是否被暫停了,大家請看:
經(jīng)多次測試,task1任務(wù)確實暫停執(zhí)行了。
3.9.6 繼續(xù)定時任務(wù)
我們能暫停任務(wù),就能把被暫停的任務(wù)恢復(fù)執(zhí)行,這么我們來測試一下。
具體請求參數(shù)附上:
{
"jobGroup": "job_group_task1_jg",
"jobName": "job_name_task1_jn"
}
控制臺查驗被暫停的task1是否被恢復(fù)執(zhí)行了,大家請看:
經(jīng)5min觀察,task1任務(wù)確實又重新執(zhí)行了。你也可以調(diào)用【正在執(zhí)行中的任務(wù)】接口作為輔助驗證,不過就是要多次調(diào)用,畢竟在非執(zhí)行間隔有點久,畢竟task1任務(wù)間隔10s執(zhí)行一次,task2任務(wù)間隔20s執(zhí)行一次。
3.9.7 查詢正在執(zhí)行的定時任務(wù)
同上述測試步驟,我們直接通過Swagger接口文檔作為測試請求:
再次測試請求:
3.9.8 查看所有定時任務(wù)
這里我們可以查詢出所有的定時任務(wù),不區(qū)分是否正在被執(zhí)行狀態(tài)。所以始終會返回job表中的總條數(shù)。
同上述測試步驟,我們直接通過Swagger接口文檔作為測試請求:
3.9.9 刪除定時任務(wù)
終于寫到最后一個刪除模擬了,同上述測試步驟,我們直接通過Swagger接口文檔作為測試請求:
具體請求參數(shù)附上:
{
"jobGroup": "job_group_task1_jg",
"jobName": "job_name_task1_jn"
}
我們從三個地方來驗證,分別是接口查詢所有任務(wù)數(shù),控制臺執(zhí)行打印,及數(shù)據(jù)庫job任務(wù)條數(shù)。
重新請求【接口查詢所有定時任務(wù)數(shù)】截圖如下:
數(shù)據(jù)庫表qrtz_job_details中task1成功被移除了,證明task1這條定時任務(wù)確實被刪除了。
好啦,以上針對Quartz的一系列操作及測試演示了,所任何不清楚的地方都可以通過評論區(qū)或私信我,我將第一時間給予你解惑。
4. 總結(jié)
本文介紹了SpringBoot集成quartz可以使定時任務(wù)的管理變得更加方便和可靠。通過將定時任務(wù)的信息保存到數(shù)據(jù)庫中,我們可以輕松地對任務(wù)進行增刪改查等操作。下面是一些主要的總結(jié):
配置數(shù)據(jù)源和quartz的相關(guān)屬性:需要在配置文件中指定數(shù)據(jù)源的連接信息和quartz的屬性,包括JobStore類型、表前綴、是否自動啟動等。
創(chuàng)建Job和Trigger:通過繼承Quartz提供的Job接口,實現(xiàn)execute方法,即可定義一個Job。同時,通過指定Trigger的cron表達式或簡單的時間間隔,可以定義一個Trigger,并將其與Job綁定起來。
通過schedulerFactoryBean創(chuàng)建Scheduler:在配置類中,通過注入schedulerFactoryBean,我們可以獲取到一個Scheduler實例,然后可以通過Scheduler的API實現(xiàn)任務(wù)的管理,包括啟動、暫停、恢復(fù)、刪除等操作。
配置JobDetail、Trigger、CronTrigger的持久化:通過將JobDetail、Trigger、CronTrigger的信息保存到數(shù)據(jù)庫中,我們可以實現(xiàn)對定時任務(wù)的持久化,即使應(yīng)用程序重新啟動或服務(wù)器崩潰,我們也可以恢復(fù)定時任務(wù)。在配置文件中,需要指定SchedulerFactoryBean的jobStore類型為JobStoreTX,同時配置DataSourceTransactionManager和QuartzTransactionManager。
使用QuartzJobBean和JobDataMap:在Job中,可以通過繼承Quartz提供的QuartzJobBean,獲取JobExecutionContext,并從中獲取JobDataMap,通過JobDataMap可以傳遞參數(shù),實現(xiàn)Job的可配置化。
總之,通過使用SpringBoot集成quartz,我們可以方便地管理定時任務(wù),實現(xiàn)任務(wù)的持久化,同時對任務(wù)的管理變得更加靈活和可靠。
以上就是SpringBoot集成quartz實現(xiàn)定時任務(wù)的詳細內(nèi)容,更多關(guān)于SpringBoot定時任務(wù)的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java基礎(chǔ)之隱式轉(zhuǎn)換vs強制轉(zhuǎn)換
這篇文章主要介紹了Java基礎(chǔ)之隱式轉(zhuǎn)換vs強制轉(zhuǎn)換的相關(guān)資料,需要的朋友可以參考下2015-12-12Java中LambdaQueryWrapper的常用方法詳解
這篇文章主要給大家介紹了關(guān)于Java中LambdaQueryWrapper常用方法的相關(guān)資料,lambdaquerywrapper是一個Java庫,用于構(gòu)建類型安全的Lambda表達式查詢,需要的朋友可以參考下2023-11-11