寫在前面: 從2018年底開始學習SpringBoot,也用SpringBoot寫過一些項目。這裏對學習Springboot的一些知識總結記錄一下。如果你也在學習SpringBoot,可以關注我,一起學習,一起進步。
相關文章:
【Springboot系列】Springboot入門到項目實戰
定時任務作用
定時任務顧名思義就是定時執行一個指定的方法。在項目中也很常用,比如:
- 定時向用戶發送短信、郵件等。
- 定期統計數據。
- 天氣預報系統定期更新數據。
SpringBoot中使用定時任務
1、創建定時器
使用SpringBoot項目中創建定時任務非常簡單,只需幾行代碼便可完成。新建一個Timer類作爲定期任務類。代碼如下:
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import java.text.SimpleDateFormat;
import java.util.Date;
@Configuration //主要用於標記配置類,兼備Component的效果。
@EnableScheduling //開啓定時任務
public class Timer {
//添加定時任務,每隔5秒執行一次
@Scheduled(cron = "0/5 * * * * ?")
private void configureTasks() {
SimpleDateFormat simpleDateFormat=new SimpleDateFormat("HH:mm:ss");
System.out.println("當前時間:"+simpleDateFormat.format(new Date()));
}
}
【注】 其中@Scheduled註解用於開啓定時任務,@Scheduled註解的核心屬性是cron,代表定時任務的觸發計劃表達式。這個表達式的格式爲:
seconds秒,minutes分鐘,hours小時,day天,month月,week星期,year年(可選添加)
@Scheduled(cron="seconds minutes hours day month week year")
2、運行效果
定時任務方法中輸出了當前時間,用於顯示定時任務效果。上面定時器方法設置的是每隔5秒執行一次,效果如下:
3、cron表達式
cron表達式中,每個位置的約束如下:
序號 | 說明 | 是否必填 | 值 | 通配符 |
---|---|---|---|---|
1 | 秒 | 是 | 0-59 | , - * / |
2 | 分 | 是 | 0-59 | , - * / |
3 | 小時 | 是 | 0-23 | , - * / |
4 | 日 | 是 | 1-31 | , - * / |
5 | 月 | 是 | 1-12 | , - * / L W |
6 | 星期 | 是 | 1-7/SUN-SAT | , - * / ? L # |
7 | 年 | 否 | 1970-2099 | , - * / |
- 星號( * ):可用在所有字段中,表示對應時間域的所有值,例如,* 在分鐘字段時,表示“每分鐘都會觸發”。
- 問號(?):該字符只在日期和星期字段中使用,它通常指定爲“無意義的值”,相當於佔位符。
- 減號(-):表達一個範圍,如在小時字段中使用“10-12”,則表示從10到12點,即10, 11, 12。
- 逗號(,):表達一個列表值,如在星期字段中使用“1, 2, 3”,則表示星期一,星期三和星期五。
- 斜槓(/):x / y表達一個等步長序列,x爲起始值,y爲增量步長值。如在秒數字段中使用0 / 15,則表示爲0, 15, 30和45秒,而5 / 15在分鐘字段中表示5, 20, 35, 50,你也可以使用* / y,它等同於0 / y。
- L:該字符只在日期和星期字段中使用,代表“Last”的意思,但它在兩個字段中意思不同。L在日期字段中,表示這個月份的最後一天,如一月的31號,非閏年二月的28號;如果L用在星期中,則表示星期六,等同於7。但是,如果L出現在星期字段裏,而且在前面有一個數值X,則表示“這個月的最後X天”,例如,6L表示該月的最後星期五。
- W:該字符只能出現在日期字段裏,是對前導日期的修飾,表示離該日期最近的工作日。例如15W表示離該月15號最近的工作日,如果該月15號是星期六,則匹配14號星期五;如果15日是星期日,則匹配16號星期一;如果15號是星期二,那結果就是15號星期二。但必須注意關聯的匹配日期不能夠跨月,如你指定1W,如果1號是星期六,結果匹配的是3號星期一,而非上個月最後的那天。W字符串只能指定單一日期,而不能指定日期範圍。
- LW組合:在日期字段可以組合使用LW,它的意思是當月的最後一個工作日。
- 井號(#):該字符只能在星期字段中使用,表示當月某個工作日。如6#3表示當月的第三個星期五(6表示星期五,#3表示當前的第三個),而4#5表示當月的第五個星期三,假設當月沒有第五個星期三,忽略不觸發。
- C:該字符只在日期和星期字段中使用,代表“Calendar”的意思。它的意思是計劃所關聯的日期,如果日期沒有被關聯,則相當於日曆中所有日期。例如5C在日期字段中就相當於日曆5日以後的第一天。1C在星期字段中相當於星期日後的第一天。
Cron表達式參數值:
- 秒(0~59) 例如0/5表示每5秒
- 分(0~59)
- 時(0~23)
- 日(0~31)的某天,需計算
- 月(0~11)
- 星期( 可填1-7[1表示星期天,7表示星期六] 或 SUN/MON/TUE/WED/THU/FRI/SAT)
常用的cron表達式含義
每隔5秒執行一次:0/5 * * * * ?
每隔1分鐘執行一次:0 */1 * * * ?
每天24點執行一次:0 0 0 * * ?
每月1號凌晨1點執行一次:0 0 1 1 * ?
每月最後一天24點執行一次:0 0 24 L * ?
每週星期天凌晨1點實行一次:0 0 1 ? * L
在15分、35分、40分執行一次:0 15,35,40 * * * ?
每天的0點、10點、15點、20點都執行一次:0 0 0,10,15,20 * * ?
4、fixedRate
fixedRate 兩次執行任務時間間隔是任務的開始點,也就是上一次執行開始多少毫秒後執行。
@Configuration //主要用於標記配置類,兼備Component的效果。
@EnableScheduling //開啓定時任務
@EnableAsync //開啓多線程
public class Timer {
@Scheduled(fixedRate = 3000)
@Async
public void configureTasks() {
SimpleDateFormat simpleDateFormat=new SimpleDateFormat("HH:mm:ss");
System.out.println("開始,時間是 : "+simpleDateFormat.format(new Date())+""+Thread.currentThread().getName());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("結束,時間是 : "+simpleDateFormat.format(new Date())+""+Thread.currentThread().getName());
}
}
【注】 fixedRate屬性值的單位爲毫秒,因爲使用到了線程,所以需要在類上添加上@EnableAsync 註解,開啓多線程。爲了能看出效果,在控制檯輸出時開始執行後,線程休眠5秒後在執行。
運行效果(是在上一次執行開始後3秒執行,輸出用線程的名字區分):
可以看出第一次執行,過了三秒,方法又開始執行了,此時第一次執行的方法還沒有結束。
5、fixedDelay
fixedDelay 的間隔是前次任務的結束與下次任務的開始,也就是上一次執行完成後多少毫秒後執行。
@Configuration //主要用於標記配置類,兼備Component的效果。
@EnableScheduling //開啓定時任務
@EnableAsync //開啓多線程
public class Timer {
@Scheduled(fixedDelay = 3000)
@Async
public void configureTasks() {
SimpleDateFormat simpleDateFormat=new SimpleDateFormat("HH:mm:ss");
System.out.println("開始,時間是 : "+simpleDateFormat.format(new Date())+""+Thread.currentThread().getName());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("結束,時間是 : "+simpleDateFormat.format(new Date())+""+Thread.currentThread().getName());
}
}
【注】 fixedDelay屬性值的單位爲毫秒,在控制檯輸出時開始執行後,線程休眠5秒後在執行。
運行效果(是在上一次執行開始後3秒執行,輸出用線程的名字區分):
可以看出第一次執行完成後又過了3秒後,纔開始重新執行。
最後有什麼不足之處,歡迎大家指出,期待與你的交流。