Spring Boot Scheduling Tasks - Spring Boot 168 EP 25

Spring Boot Scheduling Tasks – Spring Boot 168 EP 25

提供排程功能,實現定期任務執行,使用 @Scheduled 定義排程,能夠快速方便地建立項目, EP 25 增加 了範例,並透過 JUnit 5 單元測試來驗證產出結果。

前言

開發上非常地簡單,只要使用註解定義就能實現,方便日後管理與維護,同時也可以使用多種的 @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 等框架來實現。

發佈留言