回復(fù)“ 面試 ”獲取全套大廠面試資料
在開發(fā)項(xiàng)目的時(shí)候,使用定時(shí)任務(wù)的情況還是非常之多的,比如說:早上八點(diǎn)統(tǒng)一推送昨天的“戰(zhàn)報(bào)”、金融相關(guān)行業(yè)則會(huì)涉及每天的對賬等。
在 Spring + SpringMVC 環(huán)境中,一般來說,要實(shí)現(xiàn)定時(shí)任務(wù),我們有兩種方案:一種是使用 Spring 自帶的定時(shí)任務(wù)處理器 @Scheduled 注解;另一種就是使用第三方框架 Quartz 。Spring Boot 源自 Spring+SpringMVC ,因此天然具備這兩個(gè) Spring 中的定時(shí)任務(wù)實(shí)現(xiàn)策略,當(dāng)然也支持 Quartz,本文我們就來看下 Spring Boot 中使用@Scheduled的方式實(shí)現(xiàn)定時(shí)任務(wù)。
位于spring-context-**.jar包中可以找到對應(yīng)的定時(shí) 相關(guān)的幾個(gè)注解,請看下圖:
@Target ({ElementType.TYPE})@Retention (RetentionPolicy.RUNTIME)@Import ({SchedulingConfiguration.class})@Documented public @interface EnableScheduling { }
這里項(xiàng)目還是沿用前面Spring Boot實(shí)戰(zhàn)系列中的Spring Boot項(xiàng)目。請看是如何快速搞定的
第一步:給啟動(dòng)類添加注解@EnableScheduling
@EnableScheduling @SpringBootApplication public class DemoApplication { public static void main (String[] args) { SpringApplication.run(DemoApplication.class, args); } }
第二步:創(chuàng)建自己的定時(shí)類
@Component public class MyScheduled { @Scheduled (fixedRate = 5000 ) public void reportCurrentTime () { //寫你的業(yè)務(wù)代碼 System.out.println(new Date()); } }
啟動(dòng)項(xiàng)目,可以看到每五秒打印一次時(shí)間,證明是每五秒執(zhí)行一次任務(wù)。
這么輕松就搞定了Spring Boot定時(shí)任務(wù)。
回頭再看看@Scheduled
注解的源碼
@Target ({ElementType.METHOD, ElementType.ANNOTATION_TYPE})@Retention (RetentionPolicy.RUNTIME)@Documented @Repeatable (Schedules.class)public @interface Scheduled { String CRON_DISABLED = "-" ; String cron () default "" ; String zone () default "" ; long fixedDelay () default -1L ; String fixedDelayString () default "" ; long fixedRate () default -1L ; String fixedRateString () default "" ; long initialDelay () default -1L ; String initialDelayString () default "" ; }
簡要說明:
首先使用 @Scheduled 注解開啟一個(gè)定時(shí)任務(wù)。
fixedRate 表示任務(wù)執(zhí)行之間的時(shí)間間隔,具體是指兩次任務(wù)的開始時(shí)間間隔,即第二次任務(wù)開始時(shí),第一次任務(wù)可能還沒結(jié)束。
fixedDelay 表示任務(wù)執(zhí)行之間的時(shí)間間隔,具體是指本次任務(wù)結(jié)束到下次任務(wù)開始之間的時(shí)間間隔。
initialDelay 表示首次任務(wù)啟動(dòng)的延遲時(shí)間。
所有時(shí)間的單位都是毫秒。
上面這是一個(gè)基本用法,除了這幾個(gè)基本屬性之外,@Scheduled 注解也支持 cron 表達(dá)式,使用 cron 表達(dá)式,可以非常豐富的描述定時(shí)任務(wù)的時(shí)間。cron 表達(dá)式格式如下:
[秒] [分] [小時(shí)] [日] [月] [周] [年]
具體取值如下:
這一塊需要大家注意的是,月份中的日期和星期可能會(huì)起沖突,因此在配置時(shí)這兩個(gè)得有一個(gè)是 ?
通配符含義:
?
表示不指定值,即不關(guān)心某個(gè)字段的取值時(shí)使用。需要注意的是,月份中的日期和星期可能會(huì)起沖突,因此在配置時(shí)這兩個(gè)得有一個(gè)是 ?
` 表示所有值,例如:在秒的字段上設(shè)置 `
,表示每一秒都會(huì)觸發(fā)
,
用來分開多個(gè)值,例如在周字段上設(shè)置 "MON,WED,FRI" 表示周一,周三和周五觸發(fā)
-
表示區(qū)間,例如在秒上設(shè)置 "10-12",表示 10,11,12秒都會(huì)觸發(fā)
/
用于遞增觸發(fā),如在秒上面設(shè)置"5/15" 表示從5秒開始,每增15秒觸發(fā)(5,20,35,50)
#
序號(hào)(表示每月的第幾個(gè)周幾),例如在周字段上設(shè)置"6#3"表示在每月的第三個(gè)周六,(用 在母親節(jié)和父親節(jié)再合適不過了)
周字段的設(shè)置,若使用英文字母是不區(qū)分大小寫的 ,即 MON 與mon相同
L
表示最后的意思。在日字段設(shè)置上,表示當(dāng)月的最后一天(依據(jù)當(dāng)前月份,如果是二月還會(huì)自動(dòng)判斷是否是潤年), 在周字段上表示星期六,相當(dāng)于"7"或"SAT"(注意周日算是第一天)。如果在"L"前加上數(shù)字,則表示該數(shù)據(jù)的最后一個(gè)。例如在周字段上設(shè)置"6L"這樣的格式,則表示"本月最后一個(gè)星期五"
W
表示離指定日期的最近工作日(周一至周五),例如在日字段上設(shè)置"15W",表示離每月15號(hào)最近的那個(gè)工作日觸發(fā)。如果15號(hào)正好是周六,則找最近的周五(14號(hào))觸發(fā), 如果15號(hào)是周未,則找最近的下周一(16號(hào))觸發(fā),如果15號(hào)正好在工作日(周一至周五),則就在該天觸發(fā)。如果指定格式為 "1W",它則表示每月1號(hào)往后最近的工作日觸發(fā)。如果1號(hào)正是周六,則將在3號(hào)下周一觸發(fā)。(注,"W"前只能設(shè)置具體的數(shù)字,不允許區(qū)間"-")
L
和 W
可以一組合使用。如果在日字段上設(shè)置"LW",則表示在本月的最后一個(gè)工作日觸發(fā)(一般指發(fā)工資 )
下面給出幾個(gè)表達(dá)式配置案例
“0 0 12 * * ?” 每天中午12點(diǎn)觸發(fā) “0 15 10 ? * *” 每天上午10:15觸發(fā) “0 15 10 * * ?” 每天上午10:15觸發(fā) “0 15 10 * * ? *” 每天上午10:15觸發(fā) “0 15 10 * * ? 2005” 2005年的每天上午10:15觸發(fā) “0 * 14 * * ?” 在每天下午2點(diǎn)到下午2:59期間的每1分鐘觸發(fā) “0 0/5 14 * * ?” 在每天下午2點(diǎn)到下午2:55期間的每5分鐘觸發(fā) “0 0/5 14,18 * * ?” 在每天下午2點(diǎn)到2:55期間和下午6點(diǎn)到6:55期間的每5分鐘觸發(fā) “0 0-5 14 * * ?” 在每天下午2點(diǎn)到下午2:05期間的每1分鐘觸發(fā) “0 10,44 14 ? 3 WED” 每年三月的星期三的下午2:10和2:44觸發(fā) “0 15 10 ? * MON-FRI” 周一至周五的上午10:15觸發(fā) “0 15 10 15 * ?” 每月15日上午10:15觸發(fā) “0 15 10 L * ?” 每月最后一日的上午10:15觸發(fā) “0 15 10 ? * 6L” 每月的最后一個(gè)星期五上午10:15觸發(fā) “0 15 10 ? * 6L 2002-2005” 2002年至2005年的每月的最后一個(gè)星期五上午10:15觸發(fā) “0 15 10 ? * 6#3” 每月的第三個(gè)星期五上午10:15觸發(fā)
例如,在 @Scheduled 注解中來一個(gè)簡單的 cron 表達(dá)式,每隔10秒觸發(fā)一次,代碼如下:
@Component public class MyScheduled { @Scheduled (cron = "0/10 * * * * *" ) public void test () { System.out.println(new Date()+"開始執(zhí)行 " ); } }
啟動(dòng)項(xiàng)目,輸出
總結(jié),其實(shí)在Spring Boot項(xiàng)目中實(shí)現(xiàn)定時(shí)任務(wù)很簡單,兩步就搞定了:
在程序的入口Appliaction類上添加@EnableScheduling注解。
在定時(shí)方法上加@Scheduled注解。
由于篇幅有限,Quartz的實(shí)現(xiàn)方式留到下一次,ok,今天就這么輕松的結(jié)束啦。