@[TOC](@Scheduled(cron = “* * * * * *”) cron表達式通過占位符替代/設置永久不執行)
1.通過占位符寫法
2.設置永久不執行
2.1設置成去年,讓其不執行
報錯:
Caused by: java.lang.IllegalStateException: Encountered invalid @Scheduled method 'startDataCollect': Range exceeds maximum (8): '2019' in expression "* * * * * 2019"
at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.processScheduled(ScheduledAnnotationBeanPostProcessor.java:496)
at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.lambda$null$1(ScheduledAnnotationBeanPostProcessor.java:359)
at java.lang.Iterable.forEach(Iterable.java:75)
at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.lambda$postProcessAfterInitialization$2(ScheduledAnnotationBeanPostProcessor.java:359)
at java.util.LinkedHashMap.forEach(LinkedHashMap.java:684)
at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.postProcessAfterInitialization(ScheduledAnnotationBeanPostProcessor.java:358)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:429)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1766)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:593)
... 15 common frames omitted
原因:第7位參數為年份,第六位代表星期(1-7)
cron表達式格式: {秒數} {分鍾} {小時} {日期} {月份} {星期} {年份(可為空)}
秒 :可以用數字0-59 表示;
分 :可以用數字0-59 表示;
時:可以用數字0-23表示;
天:可以用數字1-31 中的任一一個值,但要注意一些特別的月份2月份沒有只能1-28,有些月份沒有31;
月:可以用0-11 或用字符串 “JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV and DEC” 表示;
周:可以用數字1-7表示(1 = 星期日)或用字符口串"SUN, MON, TUE, WED, THU, FRI and SAT"表示;
“-”:區間連接,0-10 * * * * 表示0-10秒的時候執行
“,”:多個時間點,0,10 * * * * * 表示0和10秒的時候執行
“/”:為特別單位,表示為"每"如"0/10"表示每隔10分鍾執行一次,“0"表示為從"0"分開始, “3/20"表示表示每隔20分鍾執行一次,“3"表示從第3分鍾開始執行;
“?”:表示每月的某一天,或第周的某一天;
“L”:用於每月,或每周,表示為每月的最后一天,或每個月的最后星期幾如"6L"表示"每月的最后一個星期五”;
“W”:表示為最近工作日,如"15W"放在每月(day-of-month)字段上表示為"到本月15日最近的工作日”;
“#”:是用來指定"的"每月第n個工作日,例 在每周(day-of-week)這個字段中內容為"6#3” or “FRI#3” 則表示"每月第三個星期五";
“*” 代表整個時間段。
2.2改成7個參數,最后一位放年份
依然報錯:
Caused by: java.lang.IllegalStateException: Encountered invalid @Scheduled method 'startDataCollect': Cron expression must consist of 6 fields (found 7 in "* * * * * * 2019")
at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.processScheduled(ScheduledAnnotationBeanPostProcessor.java:496)
at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.lambda$null$1(ScheduledAnnotationBeanPostProcessor.java:359)
at java.lang.Iterable.forEach(Iterable.java:75)
at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.lambda$postProcessAfterInitialization$2(ScheduledAnnotationBeanPostProcessor.java:359)
at java.util.LinkedHashMap.forEach(LinkedHashMap.java:684)
at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.postProcessAfterInitialization(ScheduledAnnotationBeanPostProcessor.java:358)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:429)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1766)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:593)
... 15 common frames omitted
原因:Spring3.0的版本后,cron表達式只能支持6個字段
2.3設置成不存在的日期,比如9月31號
報錯:
2021-10-11 11:35:41.590 [main] ERROR org.springframework.boot.SpringApplication - Application run failed
java.lang.IllegalArgumentException: Invalid cron expression "* * * 31 9 *" led to runaway search for next trigger
at org.springframework.scheduling.support.CronSequenceGenerator.doNext(CronSequenceGenerator.java:201)
at org.springframework.scheduling.support.CronSequenceGenerator.doNext(CronSequenceGenerator.java:194)
at org.springframework.scheduling.support.CronSequenceGenerator.doNext(CronSequenceGenerator.java:204)
at org.springframework.scheduling.support.CronSequenceGenerator.doNext(CronSequenceGenerator.java:194)
at org.springframework.scheduling.support.CronSequenceGenerator.doNext(CronSequenceGenerator.java:204)
at org.springframework.scheduling.support.CronSequenceGenerator.doNext(CronSequenceGenerator.java:194)
at org.springframework.scheduling.support.CronSequenceGenerator.doNext(CronSequenceGenerator.java:204)
at org.springframework.scheduling.support.CronSequenceGenerator.doNext(CronSequenceGenerator.java:194)
at org.springframework.scheduling.support.CronSequenceGenerator.doNext(CronSequenceGenerator.java:204)
at org.springframework.scheduling.support.CronSequenceGenerator.doNext(CronSequenceGenerator.java:194)
at org.springframework.scheduling.support.CronSequenceGenerator.next(CronSequenceGenerator.java:148)
at org.springframework.scheduling.support.CronTrigger.nextExecutionTime(CronTrigger.java:87)
at org.springframework.scheduling.concurrent.ReschedulingRunnable.schedule(ReschedulingRunnable.java:75)
at org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler.schedule(ThreadPoolTaskScheduler.java:313)
at org.springframework.scheduling.config.ScheduledTaskRegistrar.scheduleCronTask(ScheduledTaskRegistrar.java:414)
at org.springframework.scheduling.config.ScheduledTaskRegistrar.scheduleTasks(ScheduledTaskRegistrar.java:352)
at org.springframework.scheduling.config.ScheduledTaskRegistrar.afterPropertiesSet(ScheduledTaskRegistrar.java:332)
at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.finishRegistration(ScheduledAnnotationBeanPostProcessor.java:300)
at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.onApplicationEvent(ScheduledAnnotationBeanPostProcessor.java:231)
at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.onApplicationEvent(ScheduledAnnotationBeanPostProcessor.java:103)
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:402)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:359)
at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:896)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.finishRefresh(ServletWebServerApplicationContext.java:163)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:552)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:142)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:316)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248)
at com.copote.data.manager.metabase.api.MetabaseApplication.main(MetabaseApplication.java:26)
原因:CronSequenceGenerator的doNext算法從指定時間開始(包括指定時間)查找符合cron表達式規則下一個匹配的時間。匹配不到拋異常
2.4日期范圍(1-31),設置成0,不報錯,不執行
報錯:
2021-10-11 11:42:04.364 [main] ERROR org.springframework.boot.SpringApplication - Application run failed
java.lang.IllegalArgumentException: Overflow in day for expression "* * * 0 * *"
at org.springframework.scheduling.support.CronSequenceGenerator.findNextDay(CronSequenceGenerator.java:223)
at org.springframework.scheduling.support.CronSequenceGenerator.doNext(CronSequenceGenerator.java:189)
at org.springframework.scheduling.support.CronSequenceGenerator.next(CronSequenceGenerator.java:148)
at org.springframework.scheduling.support.CronTrigger.nextExecutionTime(CronTrigger.java:87)
at org.springframework.scheduling.concurrent.ReschedulingRunnable.schedule(ReschedulingRunnable.java:75)
at org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler.schedule(ThreadPoolTaskScheduler.java:313)
at org.springframework.scheduling.config.ScheduledTaskRegistrar.scheduleCronTask(ScheduledTaskRegistrar.java:414)
at org.springframework.scheduling.config.ScheduledTaskRegistrar.scheduleTasks(ScheduledTaskRegistrar.java:352)
at org.springframework.scheduling.config.ScheduledTaskRegistrar.afterPropertiesSet(ScheduledTaskRegistrar.java:332)
at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.finishRegistration(ScheduledAnnotationBeanPostProcessor.java:300)
at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.onApplicationEvent(ScheduledAnnotationBeanPostProcessor.java:231)
at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.onApplicationEvent(ScheduledAnnotationBeanPostProcessor.java:103)
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:402)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:359)
at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:896)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.finishRefresh(ServletWebServerApplicationContext.java:163)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:552)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:142)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:316)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248)
at com.copote.data.manager.metabase.api.MetabaseApplication.main(MetabaseApplication.java:26)
原因同4
3.討論
Linux 的crontab未嘗試上面方法,不知是否可行,使用的springboot 5.1.5試了幾種方法都不行,實際運用中如果永久停,代碼肯定要拿掉,所以不再糾結了,有懂的歡迎執教!
4.其它
scheluer 源碼
/*
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.scheduling.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* An annotation that marks a method to be scheduled. Exactly one of
* the {@link #cron()}, {@link #fixedDelay()}, or {@link #fixedRate()}
* attributes must be specified.
*
* <p>The annotated method must expect no arguments. It will typically have
* a {@code void} return type; if not, the returned value will be ignored
* when called through the scheduler.
*
* <p>Processing of {@code @Scheduled} annotations is performed by
* registering a {@link ScheduledAnnotationBeanPostProcessor}. This can be
* done manually or, more conveniently, through the {@code <task:annotation-driven/>}
* element or @{@link EnableScheduling} annotation.
*
* <p>This annotation may be used as a <em>meta-annotation</em> to create custom
* <em>composed annotations</em> with attribute overrides.
*
* @author Mark Fisher
* @author Juergen Hoeller
* @author Dave Syer
* @author Chris Beams
* @since 3.0
* @see EnableScheduling
* @see ScheduledAnnotationBeanPostProcessor
* @see Schedules
*/
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(Schedules.class)
public @interface Scheduled {
/**
* A special cron expression value that indicates a disabled trigger: {@value}.
* <p>This is primarily meant for use with ${...} placeholders, allowing for
* external disabling of corresponding scheduled methods.
* @since 5.1
*/
String CRON_DISABLED = "-";
/**
* A cron-like expression, extending the usual UN*X definition to include triggers
* on the second as well as minute, hour, day of month, month and day of week.
* <p>E.g. {@code "0 * * * * MON-FRI"} means once per minute on weekdays
* (at the top of the minute - the 0th second).
* <p>The special value {@link #CRON_DISABLED "-"} indicates a disabled cron trigger,
* primarily meant for externally specified values resolved by a ${...} placeholder.
* @return an expression that can be parsed to a cron schedule
* @see org.springframework.scheduling.support.CronSequenceGenerator
*/
String cron() default "";
/**
* A time zone for which the cron expression will be resolved. By default, this
* attribute is the empty String (i.e. the server's local time zone will be used).
* @return a zone id accepted by {@link java.util.TimeZone#getTimeZone(String)},
* or an empty String to indicate the server's default time zone
* @since 4.0
* @see org.springframework.scheduling.support.CronTrigger#CronTrigger(String, java.util.TimeZone)
* @see java.util.TimeZone
*/
String zone() default "";
/**
* Execute the annotated method with a fixed period in milliseconds between the
* end of the last invocation and the start of the next.
* @return the delay in milliseconds
*/
long fixedDelay() default -1;
/**
* Execute the annotated method with a fixed period in milliseconds between the
* end of the last invocation and the start of the next.
* @return the delay in milliseconds as a String value, e.g. a placeholder
* or a {@link java.time.Duration#parse java.time.Duration} compliant value
* @since 3.2.2
*/
String fixedDelayString() default "";
/**
* Execute the annotated method with a fixed period in milliseconds between
* invocations.
* @return the period in milliseconds
*/
long fixedRate() default -1;
/**
* Execute the annotated method with a fixed period in milliseconds between
* invocations.
* @return the period in milliseconds as a String value, e.g. a placeholder
* or a {@link java.time.Duration#parse java.time.Duration} compliant value
* @since 3.2.2
*/
String fixedRateString() default "";
/**
* Number of milliseconds to delay before the first execution of a
* {@link #fixedRate()} or {@link #fixedDelay()} task.
* @return the initial delay in milliseconds
* @since 3.2
*/
long initialDelay() default -1;
/**
* Number of milliseconds to delay before the first execution of a
* {@link #fixedRate()} or {@link #fixedDelay()} task.
* @return the initial delay in milliseconds as a String value, e.g. a placeholder
* or a {@link java.time.Duration#parse java.time.Duration} compliant value
* @since 3.2.2
*/
String initialDelayString() default "";
}
1.cron:cron表達式,指定任務在特定時間執行;
2.fixedDelay:表示上一次任務執行完成后多久再次執行,參數類型為long,單位ms;
3.fixedDelayString:與fixedDelay含義一樣,只是參數類型變為String;
4.fixedRate:表示按一定的頻率執行任務,參數類型為long,單位ms;
5.fixedRateString: 與fixedRate的含義一樣,只是將參數類型變為String;
6.initialDelay:表示延遲多久再第一次執行任務,參數類型為long,單位ms;
7.initialDelayString:與initialDelay的含義一樣,只是將參數類型變為String;
8.zone:時區,默認為當前時區,一般沒有用到。