網頁

2020/9/17

Spring Boot 使用@Schedule建立排程任務範例

Spring Boot使用@Schedule排程(scheduling task)簡單範例如下。

本篇主要參考Spring官方教學Scheduling Tasks

範例環境

  • Java 8
  • Maven
  • IntelliJ IDEA

參考IntelliJ IDEAEclipse建立Spring Boot專案。


依賴設定參考範例的pom.xml

spring-boot-starter-web中內含Spring的排程功能。
加入org.awaitility.awaitility為測試非同步(asynchronous)程式的套件。


建立排程任務類別DemoScheduleTask。類別加上@Component使被掃描並註冊為Spring的Bean,在printUnixEpochTime()前加上@Scheduled則此方法則成為排程任務。@Scheduled的屬性initialDelay=2000表示排程開始後延遲2秒才執行;fixedRate = 3000表示執行後每固定3秒再重複執行。

DemoScheduleTask

package com.abc.demo.schedule;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class DemoScheduleTask {

    @Scheduled(initialDelay = 2000, fixedRate = 3000)
    public void printUnixEpochTime() {
        System.out.println(System.currentTimeMillis());
    }
}

建立好任務必須在配置類@Configuration加上@EnableScheduling啟用排程則排程才會執行,範例是加在@SpringBootApplication類,此注釋包含了@Configuration

DemoApplication

package com.abc.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@EnableScheduling // <--- 啟用排程
@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}

執行後在console每3秒印出當前的unix epoch time。

1600399693180
1600399696177
1600399699174
1600399702171

使用awaitility套件來撰寫測試程式DemoScheduleTaskTests

DemoScheduleTaskTests

package com.abc.demo.schedule;

import org.awaitility.Awaitility;
import org.awaitility.Durations;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.SpyBean;

@SpringBootTest
class DemoScheduleTaskTests {

    private final static int MIN_NUMBER_OF_INVOCATIONS = 2;

    @SpyBean // 用@SpyBean才可被Mockito.verify驗證備測試對象的調用次數
    DemoScheduleTask demoScheduleTask;

    /**
     * 測試DemoScheduleTask.printUnixEpochTime()在10秒鐘至少被執行2次
     */
    @Test
    void printUnixEpochTime_testInvocationAtLeastTwoTimesDuringTenSeconds() {
        Awaitility.await()
                .atMost(Durations.TEN_SECONDS) // 等待期間10秒
                .untilAsserted( // 直到assert發生停止等待
                        () -> Mockito.verify(demoScheduleTask, Mockito.atLeast(MIN_NUMBER_OF_INVOCATIONS))
                                .printUnixEpochTime()); // 驗證demoScheduleTask.printUnixEpochTime()被調用2次
    }
}

參考github


沒有留言:

張貼留言