领先一步
VMware 提供培训和认证,以加快您的进度。
了解更多如果您经常收听A Bootiful Podcast,您可能已经听说过我们对 Spring Framework 的 cron 支持所做的改进。Cron 表达式主要通过@Scheduled
注解在 Spring 应用程序中使用。在 Spring 5.3 中,我们引入了CronExpression
类,它表示——您猜对了——一个cron 表达式。
CronExpression
替换了基于java.util.Calendar
的CronSequenceGenerator
,后者存在一些已知问题,Spring 团队成员都不愿意解决这些问题。引入新的类型使我们能够使用更优秀的java.time
API,解决未解决的问题,并(希望)引入新功能。虽然 Spring 通常更倾向于保持向后兼容性,但有时我们确实认为从头开始是最佳选择。
从 Spring Framework 5.3 开始,您通常使用@Scheduled
注解创建 cron 触发器,该注解内部使用CronExpression
。这意味着如果您使用的是该版本,您已经可以开始使用新功能。
如果您想自己尝试CronExpression
,可以通过静态解析方法创建一个。
var expression = CronExpression.parse("10 * * * * *");
var result = expression.next(LocalDateTime.now());
System.out.println(result);
在这个示例中,expression
表示一个每分钟触发 10 秒后的 cron 序列。parse
方法接受一个众所周知的字符串,其中包含六个用空格分隔的时间和日期字段。
┌───────────── 秒 (0-59) │ ┌───────────── 分钟 (0-59) │ │ ┌───────────── 小时 (0-23) │ │ │ ┌───────────── 月份中的天 (1-31) │ │ │ │ ┌───────────── 月份 (1-12) (或 JAN-DEC) │ │ │ │ │ ┌───────────── 星期几 (0-7) │ │ │ │ │ │ (或 MON-SUN -- 0 或 7 为星期日) │ │ │ │ │ │ * * * * * *
有一些规则适用
一个字段可以是一个星号 (*
),它总是代表“首尾”。对于月份中的天或星期几字段,可以使用问号 (?
) 代替星号。
逗号 (,
) 用于分隔列表项。
用连字符 (-
) 分隔的两个数字表示一个数字范围。指定的范围是包含性的。
在范围(或*
)之后加上/
指定该范围内数字值的间隔。
月份中的天和星期几字段也可以使用英文名称。使用特定日期或月份的前三个字母(大小写无关)。
以下是一些示例
Cron 表达式
含义
0 0 * * * *
每天每小时的顶部
*/10 * * * * *
每十秒
0 0 8-10 * * *
每天 8 点、9 点和 10 点
0 0 6,19 * * *
每天早上 6:00 和晚上 7:00
0 0/30 8-10 * * *
每天 8:00、8:30、9:00、9:30、10:00 和 10:30
0 0 9-17 * * MON-FRI
工作日 9 点到 17 点整点
0 0 0 25 12 ?
每年圣诞节午夜
next
方法返回触发器的下一次出现,如果不存在则返回null
。它接受java.time.temporal.Temporal
作为参数,这意味着它不仅接受LocalDateTime
,而且如果时区相关,也接受ZonedDateTime
。
使用java.time
API,我们可以引入一些新功能,使 Spring 对 cron 表达式的支持与其他调度程序一样。从 Spring Framework 5.3 开始,您可以在@Scheduled
中使用这些功能。
诸如0 0 * * * *
之类的表达式对于人类来说难以解析,因此,如果出现错误,也很难修复。为了提高可读性,Spring 现在支持以下宏,它们代表常用的序列。您可以使用这些宏代替六位数字的值,例如:@Scheduled(cron = "@hourly")
。
宏
含义
@yearly
(或@annually
)
每年一次 (0 0 0 1 1 *
)
@monthly
每月一次 (0 0 0 1 * *
)
@weekly
每周一次 (0 0 0 * * 0
)
@daily
(或@midnight
)
每天一次 (0 0 0 * * *
),或
@hourly
每小时一次 (0 0 * * * *
)
月份中的天和星期几字段可以包含L
字符,它在每个字段中的含义不同。在月份中的天字段中,L
代表*月份的最后一天*。如果后面跟着负偏移量(即L-n
),则表示*月份的倒数第n
天*。
在星期几字段中,L
代表*一周的最后一天*。如果前面带有数字或三个字母的名称(dL
或DDDL
),则表示*该月星期几(d
或DDD
)的最后一天*。
以下是一些示例
Cron 表达式
含义
0 0 0 L * *
每月最后一天午夜
0 0 0 L-3 * *
每月倒数第三天午夜
0 0 0 * * 5L
每月最后一个星期五午夜
0 0 0 * * THUL
每月最后一个星期四午夜
月份中的天字段可以是nW
,它代表*最接近月份第n
天的工作日*。如果n
落在星期六,则产生它之前的星期五。如果n
落在星期日,则产生它之后的星期一,如果n
是1
并且落在星期六,也会发生这种情况(即:1W
代表*该月的第一个工作日*)。
如果月份中的天字段是LW
,则表示*该月的最后一个工作日*。
以下是一些示例
Cron 表达式
含义
0 0 0 1W * *
每月第一个工作日午夜
0 0 0 LW * *
每月最后一个工作日午夜
星期几字段可以是d#n
(或DDD#n
),它代表*该月星期几(d
或DDD
)的第n
天*。
以下是一些示例
Cron 表达式
含义
0 0 0 ? * 5#2
该月第二个星期五午夜
0 0 0 ? * MON#1
该月第一个星期一午夜
改进的 cron 表达式支持只是Spring Framework 5.3 提供的众多功能 之一,并将成为即将发布的Spring Boot 2.4 版本的一部分。