Spring Cron 格式
Spring 表达式有六个字段:秒、分钟、小时、日、月和星期,例如 0 0 9 * * MON-FRI 表示工作日 09:00。星期日可以写成 0、7 或 SUN。从 Spring Framework 5.3 起,解析器还支持日期字段中的 L、W 和 #,以及 @hourly、@daily 等宏。
@Scheduled 的时区
默认情况下,表达式按服务器的默认时区计算。设置 zone 属性,例如 @Scheduled(cron = "0 0 2 * * *", zone = "Asia/Shanghai"),可以让调度与主机无关。在工具中选择相同时区即可预览运行时间。
Spring 与 Quartz 的区别
Spring 表达式看起来和 Quartz 很像,但细节不同:没有年字段,星期日是 0 而不是 1,“?”可以使用但不是必需的。当“日”和“星期”都有限定时,Spring 要求两者同时匹配。若存在等价写法,转换器会给出 Quartz 版本。
启用调度
只有用 @EnableScheduling 开启调度后,cron 方法才会运行。Spring 默认只使用一个线程,长任务会拖慢其他所有定时方法;如果有多个任务,请配置 ThreadPoolTaskScheduler 或 spring.task.scheduling.pool.size。在集群中每个实例都会触发同一个 cron,如果任务只能运行一次,请使用 ShedLock 之类的锁。
常见问题
- 为什么 Spring 提示 Cron 表达式必须有六个字段?
- Spring 需要秒字段。在五字段 crontab 表达式前加上 0 即可:0 */5 * * * * 表示每 5 分钟运行一次。
- 如何禁用 @Scheduled 定时任务?
- 使用特殊值 "-"(Scheduled.CRON_DISABLED),通常通过属性占位符来设置。
- Spring 支持每月最后一天吗?
- 支持,从 5.3 开始:0 0 0 L * * 表示每月最后一天的午夜运行。
- 可以从配置文件读取 Cron 表达式吗?
- 可以,例如 @Scheduled(cron = "${jobs.cleanup.cron}"),这样不同环境可以使用不同的调度。