如何使用SpringBoot 創建配合數據庫動態執行的定時任務?

序言:創建定時任務非常簡單,主要有兩種創建方式:

  • 基於註解(@Scheduled)
  • 基於接口(SchedulingConfigurer)

前者相信大家都很熟悉,但是實際使用中我們往往想從數據庫中讀取指定時間來動態執行定時任務,這時候基於接口的定時任務就大派用場了。

一、靜態定時任務(基於註解)

基於註解來創建定時任務非常簡單,只需幾行代碼便可完成。

@Scheduled 除了支持靈活的參數表達式cron之外,還支持簡單的延時操作,例如 fixedDelay ,fixedRate 填寫相應的毫秒數即可。

<code>import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

import java.time.LocalDateTime;

@Configuration //1.主要用於標記配置類,兼備Component的效果。
@EnableScheduling // 2.開啟定時任務,如果在XXXApplication類中添加了此註解這裡可以不寫
public class SimpleSchedule{
//3.添加定時任務
@Scheduled(cron = "0/2 * * * * ?")
private void schedules() {
System.err.println("執行定時任務1: " + LocalDateTime.now());
}
}/<code>
<code>Cron表達式參數分別表示:
秒(0~59) 例如0/5表示每5秒
分(0~59)
時(0~23)
月的某天(0~31) 需計算
月(0~11)
周幾( 可填1-7 或 SUN/MON/TUE/WED/THU/FRI/SAT)
second(秒),minute(分),hour(時),day of month(月),month,day of week(周幾)
0 * * * * MON-FRI 週一到週五每一分鐘啟動一次
* * * * * MON-FRI 週一到週五每一分鐘每一秒啟動一次/<code>

啟動應用,可以看到控制檯的信息如下:

如何使用SpringBoot 創建配合數據庫動態執行的定時任務?

使用Scheduled 確實很方便,但缺點是當我們調整了執行週期的時候,需要重啟應用才能生效,這多少有些不方便。為了達到實時生效的效果,可以使用接口來完成定時任務。

二、動態定時任務(基於接口)

這裡選用 Mysql數據庫 和 Mybatis 來查詢和調整定時任務的執行週期,然後觀察定時任務的執行情況。

1.添加數據庫記錄

這裡我已經在數據庫中創建了一個表,內容和結構如下:

如何使用SpringBoot 創建配合數據庫動態執行的定時任務?

2.創建定時器

數據庫準備好數據之後,我們編寫定時任務,注意這裡添加的是TriggerTask,目的是循環讀取我們在數據庫設置好的執行週期,以及執行相關定時任務的內容。具體代碼如下:

<code>import com.exam.service.ExamCronService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;

import java.time.LocalDateTime;

@Configuration //1.主要用於標記配置類,兼備Component的效果。
@EnableScheduling // 2.開啟定時任務,如果在XXXApplication類中添加了此註解這裡可以不寫
public class CompleteSchedule implements SchedulingConfigurer {
@Autowired
ExamCronService examCronService; //注入從數據庫查詢cron的service

/**
* 執行定時任務.
*/
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.addTriggerTask(
//1.添加任務內容(Runnable)
() -> CompleteSchedule.startSchedule(),
//2.設置執行週期(Trigger)
triggerContext -> {
//2.1 從數據庫獲取執行週期
String cron = examCronService.LookExamCron(1);

//2.2 合法性校驗.
if (StringUtils.isEmpty(cron)) {
// Omitted Code ..
}
//2.3 返回執行週期(Date)
return new CronTrigger(cron).nextExecutionTime(triggerContext);
}
);
}
public static void startSchedule(){
System.out.println("執行動態定時任務: " + LocalDateTime.now().toLocalTime());
}
}/<code>

3. 動態修改執行週期

這裡我數據庫默認修改成了0/1 * * * * ?

啟動應用後,查看控制檯,打印時間是我們預期的每1秒一次,等一段時間後將執行週期修改為每2秒執行一次後,控制檯打印如下圖,查看控制檯,發現執行週期已經改變,並且不需要我們重啟應用,十分方便

如何使用SpringBoot 創建配合數據庫動態執行的定時任務?


分享到:


相關文章: