SpringBoot設置動態定時任務
一、說明
1.在我們日常的開發中,很多時候,定時任務都不是寫死的,而是寫到數據庫中,從而實現定時任務的動態配置。
2.定時任務執行時間可根據數據庫中某個設置字段動態改變。
二、maven依賴
<dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.2.1</version> </dependency> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz-jobs</artifactId> <version>2.2.1</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> </dependency>
三、代碼
1.輸出測試類
import org.quartz.JobExecutionException;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.stereotype.Component;
@Component
@Configuration
@EnableScheduling
public class ScheduledJob {
public void execute() throws JobExecutionException {
System.out.println("hahaha");
}
}
2.Quartz配置類
import org.quartz.Trigger; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.quartz.CronTriggerFactoryBean; import org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean; import org.springframework.scheduling.quartz.SchedulerFactoryBean; @Configuration public class QuartzConfigration { /** * attention: * Details:配置定時任務 */ @Bean(name = "jobDetail") public MethodInvokingJobDetailFactoryBean detailFactoryBean(ScheduledJob task) {// ScheduleTask為需要執行的任務 MethodInvokingJobDetailFactoryBean jobDetail = new MethodInvokingJobDetailFactoryBean(); /* * 是否並發執行 * 例如每5s執行一次任務,但是當前任務還沒有執行完,就已經過了5s了, * 如果此處為true,則下一個任務會執行,如果此處為false,則下一個任務會等待上一個任務執行完后,再開始執行 */ jobDetail.setConcurrent(false); jobDetail.setName("srd-chhliu");// 設置任務的名字 jobDetail.setGroup("srd");// 設置任務的分組,這些屬性都可以存儲在數據庫中,在多任務的時候使用 /* * 為需要執行的實體類對應的對象 */ jobDetail.setTargetObject(task); /* * sayHello為需要執行的方法 * 通過這幾個配置,告訴JobDetailFactoryBean我們需要執行定時執行ScheduleTask類中的sayHello方法 */ jobDetail.setTargetMethod("execute"); return jobDetail; } /** * attention: * Details:配置定時任務的觸發器,也就是什么時候觸發執行定時任務 */ @Bean(name = "jobTrigger") public CronTriggerFactoryBean cronJobTrigger(MethodInvokingJobDetailFactoryBean jobDetail) { CronTriggerFactoryBean tigger = new CronTriggerFactoryBean(); tigger.setJobDetail(jobDetail.getObject()); tigger.setCronExpression("0 10 15 * * ?");// 初始時的cron表達式 tigger.setName("srd-chhliu");// trigger的name return tigger; } /** * attention: * Details:定義quartz調度工廠 */ @Bean(name = "schedulerTwo") public SchedulerFactoryBean schedulerFactory(Trigger cronJobTrigger) { SchedulerFactoryBean bean = new SchedulerFactoryBean(); // 用於quartz集群,QuartzScheduler 啟動時更新己存在的Job bean.setOverwriteExistingJobs(true); // 延時啟動,應用啟動1秒后 bean.setStartupDelay(1); // 注冊觸發器 bean.setTriggers(cronJobTrigger); return bean; } }
3.定時請求數據庫獲取時間類 注意sql語句的更改及判斷 查詢頻率可自行更改
package com.jdkeji.shares.quartz; import javax.annotation.Resource; import org.mybatis.spring.SqlSessionTemplate; import org.quartz.CronScheduleBuilder; import org.quartz.CronTrigger; import org.quartz.JobDetail; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import com.jdkeji.shares.config.model.BusinessConfig; @Configuration @EnableScheduling @Component public class ScheduleRefreshDatabase { @Autowired private SqlSessionTemplate st; @Resource(name = "jobDetail") private JobDetail jobDetail; @Resource(name = "jobTrigger") private CronTrigger cronTrigger; @Resource(name = "schedulerTwo") private Scheduler scheduler; @Scheduled(fixedRate = 5000) // 每隔5s查庫,並根據查詢結果決定是否重新設置定時任務 public void scheduleUpdateCronTrigger() throws SchedulerException { CronTrigger trigger = (CronTrigger) scheduler.getTrigger(cronTrigger.getKey()); String currentCron = trigger.getCronExpression();// 當前Trigger使用的 BusinessConfig bc = st.selectOne("BusinessConfig.selectByExample"); System.out.println(currentCron); String [] date = bc.getClxg().split(":"); String cron = "0 " + date[1] + " " + date[0] + " * * ?"; System.out.println(cron); if (currentCron.equals(cron)) { // 如果當前使用的cron表達式和從數據庫中查詢出來的cron表達式一致,則不刷新任務 } else { // 表達式調度構建器 CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cron); // 按新的cronExpression表達式重新構建trigger trigger = (CronTrigger) scheduler.getTrigger(cronTrigger.getKey()); trigger = trigger.getTriggerBuilder().withIdentity(cronTrigger.getKey()) .withSchedule(scheduleBuilder).build(); // 按新的trigger重新設置job執行 scheduler.rescheduleJob(cronTrigger.getKey(), trigger); currentCron = cron; } } }
四、注意
QuartzConfigration類中的detailFactoryBean(ScheduledJob)
ScheduledJob就是我們的輸出測試類

