其实cron表达式呢,其实就是一个基于字符串的,基于时间的一个定义格式,那我们就来看一下cron表达式语法
的定义,cron表达式它是一个字符串的,并且在字符串当中呢,包含6个域或者7个域,然后每个域表示的含义也不同,
我们来看一下他的基本语法,语法上有两种格式,这个是7个域的格式,这个是6个域的格式,每个域当中表示的是
什么呢,从左至右,分别为秒 分钟,小时,天,月,星期和年,那么第二种语法格式呢,就是比第一个格式少了一个年,
然后我们在这个案例当中,用的就是6个域的表现形式,而且这里我推荐大家使用6个域的表现形式,为什么这么说呢,
因为cron的表达式,他不仅可以在Schedule的定时器当中,在其他的定时任务技术当中,他也有对cron表达式的一个支持,
而有一些定时任务器,他的要求是6个域的表现形式,你给他7个域反而报错,所以这里我们使用6个域的就够了,我们看一下
每个字段允许的值是什么,第一个位置秒,这个位置允许添加的值就是0到59,表示60秒,然后包含0到59,如果给的值超过了
允许值,是什么样的呢,比如说在我这个案例当中,我把秒改成60,然后我们来运行我们这个程序,观察控制台,马上会得到
一个异常
@Scheduled(cron="60 * * * * ?")
public void scheduledMethod(){
System.out.println("定时器被触发"+new Date());
}
这个异常说的很清楚了
Initialization of bean failed; nested exception is java.lang.IllegalStateException:
Encountered invalid @Scheduled method 'scheduledMethod':
Range exceeds maximum (60): '60' in expression "60 * * * * ?"
在我当前的表达式当中,所给出的值已经超出了他的最大范围,在我这个表达式当中,所以这个值还是不能够随便乱填的,
所以我们填的就是0到59的一个范围,那这里我们填一个3,这表示什么含义呢,
@Scheduled(cron="3 * * * * ?")
public void scheduledMethod(){
System.out.println("定时器被触发"+new Date());
}
这个表示第三秒钟,秒后面是分钟,这个*号表示任意的,那就是每分钟的第三秒,就是每分钟的第三秒去执行这个方法,不是
每隔3秒,注意不是每隔3秒,是每分钟的第三秒,我们再往下看,分钟也就是我们的第二个域,分钟允许填的值也是0到59范围内的,
来表示60分钟,比如我这里写一个50
@Scheduled(cron="3 50 * * * ?")
public void scheduledMethod(){
System.out.println("定时器被触发"+new Date());
}
就是50分第3秒,去执行这个,咱们再往下看,除了有分钟以外,第三个域,是小时,小时的取值范围是0到23,那么也就是说,
它是采用了24时制的时间,对于小时的表现格式,0就是我们凌晨的12点,然后23就是晚上的11点,比如说,第三个域是小时,
我给一个18,这表示什么意思呢,表示6点50分第3秒会触发这个方法
@Scheduled(cron="3 50 18 * * ?")
public void scheduledMethod(){
System.out.println("定时器被触发"+new Date());
}
除了小时以后呢,第四个就是我们的天,就是我们的日,他的取值范围是1到31号,这里有一个地方需要我们注意,
比如我们这里写一个31
@Scheduled(cron="3 50 18 31 * ?")
public void scheduledMethod(){
System.out.println("定时器被触发"+new Date());
}
其实我们知道的,并不是每一个月份都有31号,比如像2月份,有可能是28,也有可能是29,然后像小月的,比如像4月份,
他就到30号,那如果我这个写了31号,会表示什么含义呢,其实日还要配合着下一个参数,月,我现在这个月给定的是31号,
表示任意一月,在任意月当中,如果这个月有31号,那就在这个月的31号6点50分第3秒,来执行这个方法,来触发这个方法,
如果这块我写2呢
@Scheduled(cron="3 50 18 31 2 ?")
public void scheduledMethod(){
System.out.println("定时器被触发"+new Date());
}
很显然这是不对的,2月份哪有31号,那如果我非要这么写,会是一个什么样的结果呢,我们来运行一下
这个时候你发现你又得到一个异常了
java.lang.IllegalArgumentException: Invalid cron expression "3 50 18 31 2 ?" led to runaway search
for next trigger
然后这个异常里说什么呢,它是一个无效的cron表达式,因为在这个表达式当中,他永远都不会被触发,也就是2月份
当中没有31号的,你给的表达式要我在2月31号去触发,怎么给你触发,所以这块也是有问题的,那么我们在定义天的时候,
一定要注意他跟月是有关系的,如果我要这么写呢
@Scheduled(cron="3 50 18 15 2 ?")
public void scheduledMethod(){
System.out.println("定时器被触发"+new Date());
}
这就没有什么问题的,这表示什么呢,2月15号6点50分03秒,来触发这个方法,这是可以的,然后我们再往下看,现在我们把月说完了,
还有一个是星期,星期他的取值范围是1到7,这里有一个地方需要注意的是,这个1并不是表示星期一,你像美国人,他的每一个星期的
起始的日期,都用的星期日,那么他的1就表示星期日,作为一周的开始,然后7则表示星期六,作为一周的结束,这里要给的话要注意,
在给定星期的时候呢,还有一个地方需要注意,比如这块我给一个4
@Scheduled(cron="3 50 18 15 2 4")
public void scheduledMethod(){
System.out.println("定时器被触发"+new Date());
}
这表示什么,这表示的是星期三,那么其实这个时间格式也是会有问题的,什么问题呢,在2月份当中,他的星期四,他并不一定是
15号,所以星期和日是有冲突的,所以我们一般来做这个定义的时候,我们一般是舍弃一个,如果把它舍掉就表示2月15号
@Scheduled(cron="3 50 18 15 2 ?")
如果这个是问号,则表示2月份的每个星期四
@Scheduled(cron="3 50 18 ? 2 14")
2月份的每个星期四的6点50分03秒,来触发我这个方法,问号其实就是表示一个占位,你舍弃谁,就用一个问号占位就可以了,
日和星期在某种程度上,它是有冲突的,一般都会选择一个,接下来再看这个年,年我们一般就不去给定了,我们用的是6个域的
表现形式,你要给也没问题,但是要注意的就是,如果我们给年的话,他的取值是1970年到2099年的范围,那么我们就讲了每个
取名的一个定义,我们在每个域里面还可以写特殊符号,比如我们可以写星号,星号什么意思呢,可以用在所有字段中,表示对应
时间的每一个时刻,就是任意一个,例如在*/字段上,就是表示每分钟,
@Scheduled(cron="3 50 18 * 2 ?")
public void scheduledMethod(){
System.out.println("定时器被触发"+new Date());
}
就是2月份当中的任意一天,每一天的6点50分03秒,来触发这个方法,那如果我把50换乘*呢
@Scheduled(cron="3 * 18 * 2 ?")
public void scheduledMethod(){
System.out.println("定时器被触发"+new Date());
}
那就表示2月份的每一天的6点的每一分钟的第三秒去触发这个方法,这个就很好理解,除了有分号以外呢,还有问号,
问号我们已经用过了,问号其实就是表示一个单位,他通常指定为无意义的值,相当于占位符,我们再来看减号,就是我们
的连字符,减号他表示的就是一个范围,比如我先在是每分钟的第三秒,我现在改成10-15
@Scheduled(cron="10-15 * 18 * 2 ?")
public void scheduledMethod(){
System.out.println("定时器被触发"+new Date());
}
这是什么意思呢,就是每分钟的10到15秒内,那就是执行5次,应该执行5次,他表示的是一个范围,还有一个逗号,
逗号表示的是什么呢,是一个列表值,比如我把10-15改成逗号
@Scheduled(cron="10,15 * 18 * 2 ?")
public void scheduledMethod(){
System.out.println("定时器被触发"+new Date());
}
这表示的是2月份的每一天的6点每分钟的,第10秒钟和第15秒钟,去触发这个方法,然后还有一个斜线,斜线是我们刚才用过的,
@Scheduled(cron="0/2 * 18 * 2 ?")
public void scheduledMethod(){
System.out.println("定时器被触发"+new Date());
}
0/2表示什么意思呢,表示一个等步长序列,从几开始,他的增长量是多少,我这个案例,是从第0秒开始,每2秒执行一次,
说白了就是间隔两秒,直接给个2不是间隔两秒
@Scheduled(cron="2 * 18 * 2 ?")
public void scheduledMethod(){
System.out.println("定时器被触发"+new Date());
}
这个是每分钟的第二秒去执行,那其实对于cron的表示式还是比较简单的,下面还有其他的特殊字符的一个使用,
这里就不说了,自己去看一下,我们再来看一个案例,来做一个cron表达式的一个总结,
@Scheduled(cron="0 0 1 1 1 ?")
在这个Schedule当中加了一个cron表达式,这表示什么意思呢,每年的1月份的1日1点去触发这个方法,表示的就是每天的1月1号的1点
去触发这个方法
@Scheduled(cron="0 0 1 1 1,6 ?")
这个表示每天的1月和6月的1号的1点去触发他
@Scheduled(cron="0 0 1 1 1,4,7,10 ?")
月份是1月份,4月份,7月份,10月份,其实就是一个季度,表达式就是每个季度的第一个月份的1号的1点去执行一次
@Scheduled(cron="0 0 1 1 * ?")
每一个月的1号1点去执行一次
@Scheduled(cron="0 0 1 * * *")
每天的凌晨1点,执行一次,所以这个还是比较简单