开发者

SpringBoot @Scheduled Cron表达式使用方式

目录
  • Cron 表达式详解
    • 1. 表达式格式‌
    • 2. 特殊字符解析
    • 3. 常用示例
    • ‌4. 重点规则
    • 5. 动态与复杂场景‌
    • 6. 调试与验证‌
    • 7. 常见问题‌
  • 总结‌

    Cron 表达式详解

    Cron 表达式是用于定义定时任务执行时间的字符串,广泛应用于 Spring 的 @Scheduled、Quartz 等定时任务框架。

    其核心是通过 ‌时间字段‌ 和 ‌通配符‌ 组合实现复杂的调度规则。

    1. 表达式格式‌

    Cron 表达式由 ‌6或7个字段‌ 组成,分别表示不同时间单位(Spring 中通常用 ‌6位‌ 格式)。

    格式如下:

    字段允许值特殊字符说明
    秒(Seconds)0-59, - * /可精确到秒级调度
    分(Minutes)0-59, - * /
    小时(Hours)0-23, - * /
    日(Day)1-31, - * / ? L W月份中的某一天
    月(Month)1-12 或 JAN-DEC, - * /
    周(Week)0-7 或 SUN-SAT (0=周日), - * / ? L #周几(1=MON, 7=SUN)
    年(Year)1970-2099 (可选), - * /‌Spring 中通常省略

    2. 特殊字符解析

    符号作用示例
    *匹配任意值0 * * * * ? 每分钟的0秒执行
    ?仅在 ‌日‌ 或 ‌周&zwnjjs; 字段使用,表示“无意义”0 0 0 * * ? 每天0点执行
    -范围区间0 0 10-12 * * ? 10-12点每小时执行
    ,多个值0 0 2,14 * * ? 每天2点和14点执行
    /步长(间隔时间)0 0/5 * * * ? 每隔5分钟执行
    L最后一天(仅 ‌日‌ 或 ‌周‌ 字段)0 0 L * * ? 每月最后一天0点执行
    W最近工作日(仅 ‌日‌ 字段)0 0 0 15W * ? 每月15日最近的工作日执行
    #指定月份的周几(仅 ‌周‌ 字段)0 0 0 ? * 6#3 每月第3个周五执行

    3. 常用示例

    表达式说明
    0 0 12 * * ?每天中午12点执行
    0 0/5 14 * * ?每天下午2点开始,每隔5分钟执行一次
    0 15 10 ? * MON-FRI每周一至周五上午10:15执行
    0 0 0 1 1 ? 20242024年1月1日0点执行(需7位表达式)
    0 0 8-18/2 ? * MON每周一上午8点到下午6点,每隔2小时执行一次
    0 0 0 L * ?每月最后一天的0点执行
    0 0 0 15W * ?每月15日最近的工作日执行
    0 0 0 ? * 6#3每月第3个周五0点执行

    ‌4. 重点规则

    ‌1. 日与周的互斥性‌

    • 若同时指定 ‌日‌ 和 ‌周‌,需用 ? 忽略其中一个字段。
    • ✅ 正确:0 0 0 ? * MON(每周一执行,忽略日)
    • ❌ 错误:0 0 0 * * MON(日和周同时生效,可能冲突)

    2‌. 月份和星期的缩写‌

    • 月份:JAN, FEB, MAR… DEC
    • 星期:SUN, MON, TUE… SAT

    1. L 和 W 的组合‌
    • LW 表示当月的最后一个工作日。
    • L-3 表示倒数第3天。‌
    1. 年份字段(可选)‌
    • Spring 的 @Schedu编程客栈led ‌不支持年份字段‌,需用6位表达式。

    5. 动态与复杂场景‌

    1‌. 动态 Cron 表达式‌

    • Spring 中可通过 @Scheduled(cron = “${cron.expression}”) 从配置文件读取。
    • 结合数据库动态更新任务:
    @Scheduled(cron = "#{@cronService.getCronExpression()}")
    public void dynamicTask() {
        // 业务逻辑
    }

    2‌. 避开整点任务高峰‌

    • 添加随机延迟(避免多个任务同时触发):
    @Scheduled(cron = "0 #{T(Java.util.concurrent.ThreadLocalRandom).current().nextInt(55)} * * * ?")
    public void randomMinuteTask() {
        // 每小时随机分钟执行
    }

    3‌. 闰年处理‌

    • Cron 无法直接处理闰年,需结合代码逻辑判断。

    6. 调试与验证‌

    www.devze.com

    1‌. 在线工具‌

    • Crontab Guru:快速验证表达式。
    • CronMaker:生成表达式并查看下次执行时间。
    1. 日志调试‌
    • 在任务方法中添加日志,观察触发时间是否符合预期:
    @Scheduled(cron = "0 0/5 * * * ?")
    public void lo编程客栈gTask() {
        log.info("任务执行时间: {}", LocalDateTime.now());
    }

    7. 常见问题‌

    ‌1. 为什么任务没有执行?‌

    • 检查是否添加 @EnableScheduling
    • 检查 Cron 表达式是否正确(如 Spring 不支持年份字段)。
    • 检查时区设置(默认使用服务器时区,可通过 zone 属性修改)。

    ‌2. 如何实现每隔 N 天执行?‌

    • 方案1:使用 0 0 0 */N * ?(如 0 0 0 */5 * ? 每隔5天执行)。
    • 方案2:通过代码记录上一次执行时间。

    ‌3. 分布式环境下的幂等性‌

    使用 Redis 分布式锁:

    @Scheduled(cron = "0 0 * * * ?")
    public void distributedTask() {
        if (redisLock.tryLock("taskLock", 10)) {
            try {
                // 业务逻辑
            } finally {
                redisLock.unlock("taskLock");
            }
        }
    }

    总结‌

    Cron 编程客栈表达式通过简洁的语法实现了灵活的定时规则,但需注意 ‌字段互斥性‌ 和 ‌特殊字符的适用场景‌。

    在复杂业务中,可结合动态配置、分布式锁和日志监控来确保任务稳定执行。

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程客栈(www.devze.com)。

    0

    上一篇:

    下一篇:

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    最新开发

    开发排行榜