<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Spring Boot 寫定時(shí)任務(wù),發(fā)現(xiàn)了一個(gè)大坑!

          共 5700字,需瀏覽 12分鐘

           ·

          2021-05-10 15:52

          點(diǎn)擊關(guān)注公眾號(hào),Java干貨及時(shí)送達(dá)

          最近棧長(zhǎng)用 Spring Boot 寫了一個(gè)定時(shí)任務(wù):

          @Scheduled(cron = "0/10 * * * * ? *")
          public void execute() {
           ...
          }

          Spring Boot 實(shí)現(xiàn)定時(shí)任務(wù)確實(shí)很簡(jiǎn)單,其實(shí)是從 Spring 3.1 開始,定時(shí)任務(wù)的編寫就變得非常簡(jiǎn)單,只需要幾個(gè)注解就能快速開啟計(jì)劃任務(wù)的支持,具體可以看這篇文章:https://mp.weixin.qq.com/s/hsuCC93OJFc8URI517-umg

          可是當(dāng)我把代碼寫完,啟動(dòng)就報(bào)錯(cuò):

          Caused by: java.lang.IllegalStateException: Encountered invalid @Scheduled method 'xxx': Cron expression must consist of 6 fields (found 7 in "0/10 * * * * ? *")
           at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.processScheduled(ScheduledAnnotationBeanPostProcessor.java:511) ~[spring-context-5.3.1.jar:5.3.1]
           at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.lambda$null$1(ScheduledAnnotationBeanPostProcessor.java:374) ~[spring-context-5.3.1.jar:5.3.1]
           at java.lang.Iterable.forEach(Iterable.java:75) ~[na:1.8.0_261]
           at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.lambda$postProcessAfterInitialization$2(ScheduledAnnotationBeanPostProcessor.java:374) ~[spring-context-5.3.1.jar:5.3.1]
           at java.util.LinkedHashMap.forEach(LinkedHashMap.java:684) ~[na:1.8.0_261]
           at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.postProcessAfterInitialization(ScheduledAnnotationBeanPostProcessor.java:373) ~[spring-context-5.3.1.jar:5.3.1]
           at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:444) ~[spring-beans-5.3.1.jar:5.3.1]
           at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1792) ~[spring-beans-5.3.1.jar:5.3.1]
           at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:609) ~[spring-beans-5.3.1.jar:5.3.1]
           ... 16 common frames omitted

          什么鬼?

          錯(cuò)誤描述大概是說我的 Cron 表達(dá)式有問題,Cron 表達(dá)式只能由 6 位組成,但我的表達(dá)式有 7 位,不能啊,表達(dá)式也確實(shí)沒問題的啊。。。

          點(diǎn)進(jìn)去看下 @Scheduled 注解的 cron 參數(shù)源碼:

          確實(shí)只有 6 位,并沒有表示年份的占位。

          繼續(xù)看源碼,CronSequenceGenerator 在 Spring 5.3 中已經(jīng)標(biāo)識(shí)廢棄了,需要轉(zhuǎn)到:

          org.springframework.scheduling.support.CronExpression

          再點(diǎn)進(jìn)去看 CronExpression 類的源碼:

          6 個(gè)字段的意思很清楚了,具體可以參考:

          https://www.manpagez.com/man/5/crontab/

          示例表達(dá)式:

          "0 0 * * * *" = the top of every hour of every day.
          "*/10 * * * * *" = every ten seconds.
          "0 0 8-10 * * *" = 8, 9 and 10 o'clock of every day.
          "0 0 6,19 * * *" = 6:00 AM and 7:00 PM every day.
          "0 0/30 8-10 * * *" = 8:00, 8:30, 9:00, 9:30, 10:00 and 10:30 every day.
          "0 0 9-17 * * MON-FRI" = on the hour nine-to-five weekdays
          "0 0 0 25 12 ?" = every Christmas Day at midnight
          "0 0 0 L * *" = last day of the month at midnight
          "0 0 0 L-3 * *" = third-to-last day of the month at midnight
          "0 0 0 1W * *" = first weekday of the month at midnight
          "0 0 0 LW * *" = last weekday of the month at midnight
          "0 0 0 * * 5L" = last Friday of the month at midnight
          "0 0 0 * * THUL" = last Thursday of the month at midnight
          "0 0 0 ? * 5#2" = the second Friday in the month at midnight
          "0 0 0 ? * MON#1" = the first Monday in the month at midnight

          并且支持以下代替寫法:

          "@yearly" (or "@annually") to run un once a year, i.e. "0 0 0 1 1 *",
          "@monthly" to run once a month, i.e. "0 0 0 1 * *",
          "@weekly" to run once a week, i.e. "0 0 0 * * 0",
          "@daily" (or "@midnight") to run once a day, i.e. "0 0 0 * * *",
          "@hourly" to run once an hour, i.e. "0 0 * * * *".

          如:每年:0 0 0 1 1 *,就可以寫成:@yearly,除了每年,還有每月、每月、每周、每天、每小時(shí),可惜……沒有每分、每秒!

          Spring Task 我們可以將它看成是一個(gè)輕量級(jí)的 Quartz,而且使用起來比 Quartz 要簡(jiǎn)單許多,使用了類似于 cron 的表達(dá)式,并擴(kuò)展了平常的 UN*X 定義,看來和平常的 cron 表達(dá)式還不太一樣,位數(shù)不同,也存在兼容問題,真坑。。。

          既然知道了問題所在,再回到之前錯(cuò)誤,那就只能把最后的表示 "年" 的字段去掉,6 位就夠了,第7 位不要,默認(rèn)就是表示每年。

          那么問題來了,我想在具體的某年,如 2025/02/25 這天執(zhí)行任務(wù),咋整?

          沒辦法,Spring Task 不能指定年份,那就只能換成 Quartz,Quartz 也更強(qiáng)大,所以,如果是簡(jiǎn)單的定時(shí)任務(wù),Spring Task 就搞定了,復(fù)雜的建議還是使用 Quartz。

          另外,注意,Spring Task 的 cron 表達(dá)式并不是完全兼容通常的 cron 表達(dá)式,最好根據(jù)以上官方的文檔來編寫,以免到了線上不執(zhí)行那就完蛋了。

          最后,覺得我的文章對(duì)你用收獲的話,動(dòng)動(dòng)小手,給個(gè)在看、轉(zhuǎn)發(fā),原創(chuàng)不易,棧長(zhǎng)需要你的鼓勵(lì)。

          版權(quán)申明:本文系公眾號(hào) "Java技術(shù)棧" 原創(chuàng),原創(chuàng)實(shí)屬不易,轉(zhuǎn)載、引用本文內(nèi)容請(qǐng)注明出處,禁止抄襲、洗稿,請(qǐng)自重,尊重他人勞動(dòng)成果和知識(shí)產(chǎn)權(quán)。






          關(guān)注Java技術(shù)棧看更多干貨



          獲取 Spring Boot 實(shí)戰(zhàn)筆記!
          瀏覽 147
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产 激情 视频 在线 | 丁香色播五月 | 人人看黄色视频 | 天天撸天天干天天日 | 在线免费亚洲视频 |