Spring Boot(十五)— 任務排程
任務排程(也可以稱為定時任務)是指在特定的時間段去執行一個規定的任務過程。Spring Boot為開發者提供了一個更優雅的方式建立任務排程程式。在本章節中,我們將學習使用Spring Boot來建立任務排程程式。
任務排程分為兩種型別,一種是間隔時間執行的任務,如每隔3秒執行一次任務程式;另外一種時指定具體時間的任務,如在每天的凌晨整點備份資料庫。
Cron表示式
在開始講解定時任務之前,先來看一下定時任務中的Cron表示式的相關內容。Cron表示式用於配置CronTrigger例項,它是org.quartz.Trigger的子類。Cron表示式被放置在**@Scheduled** 註釋標籤中,下面的程式碼給出了一個cron表示式的樣例:
@Scheduled(cron = "0/5 * 22 * * ?")
public void cronJobSchedule(){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
Date now = new Date();
logger.info("Java cron job expression scheduler::"+sdf.format(now));
}
複製程式碼
在cron表示式中,一共有七位表示式引數,我們將使用一張表格來了解各個引數的用途:
位數 | 說明 | 範圍 |
---|---|---|
第一位 | 表示秒 | 取值範圍:0-59 |
第二位 | 表示分鐘 | 取值範圍:0-59 |
第三位 | 表示小時 | 取值範圍:0-23 |
第四位 | 表示日期 | 取值範圍:1-31 |
第五位 | 表示月份 | 取值範圍:1-12 |
第六位 | 表示星期 | 取值範圍:1-7 |
第七位 | 表示年份,通常置空 | 取值範圍:1970-2099 |
說明,在第六位星期引數中,1表示的是星期日,除使用數字表示外,還可以使用表示星期的英文縮寫來設定
瞭解了cron表示式的語法規則後,我們再來了解一下表示式中各種佔位符的含義。cron表示式中一共可以使用的佔位符有5個,如下表所示:
佔位符 | 說明 | 示例 |
---|---|---|
(星號)* | 可以理解為一個週期 | 每秒、沒分、每小時等 |
(問好)? | 只能出現在日期和星期兩個位置中 | 表示時間不確定 |
(橫線)- | 表示一個時間範圍 | 如在小時中10-11,表示從上午10點到上午11點 |
(逗號), | 表示一個列表值 | 如在星期中使用:1,3,5 表示星期一、星期三和星期五 |
(斜槓)/ | 表示一個開始時間和間隔時間週期 | 在分鐘中使用:0/15 表示從0分開始,每15分鐘執行一次 |
下面將列舉一些示例來說明cron表示式和佔位符:
表示式 | 說明 |
---|---|
0 0 0 * * ? | 每天00:00:00執行任務 |
0 30 10 * * ? | 每天上午10:30:00執行任務 |
0 30 10 ? * * | 每天上午10:30:00執行任務 |
0 0/15 10 * * ? | 每天上午10:00:00、10:15:00、10:30:00和10:45:00這四個時間點執行任務 |
0 0 0 ? * 1 | 每個星期天的凌晨整點執行任務 |
0 0 0 ? * 1#3 | 每個月的第三個星期天的凌晨整點執行任務 |
開啟定時任務
在Spring Boot應用程式中,需要使用**@EnableScheduling**註解來開啟對定時任務的支援,並且該註解應該用於應用程式主類上,下面的程式碼演示了在Spring Boot中開啟定時任務支援。
package com.ramostear.application;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
public class ScheduleApplication {
public static void main(String[] args) {
SpringApplication.run(ScheduleApplication.class, args);
}
}
複製程式碼
固定時間任務
下面我們將使用cron表示式建立一個固定時間的排程任務來實現每天的22點到23點每隔15秒鐘執行一次任務。
package com.ramostear.application.schedule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @author ramostear
* @create-time 2019/3/11 0011-21:49
* @modify by :
* @since:
*/
@Component
public class DemoScheduler {
private static final Logger logger = LoggerFactory.getLogger(DemoScheduler.class);
@Scheduled(cron = "0/15 * 22-23 * * ?")
public void cronJobSchedule(){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
Date now = new Date();
logger.info("Java cron job expression scheduler::"+sdf.format(now));
}
}
複製程式碼
下面的文字是應用程式在23:09分啟動後,控制檯視窗輸出的日誌資訊:
[2019-03-11T23:09:00.000z][com.ramostear.application.schedule.DemoScheduler][scheduling-1][26][INFO ]
Java cron job expression scheduler::2019-03-11 23:09:00.001
[2019-03-11T23:09:15.015z][com.ramostear.application.schedule.DemoScheduler][scheduling-1][26][INFO ]
Java cron job expression scheduler::2019-03-11 23:09:15.002
[2019-03-11T23:09:30.030z][com.ramostear.application.schedule.DemoScheduler][scheduling-1][26][INFO ]
Java cron job expression scheduler::2019-03-11 23:09:30.001
[2019-03-11T23:09:45.045z][com.ramostear.application.schedule.DemoScheduler][scheduling-1][26][INFO ]
Java cron job expression scheduler::2019-03-11 23:09:45.002
[2019-03-11T23:10:00.000z][com.ramostear.application.schedule.DemoScheduler][scheduling-1][26][INFO ]
Java cron job expression scheduler::2019-03-11 23:10:00.002
複製程式碼
固定週期任務
固定時間週期排程任務是指從應用程式啟動開始,在固定的時間週期執行一次任務,如每1000毫秒執行一次、每1分鐘執行一次。下面的程式碼給出了建立固定週期排程任務的示例:
@Scheduled(fixedRate = 1000)
public void fiexdRateSchedule(){
//TODO ...
}
複製程式碼
通過配置fixedRate引數的值,實現從應用程式啟動後,每隔5秒鐘執行一次任務。
package com.ramostear.application.schedule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @author ramostear
* @create-time 2019/3/11 0011-21:49
* @modify by :
* @since:
*/
@Component
public class DemoScheduler {
private static final Logger logger = LoggerFactory.getLogger(DemoScheduler.class);
@Scheduled(fixedRate=5000)
public void fixedRateSchedule(){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
Date now = new Date();
logger.info("Java fixedRate scheduler::"+sdf.format(now));
}
}
複製程式碼
下面的文字是在23:18分啟動應用程式後,控制檯視窗輸出的日誌資訊。
[2019-03-11T23:18:22.022z][com.ramostear.application.schedule.DemoScheduler][scheduling-1][33][INFO ]
Java fixedRate scheduler::2019-03-11 23:18:22.062
[2019-03-11T23:18:27.027z][com.ramostear.application.schedule.DemoScheduler][scheduling-1][33][INFO ]
Java fixedRate scheduler::2019-03-11 23:18:27.062
[2019-03-11T23:18:32.032z][com.ramostear.application.schedule.DemoScheduler][scheduling-1][33][INFO ]
Java fixedRate scheduler::2019-03-11 23:18:32.062
[2019-03-11T23:18:37.037z][com.ramostear.application.schedule.DemoScheduler][scheduling-1][33][INFO ]
Java fixedRate scheduler::2019-03-11 23:18:37.063
[2019-03-11T23:18:42.042z][com.ramostear.application.schedule.DemoScheduler][scheduling-1][33][INFO ]
Java fixedRate scheduler::2019-03-11 23:18:42.062
複製程式碼
時延排程
所謂的時延排程,是通過設定initialDelay和fixedDelay屬性的值來控制當應用程式啟動成功後,推遲一定時間再執行排程任務,其使用的語法如下:
@Scheduled(fixedDelay=1000,initialDelay=1000)
public fixedDelaySchedule(){
}
複製程式碼
現在,我們將實現一個特定的定時任務需求:在應用程式啟動成功後延遲10秒鐘,再以每5秒鐘的頻率執行任務:
package com.ramostear.application.schedule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @author ramostear
* @create-time 2019/3/11 0011-21:49
* @modify by :
* @since:
*/
@Component
public class DemoScheduler {
private static final Logger logger = LoggerFactory.getLogger(DemoScheduler.class);
@Scheduled(fixedDelay = 5000,initialDelay = 10000)
public void fixedRateAndInitialDelaySchedule(){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
Date now = new Date();
logger.info("Java fixedRate and initialDelay scheduler::"+sdf.format(now));
}
}
複製程式碼
下面的文字顯示了在23:30:59啟動應用程式,控制檯視窗輸出的日誌資訊:
[2019-03-11T23:31:01.001z][org.springframework.boot.StartupInfoLogger][main][59][INFO ] Started ScheduleApplication in 2.193 seconds (JVM running for 2.904)
[2019-03-11T23:31:11.011z][com.ramostear.application.schedule.DemoScheduler][scheduling-1][40][INFO ] Java fixedRate and initialDelay scheduler::2019-03-11 23:31:11.639
[2019-03-11T23:31:16.016z][com.ramostear.application.schedule.DemoScheduler][scheduling-1][40][INFO ] Java fixedRate and initialDelay scheduler::2019-03-11 23:31:16.640
[2019-03-11T23:31:21.021z][com.ramostear.application.schedule.DemoScheduler][scheduling-1][40][INFO ] Java fixedRate and initialDelay scheduler::2019-03-11 23:31:21.641
[2019-03-11T23:31:26.026z][com.ramostear.application.schedule.DemoScheduler][scheduling-1][40][INFO ] Java fixedRate and initialDelay scheduler::2019-03-11 23:31:26.643
[2019-03-11T23:31:31.031z][com.ramostear.application.schedule.DemoScheduler][scheduling-1][40][INFO ] Java fixedRate and initialDelay scheduler::2019-03-11 23:31:31.644
複製程式碼
從日誌資訊中可以看到,應用程式在23:31:01啟動成功。等待十秒後,在23:31:11輸出了第一條日誌資訊,往後每隔5秒輸出一條日誌資訊。
注意:上面所設定的引數都是以毫秒為單位
本章節的課程原始碼已經上傳至Github程式碼倉庫,你可以訪問下面的連結獲取課程原始碼:github.com/ramostear/s…