Spring的定时任务的相关支持是存放在Spring-context.jar中的,默认是关闭状态,使用的话记得开启。
开启定时任务
使用注解@EnableScheduling 即可开启
各方式说明
这里我们使用@Scheduled的方式进行讲解。默认提供了fixedDelay,fixedRate,cron
参阅源代码:
public @interface Scheduled {
String cron() default "";
long fixedDelay() default -1L;
String fixedDelayString() default "";
long fixedRate() default -1L;
String fixedRateString() default "";
long initialDelay() default -1L;
String initialDelayString() default "";
}
fixedDelay
固定延迟,在延迟一段时间后执行定时任务,并不是从定时任务加载后立刻执行。
示例
以下任务是在五秒后开始执行定时任务,并且每五秒执行一次。默认单位是毫秒(后续不在说明,基本都是毫秒)
@Scheduled(fixedDelay=5000)
public void doSomething() {
// something that should execute periodically
}
fixedRate
固定速率执行定时任务,从启动就开始执行,即启动的时候会立刻执行一次。也可以通过参数(initialDelay )进行调整
示例
以下任务自启动开始立刻执行一次,之后每5秒执行一次。
@Scheduled(fixedRate=5000)
public void doSomething() {
// something that should execute periodically
}
以下任务自启动开始,延迟一秒后执行一次,之后每5秒执行一次。
@Scheduled(initialDelay=1000, fixedRate=5000)
public void doSomething() {
// something that should execute periodically
}
cron
Spring 中也支持Cron格式的定时任务,但是切记Spring做了简化,以及优化,与纯cron是有些差异的。以下后给出说明。
- 解析类:CronSequenceGenerator
/**
* 解析给定的表达式
与纯cron表达式相比,Spring中只支持6位的形式(没有年份的选项)。需要特别注意。
*/
private void parse(String expression) throws IllegalArgumentException {
String[] fields = StringUtils.tokenizeToStringArray(expression, " ");
//判断cron位数
if (!areValidCronFields(fields)) {
throw new IllegalArgumentException(String.format(
"Cron expression must consist of 6 fields (found %d in \"%s\")", fields.length, expression));
}
//设置第一位秒
setNumberHits(this.seconds, fields[0], 0, 60);
//设置第2位分钟
setNumberHits(this.minutes, fields[1], 0, 60);
//设置第3位小时
setNumberHits(this.hours, fields[2], 0, 24);
//设置第4位天
setDaysOfMonth(this.daysOfMonth, fields[3]);
//设置第5位月
setMonths(this.months, fields[4]);
//设置第6位星期
setDays(this.daysOfWeek, replaceOrdinals(fields[5], "SUN,MON,TUE,WED,THU,FRI,SAT"), 8);
if (this.daysOfWeek.get(7)) {
// 星期天可以是0或者7 也就是说 Spring的星期是从0开始,1对应星期一,2对应星期2,依次类推
this.daysOfWeek.set(0);
this.daysOfWeek.clear(7);
}
}
示例
以下示例标示工作日内,每五秒执行一次任务。
@Scheduled(cron="*/5 * * * * MON-FRI")
public void doSomething() {
// something that should execute on weekdays only
}
关于Cron表达式
而且cron一般被用在CronTrigger或者其子类org.quartz.Trigger。cron一般为6位,特殊情况下会是7位。相互直接以空格分割,允许的字符参阅下面的列表。
名称 | 必选项 | 允许值 | 允许特殊字符 |
---|---|---|---|
Seconds | Y | 0-59 | , - * / |
Minutes | Y | 0-59 | , - * / |
Hours | Y | 0-23 | , - * / |
Day of month | Y | 1-31 | , - * ? / L W C |
Month | Y | 0-11 or JAN-DEC | , - * / |
Day of week | Y | 1-7 or SUN-SAT | , - * ? / L C # |
Year | N | empty or 1970-2099 | , - * / |
特殊字符含义说明
(*)星号:
可以理解为每的意思,每秒,每分,每天,每月,每年…(?)问号:问号只能出现在日期和星期这两个位置,表示这个位置的值不确定,每天3点执行,所以第六位星期的位置,我们是不需要关注的,就是不确定的值。同时:日期和星期是两个相互排斥的元素,通过问号来表明不指定值。比如,1月10日,比如是星期1,如果在星期的位置是另指定星期二,就前后冲突矛盾了。
(-)减号:表达一个范围,如在小时字段中使用“10-12”,则表示从10到12点,即10,11,12
(,)逗号:表达一个列表值,如在星期字段中使用“1,2,4”,则表示星期一,星期二,星期四
(/)斜杠:如:x/y,x是开始值,y是步长,比如在第一位(秒) 0/15就是,从0秒开始,每15秒,最后就是0,15,30,45,60 另:*/y,等同于0/y
(L):表示最后,比如表示每个月的最后一天等
- (W):表示工作日,比如15W表示当月第15个工作日。
- (C):表示日历, 比如2C,在月份中表示日历中的第二天,如果在星期上,则表示第一个星期一或者日历中的每一个星期一
- (#):用于指定”第 n 个”XXX 天的月份。例如,值为”6 #3”在一天的星期字段中意味着”每月的第三个星期五”(第 6 天 = 周五和”#3”= 该月份的第 3 名)
cron示例
表达式 | 意义 |
---|---|
0 0 12 * * ? | 触发在 12 下午 (中午) 每一天 |
0 15 10?* * | 触发在 10:15 上午每一天 |
0 15 10 * *? | 触发在 10:15 上午每一天 |
0 15 10 * ? | 触发在 10:15 上午每一天 |
0 15 10 * *?2005 | 触发在 10:15 上午在 2005 年期间的每一天 |
0 * 14 * *? | 触发在 2 下午开始和结束于 2:59 下午,每一天每一分钟 |
0 0/5 14 * *? | 触发在 2 下午开始和结束于 2:55 下午,每一天每隔 5 分钟 |
0 0/5 14,18 * * ? | 触发在 2 下午开始和结束于 2:55 下午,每隔 5 分钟和触发在 6 下午开始和结束于 6:55 下午,每一天每隔 5 分钟 |
0 0 5 14 * *? | 触发在 2 下午开始和结束于 2:05 下午,每一天每一分钟 |
0 10,44 14?3 WED | 触发在 2:10 下午和 2:44 下午每周三在 3 月份。 |
0 15 10?* MON-FRI | 触发在 10:15 上午,每个星期一、 星期二、 星期三、 星期四和星期五 |
0 15 10 15 * ? | 触发在 10:15 上午每月 15 日 |
0 15 10 L *? | 触发在 10:15 上午对每月的最后一天 |
0 15 10?* 6 L | 触发在 10:15 上午对每月的最后一个星期五 |
0 15 10?* 6 L | 触发在 10:15 上午对每月的最后一个星期五 |
0 15 10?* 6 L 2002-2005 | 触发在 10:15 上午在 2002年、 2003年、 2004 年和 2005 年每月每上星期五 |
0 15 10?* 6 #3 | 触发在 10:15 上午上每个月第三个星期五 |
0 0 12 1/5 *? | 触发在 12 下午 (中午) 每隔 5 天每个月,每月的第一天开始。 |
0 11 11 11 11 ? | 触发在 11:11 上午每 11 月 11 日。 |
最后
作者:ricky
QQ交流群:244930845