javascript
与Spring的计划任务一起按时运行
您是否需要每天像鬧鐘一樣在同一時間運行某個流程? 然后,Spring的預(yù)定任務(wù)適合您。 允許您使用@Scheduled注釋方法,以使其在指定的時間或內(nèi)部間隔運行。 在本文中,我們將研究如何設(shè)置一個可以使用計劃任務(wù)的項目,以及如何使用不同的方法來定義它們的執(zhí)行時間。
我將在本文中使用Spring Boot,以使依賴關(guān)系變得簡潔而又簡單,這是因為可以對spring-boot-starter依賴項進行調(diào)度,該依賴項將以某種方式包含在幾乎每個Spring Boot項目中。 這使您可以使用任何其他啟動程序依賴項,因為它們會引入spring-boot-starter及其所有關(guān)系。 如果要包括確切的依賴項本身,請使用spring-context 。
您可以使用spring-boot-starter 。
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>2.0.0.RC1</version> </dependency>或直接使用spring-context 。
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.0.3.RELEASE</version> </dependency>創(chuàng)建計劃任務(wù)非常簡單。 將@Scheduled批注添加到希望自動運行的任何方法中,并將@EnableScheduling包含在配置文件中。
因此,例如,您可能會遇到類似以下的內(nèi)容。
@Component public class EventCreator {private static final Logger LOG = LoggerFactory.getLogger(EventCreator.class);private final EventRepository eventRepository;public EventCreator(final EventRepository eventRepository) {this.eventRepository = eventRepository;}@Scheduled(fixedRate = 1000)public void create() {final LocalDateTime start = LocalDateTime.now();eventRepository.save(new Event(new EventKey("An event type", start, UUID.randomUUID()), Math.random() * 1000));LOG.debug("Event created!");} }這里有很多代碼對于運行計劃任務(wù)并不重要。 正如我在一分鐘前說過的,我們需要在方法上使用@Scheduled ,它將自動開始運行。 因此,在上面的示例中, create方法將每隔1000毫秒(1秒)開始運行,如注釋的fixedRate屬性所示。 如果我們想更改其運行頻率,則可以增加或減少fixedRate時間,或者可以考慮使用可用的不同調(diào)度方法。
因此,您可能想知道這些其他方法是正確的嗎? 好了,它們就在這里(我還將在此處包括fixedRate )。
- fixedRate在fixedRate調(diào)用之間以固定的毫秒周期執(zhí)行該方法。
- fixedRateString一樣的fixedRate ,但有一個字符串值來代替。
- fixedDelay在一次調(diào)用結(jié)束與下一次調(diào)用之間以固定的毫秒周期執(zhí)行該方法。
- fixedDelayString一樣fixedDelay但一個字符串值來代替。
- cron使用類似cron的表達(dá)式來確定何時執(zhí)行該方法(我們將在以后更深入地介紹此方法)。
@Scheduled批注還有一些其他實用程序?qū)傩浴?
- zone指示將解析cron表達(dá)式的時區(qū),如果不包括時區(qū),它將使用服務(wù)器的默認(rèn)時區(qū)。 因此,如果您需要它在特定時區(qū)運行,例如香港,則可以使用zone = "GMT+8:00" 。
- initialDelay延遲第一次執(zhí)行計劃任務(wù)的毫秒數(shù),需要使用固定速率或固定延遲屬性之一。
- initialDelayString同為initialDelay但一個字符串值來代替。
以下是一些使用固定速率和延遲的示例。
@Scheduled(fixedRate = 1000)與之前相同,每1秒運行一次。
@Scheduled(fixedRateString = "1000")同上。
@Scheduled(fixedDelay = 1000)在上一次調(diào)用完成后運行1秒。
@Scheduled(fixedRate = 1000, initialDelay = 5000)每秒運行一次,但要等待5秒鐘才能首次執(zhí)行。
現(xiàn)在來看一下cron屬性,它可以對任務(wù)的計劃進行更多控制,讓我們定義任務(wù)運行的秒數(shù),分鐘數(shù)和小時數(shù),甚至可以進一步指定任務(wù)的運行年限。
以下是構(gòu)建cron表達(dá)式的組件的細(xì)分。
- Seconds值可以為0-59或特殊字符, - * / 。
- Minutes值可以為0-59或特殊字符, - * / 。
- Hours值可以為0-59或特殊字符, - * / 。
- Day of month可以具有值1-31或特殊字符, - * ? / LWC , - * ? / LWC 。
- Month值可以為1-12 , JAN-DEC或特殊字符, - * / 。
- Day of week可以具有值1-7 , SUN-SAT或特殊字符, - * ? / LC # , - * ? / LC # 。
- Year可以為空,值為1970-2099或特殊字符, - * / 。
為了更加清楚起見,我將細(xì)目分類組合成一個由字段標(biāo)簽組成的表達(dá)式。
@Scheduled(cron = "[Seconds] [Minutes] [Hours] [Day of month] [Month] [Day of week] [Year]")請不要在表達(dá)式中包括花括號(我使用它們使表達(dá)式更清晰)。
在繼續(xù)之前,我們需要了解特殊字符的含義。
- *表示所有值,因此,如果在第二個字段中使用,則表示每秒或在天字段中使用,表示每天運行。
- ? 表示沒有特定的值,并且可以在“月的天”或“星期幾”字段中使用,其中使用一個會使另一個無效。 如果我們指定在一個月的15日觸發(fā),則一個? 將在“ Day of week字段中使用。
- -表示值的范圍(例如,小時數(shù)字段中的1-3表示小時數(shù)1、2和3)。
- ,代表附加價值,例如周一,周三,SUN在本周,說明此一天,在周一,周三和周日。
- /代表增量,例如,秒字段中的0/15從0(0、15、30和45)開始每15秒觸發(fā)一次。
- L代表一周或一個月的最后一天。 請記住,在這種情況下,星期六是一周的結(jié)束,因此在“星期幾”字段中使用L將在星期六觸發(fā)。 可以將其與月日字段中的數(shù)字結(jié)合使用,例如6L代表月的最后一個星期五,或者L-3這樣的表達(dá)式表示月的最后一天。 如果我們在星期幾字段中指定一個值,則必須使用? 在“月”字段中,反之亦然。
- W表示每月的最接近的工作日。 例如,如果15W是工作日,則在每月的第15天觸發(fā),否則它將在最近的工作日運行。 該值不能在日期值列表中使用。
- #指定任務(wù)應(yīng)該在星期幾和星期幾觸發(fā)。 例如, 5#2表示該月的第二個星期四。 如果您指定的日期和星期溢出到下個月,則不會觸發(fā)。
在這里可以找到有用的資源,其中的解釋稍長一些,這有助于我撰寫本文。
讓我們來看幾個例子。
@Scheduled(cron = "0 0 12 * * ?")每天晚上12點開火。
@Scheduled(cron = "0 15 10 * * ? 2005")2005年每天早上10:15觸發(fā)。
@Scheduled(cron = "0/20 * * * * ?")每20秒觸發(fā)一次。
有關(guān)更多示例,請參閱我前面提到的鏈接, 此處再次顯示。 幸運的是,如果您在編寫一個簡單的cron表達(dá)式時遇到麻煩,那么您應(yīng)該可以在Google中找到所需的方案,因為有人可能已經(jīng)在Stack Overflow上問了同樣的問題。
要將上述內(nèi)容與一個小的代碼示例綁定在一起,請參見下面的代碼。
@Component public class AverageMonitor {private static final Logger LOG = LoggerFactory.getLogger(AverageMonitor.class);private final EventRepository eventRepository;private final AverageRepository averageRepository;public AverageMonitor(final EventRepository eventRepository, final AverageRepository averageRepository) {this.eventRepository = eventRepository;this.averageRepository = averageRepository;}@Scheduled(cron = "0/20 * * * * ?")public void publish() {final double average =eventRepository.getAverageValueGreaterThanStartTime("An event type", LocalDateTime.now().minusSeconds(20));averageRepository.save(new Average(new AverageKey("An event type", LocalDateTime.now()), average));LOG.info("Average value is {}", average);} }在這里,我們有一個類,每20秒向Cassandra查詢一次同一時間段內(nèi)事件的平均值。 同樣,這里的大多數(shù)代碼都是@Scheduled批注中的噪音,但在野外看到它可能會有所幫助。 此外,如果您觀察到這一情況,則對于每20秒運行一次的用例,在此處使用頻繁運行任務(wù)的情況下,使用fixedRate以及可能使用fixedDelay屬性而不是cron更為合適。
@Scheduled(fixedRate = 20000)是上面使用的cron表達(dá)式的fixedRate等效項。
我前面提到的最終要求是將@EnableScheduling批注添加到配置類。
@SpringBootApplication @EnableScheduling public class Application {public static void main(final String args[]) {SpringApplication.run(Application.class);} }作為一個很小的Spring Boot應(yīng)用程序,我已將@EnableScheduling批注附加到主@SpringBootApplication類。
總而言之,我們可以安排任務(wù)使用@Scheduled注釋以及執(zhí)行之間的毫秒級速率或cron表達(dá)式來觸發(fā),以實現(xiàn)無法用前者表達(dá)的更佳時序。 對于需要非常頻繁運行的任務(wù),使用fixedRate或fixedDelay屬性就足夠了,但是一旦執(zhí)行之間的時間變大,則很難快速確定所定義的時間。 發(fā)生這種情況時,應(yīng)使用cron屬性以更好地了解計劃的時間。
這篇文章中使用的少量代碼可以在我的GitHub上找到 。
如果您發(fā)現(xiàn)這篇文章很有幫助,并希望在我撰寫新教程時保持最新,請在Twitter上@LankyDanDev關(guān)注我。
翻譯自: https://www.javacodegeeks.com/2018/02/running-time-springs-scheduled-tasks.html
總結(jié)
以上是生活随笔為你收集整理的与Spring的计划任务一起按时运行的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 三星bada系统手机(三星bada系统手
- 下一篇: 80手机电影网 80s手机电影网站下载的