提供排程功能,實現定期任務執行,使用 @Scheduled 定義排程,能夠快速方便地建立項目, EP 25 增加 了範例,並透過 JUnit 5 單元測試來驗證產出結果。
Table of Contents
Toggle前言
開發上非常地簡單,只要使用註解定義就能實現,方便日後管理與維護,同時也可以使用多種的 @Scheduled,搭配不同的參數設定,產生不同的排程效果。
Spring Boot Scheduling Tasks
檔案目錄
./
+- build.gradle
+- src
+- main
+- resources
| +- application.properties
+- java
+- org
+- ruoxue
+- spring_boot_168
+- config
| +- ScheduleConfig.java
configureTasks
註冊連線池,設定前缀名稱,及初始化排程管理器。
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
String prefix = "SCHEDULE-T-";
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setThreadNamePrefix(prefix);
scheduler.setPoolSize(ThreadPoolConfig.MAX_POOLSIZE);
scheduler.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
taskRegistrar.setScheduler(scheduler);
scheduler.initialize();
log.info("prefix: " + prefix);
}
ScheduleConfig.java
新增檔案,使用 @EnableScheduling 開啟排程。
Scheduling Job Description
前綴 SCHEDULE-T- 開頭,用於處理排程任務,如:訂單處理,發送郵件等用途。
package org.ruoxue.spring_boot_168.config;
import java.util.concurrent.ThreadPoolExecutor;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import lombok.extern.slf4j.Slf4j;
@EnableScheduling
@Configuration
@Slf4j
public class ScheduleConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
String prefix = "SCHEDULE-T-";
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setThreadNamePrefix(prefix);
scheduler.setPoolSize(ThreadPoolConfig.MAX_POOLSIZE);
scheduler.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
taskRegistrar.setScheduler(scheduler);
scheduler.initialize();
log.info("prefix: " + prefix);
}
}
@Scheduled 參數
Param | Description |
cron | 表示式,指定任務在特定時間執行 |
fixedDelay | 表示上一次任務執行完成後多久再次執行,參數型別 long ,單位毫秒 |
fixedDelayString | 與 fixedDelay 一樣功能,參數型別 String |
fixedRate | 表示按一定的頻率執行任務,參數型別 long ,單位毫秒 |
fixedRateString | 與 fixedRate 一樣功能,參數型別 String |
initialDelay | 表示延遲多久執行第一次任務,參數型別 long,單位毫秒 |
initialDelayString | 與 initialDelay 一樣功能,參數型別 String |
zone | 時區,預設為目前時區 |
Cron 表示式
Cron 是一個字串,是由空格隔開的 6 或 7 個域所組成,每一個域對應一個含義,如:秒 分 時 每月第幾天 月 星期 年,其中年是可選欄位。
┌───────────── second (0-59) │ ┌───────────── minute (0 - 59) │ │ ┌───────────── hour (0 - 23) │ │ │ ┌───────────── day of the month (1 - 31) │ │ │ │ ┌───────────── month (1 - 12) (or JAN-DEC) │ │ │ │ │ ┌───────────── day of the week (0 - 7) │ │ │ │ │ │ (0 or 7 is Sunday, or MON-SUN) │ │ │ │ │ │ * * * * * *
Param | Description |
秒 | , – * / 四個字元,有效範圍為 0-59 的整數 |
分 | , – * / 四個字元,有效範圍為 0-59 的整數 |
時 | , – * / 四個字元,有效範圍為 0-23 的整數 |
每月第幾天 | , – * / ? L W C 八個字元,有效範圍為 0-31 的整數 |
月 | , – * / 四個字元,有效範圍為 1-12 的整數或 JAN-DEC |
星期 | , – * / ? L C # 八個字元,有效範圍為 1-7 的整數或 SUN-SAT 兩個範圍,1 表示星期天,2 表示星期一, 依次類推 |
* | 表示匹配該域的任意值,比如在秒*,就表示每秒都會觸發事件 |
? | 只能用在每月第幾天和星期兩個域,表示不指定值,當 2 個子表示式其中之一被指定了值以後,為了避免衝突,需要將另一個子表示式的值設為 ? |
- | 表示範圍,例如在分域使用 5-20 ,表示從 5 分到 20 分鐘每分鐘觸發一次 |
/ | 表示起始時間開始觸發,然後每隔固定時間觸發一次,例如在分域使用5/20,則意味著5分,25分,45分,分別觸發一次 |
, | 表示列出列舉值。例如:在分域使用5,20,則意味著在5和20分時觸發一次 |
L | 表示最後,只能出現在星期和每月第幾天域,如果在星期域使用 1L,意味著在最後的一個星期日觸發 |
W | 表示有效工作日(週一到週五),只能出現在每月第幾日域,系統將在離指定日期的最近的有效工作日觸發事件,W 的最近尋找不會跨過月份 |
LW | 這兩個字元可以連用,表示在某個月最後一個工作日,即最後一個星期五 |
# | 用於確定每個月第幾個星期幾,只能出現在每月第幾天域,例如在 1#3,表示某月的第三個星期日 |
測試 JUnit 5
ScheduleConfigTest.java
新增單元測試,驗證是否符合預期 。
package org.ruoxue.spring_boot_168.config;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.ruoxue.spring_boot_168.Application;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = Application.class)
public class ScheduleConfigTest {
@Autowired
private ScheduleConfig config;
@Test
public void config() {
assertNotNull(config);
}
}
Scheduling Tasks in Java config
測試方法上點右鍵執行 Run As -> JUnit Test ,查看 console 。
2022-06-20T11:35:57.157+0800 [main] INFO configureTasks:27 - prefix: SCHEDULE-T-
心得分享
Task Scheduler
輕量級的排程定時任務的實現,簡單方便使用,不過只能單點執行,若需要更多功能,如:分散式任務調度,此時可考慮 Elastic-Job、XXL-JOB 等框架來實現。