“每隔几分钟执行一个任务”这种需求,几乎在每个项目里都有可能遇到。Spring框架提供了一种简单的方式来完成这一需求。你只需要在定时执行的方法上加上注解就行了。
首先你需要开启这一功能:在任何一个 @Configuration
类上添加上 @EnableScheduling
注解:
这个 @EnableScheduling
注解,是放在 Spring框架 的 spring-context
模块,它比较基础,同时也被Spring Boot所依赖,所以不需要引入额外的库。
然后在你的组件中,创建需要定时执行的方法,并添加 @Scheduled
注解。下图演示了两种定时任务的写法,他们两个都是“每隔10秒钟”执行一个任务,但是稍稍有些区别。 fixedRate
参数表明前后两次任务的 开始时间 相差10秒, fixedDelay
参数表明前一次任务 结束时间 和后一次的 开始之间 相差10秒。
对于以上两种方式,你还可以添加 initialDelay
参数,等程序启动一段时间之后,再开始跑定时任务。
另外,三个参数 fixedRate
, fixedDelay
和 initialDelay
都是long类型,都表示毫秒,你还可以用更易读的方式来传递时间,使用 fixedRateString
、 fixedDelayString
或 initialDelayString
参数,传递表示时间长度的字符串。他们的格式为 PnDTnHnMn.nS
,其中的n替换为数字,使用方法如下:
表示时间长度的字符串在框架里最终会被解析成 java.time.Duration
对象,感兴趣的可以去看看 Duration
的介绍和源码等。
还有一种需求,不太好描述,比如“每天晚上2点备份数据”这种操作,用上面介绍的方法不太好计算 initialDelay
,不过如果你用过cron或者crontab命令写过定时任务的话,应该知道这类需求是比较好描述的。考虑到这种情况, @Scheduled
还提供了 cron
参数,可以使用类似的语法描述任务的时间。
cron参数一点一点解释挺麻烦的,不如直接看怎么用:
0 0 * * * * */10 * * * * * 0 0 8-10 * * * 0 0 6,19 * * * 0 0/30 8-10 * * * 0 0 9-17 * * MON-FRI
空格把字符串分成六个部分,分别表示秒,分,时,日,月,星期。包含数字和符号:
*
表示“所有,每个”, -
表示“区间” ,
表示“列表”。 /
表示序列,左侧为开始时间,右侧为步长 ?
表示“每个可能的时间”,话说我也没搞懂这个的作用,如果你想搞懂的话不妨搜索下“ cron question mark ” 一旦当前时间匹配了cron字符串,你的任务就会执行。写完字符串之后,记得加个注释,告诉你的朋友或者同事是啥意思,并不是每个人都看的清楚,甚至你自己过了几个月之后也看不懂了。更多相关内容你可以查看 CronSequenceGenerator
类的源码。
注意,这种定时任务的使用方式只适用于单机的情况,如果你的项目是分布式的,每个机器上程序运行的时候都会有一套定时操作,跑起来肯定乱套了。此类需求可以用Quartz来实现。