定时任务Cron表达式工具类Cron Util

农民  论坛元老 | 2025-4-20 11:11:32 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 1585|帖子 1585|积分 4755

依赖

cron-utils的github地点:https://github.com/jmrozanec/cron-utils
  1. <dependency>
  2.     <groupId>com.cronutils</groupId>
  3.     <artifactId>cron-utils</artifactId>
  4.     <version>9.2.1</version>
  5. </dependency>
复制代码
基本使用

定义cron表达式的支持范围
  1. // 创建cron定义,自定义cron表达式支持的范围
  2. CronDefinition cronDefinition =
  3.     CronDefinitionBuilder.defineCron()
  4.         .withSeconds().and()
  5.         .withMinutes().and()
  6.         .withHours().and()
  7.         .withDayOfMonth()
  8.             .supportsHash().supportsL().supportsW().and()
  9.         .withMonth().and()
  10.         .withDayOfWeek()
  11.             .withIntMapping(7, 0)
  12.             .supportsHash().supportsL().supportsW().and()
  13.         .withYear().optional().and()
  14.         .instance();
  15. // 传入要生成的cron表达式类型获取cron定义
  16. cronDefinition = CronDefinitionBuilder.instanceDefinitionFor(CronType.QUARTZ);
复制代码
支持定时任务的类型:

  • CRON4J
  • QUARTZ
  • UNIX
  • SPRING
  • SPRING53
天生cron表达式
  1. import static com.cronutils.model.field.expression.FieldExpressionFactory.*;
  2. Cron cron = CronBuilder.cron(CronDefinitionBuilder.instanceDefinitionFor(CronType.QUARTZ))
  3.     .withYear(always())
  4.     .withDoM(between(SpecialChar.L, 3))
  5.     .withMonth(always())
  6.     .withDoW(questionMark())
  7.     .withHour(always())
  8.     .withMinute(always())
  9.     .withSecond(on(0))
  10.     .instance();
  11. String cronAsString = cron.asString(); // 0 * * L-3 * ? *
复制代码
各方法对应cron表达式关系:

  • always:表现*
  • questionMark:表现?
  • on:表现具体值
  • between:表现-,比方,between(0,5)表现0-5
  • and:表现,,比方,and(on(1),on(5))表现0,5
  • every:表现/,比方,every(on(2),3)表现2/3
获取cron表达式描述
  1. public class Test {
  2.     public static void main(String[] args) {
  3.         // 创建cron描述器
  4.         CronDescriptor descriptor = CronDescriptor.instance();
  5.         // 创建cron定义
  6.         CronDefinition cronDefinition = CronDefinitionBuilder.instanceDefinitionFor(QUARTZ);
  7.         // 创建cron解析器
  8.         CronParser cronParser = new CronParser(cronDefinition);
  9.         String describe = descriptor.describe(cronParser.parse("0 0 12 ? * 6"));
  10.         System.out.println(describe);
  11.         describe = descriptor.describe(cronParser.parse("*/45 * * * * ?"));
  12.         System.out.println(describe);
  13.         
  14.         // 设置语言
  15.                 descriptor = CronDescriptor.instance(Locale.CHINESE);
  16.         describe = descriptor.describe(cronParser.parse("0 0 12 ? * 6"));
  17.         System.out.println(describe);
  18.         describe = descriptor.describe(cronParser.parse("*/45 * * * * ?"));
  19.         System.out.println(describe);
  20.     }
  21. }
复制代码
  1. // 运行结果:
  2. at 12:00 at Friday day
  3. every 45 seconds
  4. 在 12:00 在 星期五 天
  5. 每 45 秒
复制代码
校验cron表达式的精确性
  1. public class Test {
  2.     public static void main(String[] args) {
  3.         CronDefinition cronDefinition = CronDefinitionBuilder.instanceDefinitionFor(QUARTZ);
  4.         CronParser cronParser = new CronParser(cronDefinition);
  5.         Cron cron = cronParser.parse("0 0 12 ? * 6");
  6.         // 校验cron表达式
  7.         cron.validate();
  8.         cron = cronParser.parse("0 0 12 ? * ?");
  9.         cron.validate();
  10.     }
  11. }
复制代码
工具类

WeekEnum

定义星期的罗列类信息
  1. @Getter
  2. @AllArgsConstructor
  3. public enum WeekEnum {
  4.     SUNDAY(1, "星期天"),
  5.     MONDAY(2, "星期一"),
  6.     TUESDAY(3, "星期二"),
  7.     WEDNESDAY(4, "星期三"),
  8.     THURSDAY(5, "星期四"),
  9.     FRIDAY(6, "星期五"),
  10.     SATURDAY(7, "星期六");
  11.     private Integer code;
  12.     private String desc;
  13. }
复制代码
CycleTypeEnum

定义要天生的cron表达式类型罗列类信息
  1. @Getter
  2. @AllArgsConstructor
  3. public enum CycleTypeEnum {
  4.     MINUTE(1, "分钟"),
  5.     HOUR(2, "小时"),
  6.     DAY(3, "日"),
  7.     WEEK(4, "周"),
  8.     MONTH(5, "月"),
  9.     QUARTER(6, "季度"),
  10.     YEAR(7, "年");
  11.     private Integer code;
  12.     private String desc;
  13. }
复制代码
RepeatRuleEnum

定义要天生月、季度的cron表达式循环规则罗列类信息
  1. @Getter
  2. @AllArgsConstructor
  3. public enum RepeatRuleEnum {
  4.     WEEK(1, "周"),
  5.     DATE(2, "日期");
  6.     private Integer code;
  7.     private String desc;
  8. }
复制代码
CronDto

定义cron表达式工具类的请求体信息
  1. @Data
  2. public class CronDto {
  3.     /**
  4.      * 周期类型 minute:分钟 hour: 小时; day: 天; week: 周; month: 月; quarter: 季; year: 年
  5.      */
  6.     private Integer cycleType;
  7.     /**
  8.      * 执行时间
  9.      */
  10.     private LocalDateTime executionTime;
  11.     /**
  12.      * 指定一周哪几天
  13.      */
  14.     private List<Integer> weekDays;
  15.     /**
  16.      * 指定一个月哪几天
  17.      */
  18.     private List<Integer> monthDays;
  19.     /**
  20.      * 指定一年哪几月
  21.      */
  22.     private List<Integer> quartzMonths;
  23.     /**
  24.      * 一周的星期几
  25.      */
  26.     private Integer dayOfWeek;
  27.     /**
  28.      * 第几周
  29.      */
  30.     private Integer week;
  31.     /**
  32.      * 重复规则:周 天
  33.      */
  34.     private Integer repeatRule;
  35. }
复制代码
CronUtils

根据年、月、日、时、分、秒、星期、季度实现不同的cron表达式
注意:天生年、月、季度的cron表达式时可以根据日或者星期额外判定
  1. public class CronUtils {
  2.     /**
  3.      * 星期
  4.      */
  5.     private static final List<Integer> WEEKS = Arrays.stream(WeekEnum.values()).map(WeekEnum::getCode).collect(Collectors.toList());
  6.     public static String createCron(CronDto cronDto) {
  7.         Integer cycleType = cronDto.getCycleType();
  8.         LocalDateTime executionTime = cronDto.getExecutionTime();
  9.         CronBuilder cronBuilder = CronBuilder.cron(CronDefinitionBuilder.instanceDefinitionFor(CronType.QUARTZ));
  10.         // 每分钟一次
  11.         if (Objects.equals(CycleTypeEnum.MINUTE.getCode(), cycleType)) {
  12.             return getSecondCron(cronBuilder, executionTime);
  13.         }
  14.         // 每小时一次
  15.         if (Objects.equals(CycleTypeEnum.HOUR.getCode(), cycleType)) {
  16.             return getMinuteCron(cronBuilder, executionTime);
  17.         }
  18.         // 每日一次
  19.         if (Objects.equals(CycleTypeEnum.DAY.getCode(), cycleType)) {
  20.             return getDayCron(cronBuilder, executionTime);
  21.         }
  22.         // 每周一次
  23.         if (Objects.equals(CycleTypeEnum.WEEK.getCode(), cycleType)) {
  24.             return getWeekCron(cronDto, cronBuilder, executionTime);
  25.         }
  26.         // 每月一次
  27.         if (Objects.equals(CycleTypeEnum.MONTH.getCode(), cycleType)) {
  28.             return getMonthCron(cronDto, cronBuilder, executionTime);
  29.         }
  30.         // 每季度一次
  31.         if (Objects.equals(CycleTypeEnum.QUARTER.getCode(), cycleType)) {
  32.             return getQuarterCron(cronDto, cronBuilder, executionTime);
  33.         }
  34.         // 每年一次
  35.         if (Objects.equals(CycleTypeEnum.YEAR.getCode(), cycleType)) {
  36.             return getYearCron(cronBuilder, executionTime);
  37.         }
  38.         return "";
  39.     }
  40.     public static String getYearCron(CronBuilder cronBuilder, LocalDateTime executionTime) {
  41.         return cronBuilder.withSecond(on(executionTime.getSecond()))
  42.                 .withMinute(on(executionTime.getMinute()))
  43.                 .withHour(on(executionTime.getHour()))
  44.                 .withDoM(on(executionTime.getDayOfMonth()))
  45.                 .withMonth(on(executionTime.getMonthValue()))
  46.                 .withDoW(questionMark())
  47.                 .instance()
  48.                 .asString();
  49.     }
  50.     public static String getQuarterCron(CronDto cronDto, CronBuilder cronBuilder, LocalDateTime executionTime) {
  51.         List<FieldExpression> flist = new ArrayList<>();
  52.         cronDto.getQuartzMonths().forEach(e -> flist.add(FieldExpressionFactory.on(e)));
  53.         return cronBuilder.withSecond(on(executionTime.getSecond()))
  54.                 .withMinute(on(executionTime.getMinute()))
  55.                 .withHour(on(executionTime.getHour()))
  56.                 .withDoM(questionMark())
  57.                 .withMonth(and(flist))
  58.                 .withDoW(on(WEEKS.get(cronDto.getDayOfWeek()), SpecialChar.HASH, cronDto.getWeek()))
  59.                 .instance()
  60.                 .asString();
  61.     }
  62.     public static String getMonthCron(CronDto cronDto, CronBuilder cronBuilder, LocalDateTime executionTime) {
  63.         Integer repeatRule = cronDto.getRepeatRule();
  64.         // 按周
  65.         if (Objects.equals(RepeatRuleEnum.WEEK.getCode(), repeatRule)) {
  66.             List<FieldExpression> weekDays = new ArrayList<>();
  67.             if (!CollectionUtils.isEmpty(cronDto.getWeekDays())) {
  68.                 cronDto.getWeekDays().forEach(e -> weekDays.add(FieldExpressionFactory.on(WEEKS.get(cronDto.getDayOfWeek()),
  69.                         SpecialChar.HASH, e)));
  70.             }
  71.             return cronBuilder.withSecond(on(executionTime.getSecond()))
  72.                     .withMinute(on(executionTime.getMinute()))
  73.                     .withHour(on(executionTime.getHour()))
  74.                     .withDoM(questionMark())
  75.                     .withMonth(always())
  76.                     .withDoW(CollectionUtils.isEmpty(weekDays) ? on(WEEKS.get(cronDto.getDayOfWeek()), SpecialChar.HASH,
  77.                             cronDto.getWeek()) : and(weekDays))
  78.                     .instance()
  79.                     .asString();
  80.         }
  81.         // 按天
  82.         if (Objects.equals(RepeatRuleEnum.DATE.getCode(), repeatRule)) {
  83.             List<FieldExpression> monthDays = new ArrayList<>();
  84.             cronDto.getMonthDays().forEach(e -> monthDays.add(FieldExpressionFactory.on(e)));
  85.             return cronBuilder.withSecond(on(executionTime.getSecond()))
  86.                     .withMinute(on(executionTime.getMinute()))
  87.                     .withHour(on(executionTime.getHour()))
  88.                     .withDoM(and(monthDays))
  89.                     .withMonth(always())
  90.                     .withDoW(questionMark())
  91.                     .instance()
  92.                     .asString();
  93.         }
  94.         return "";
  95.     }
  96.     public static String getWeekCron(CronDto cronDto, CronBuilder cronBuilder, LocalDateTime executionTime) {
  97.         List<FieldExpression> weekDays = new ArrayList<>();
  98.         cronDto.getWeekDays().forEach(e -> weekDays.add(FieldExpressionFactory.on(e)));
  99.         return cronBuilder.withSecond(on(executionTime.getSecond()))
  100.                 .withMinute(on(executionTime.getMinute()))
  101.                 .withHour(on(executionTime.getHour()))
  102.                 .withDoM(questionMark())
  103.                 .withMonth(always())
  104.                 .withDoW(and(weekDays))
  105.                 .instance()
  106.                 .asString();
  107.     }
  108.     public static String getDayCron(CronBuilder cronBuilder, LocalDateTime executionTime) {
  109.         return cronBuilder.withSecond(on(executionTime.getSecond()))
  110.                 .withMinute(on(executionTime.getMinute()))
  111.                 .withHour(on(executionTime.getHour()))
  112.                 .withDoM(always())
  113.                 .withMonth(always())
  114.                 .withDoW(questionMark())
  115.                 .instance()
  116.                 .asString();
  117.     }
  118.     public static String getMinuteCron(CronBuilder cronBuilder, LocalDateTime executionTime) {
  119.         return cronBuilder.withSecond(on(executionTime.getSecond()))
  120.                 .withMinute(on(executionTime.getMinute()))
  121.                 .withHour(always())
  122.                 .withDoM(always())
  123.                 .withMonth(always())
  124.                 .withDoW(questionMark())
  125.                 .instance()
  126.                 .asString();
  127.     }
  128.     public static String getSecondCron(CronBuilder cronBuilder, LocalDateTime executionTime) {
  129.         return cronBuilder.withSecond(on(executionTime.getSecond()))
  130.                 .withMinute(always())
  131.                 .withHour(always())
  132.                 .withDoM(always())
  133.                 .withMonth(always())
  134.                 .withDoW(questionMark())
  135.                 .instance()
  136.                 .asString();
  137.     }
  138. }
复制代码
使用案例
  1. public class Test {
  2.     public static void main(String[] args) {
  3.         CronDto cronDto = new CronDto();
  4.         cronDto.setCycleType(1);
  5.         cronDto.setExecutionTime(LocalDateTime.now());
  6.         String cron = createCron(cronDto);
  7.         System.out.println(cron);
  8.         cronDto.setCycleType(2);
  9.         cron = createCron(cronDto);
  10.         System.out.println(cron);
  11.         cronDto.setCycleType(3);
  12.         cron = createCron(cronDto);
  13.         System.out.println(cron);
  14.         cronDto.setCycleType(4);
  15.         cronDto.setWeekDays(Arrays.asList(1, 2));
  16.         cron = createCron(cronDto);
  17.         System.out.println(cron);
  18.         cronDto.setCycleType(5);
  19.         cronDto.setRepeatRule(1);
  20.         cronDto.setDayOfWeek(1);
  21.         cron = createCron(cronDto);
  22.         System.out.println(cron);
  23.         cronDto.setCycleType(5);
  24.         cronDto.setRepeatRule(1);
  25.         cronDto.setWeek(1);
  26.         cronDto.setDayOfWeek(1);
  27.         cronDto.setWeekDays(null);
  28.         cron = createCron(cronDto);
  29.         System.out.println(cron);
  30.         cronDto.setCycleType(5);
  31.         cronDto.setRepeatRule(2);
  32.         cronDto.setMonthDays(Arrays.asList(1, 2));
  33.         cron = createCron(cronDto);
  34.         System.out.println(cron);
  35.         cronDto.setCycleType(6);
  36.         cronDto.setQuartzMonths(Arrays.asList(1, 2));
  37.         cron = createCron(cronDto);
  38.         System.out.println(cron);
  39.         cronDto.setCycleType(7);
  40.         cron = createCron(cronDto);
  41.         System.out.println(cron);
  42.     }
  43. }
复制代码
  1. // 运行结果:
  2. 14 * * * * ?
  3. 14 28 * * * ?
  4. 14 28 9 * * ?
  5. 14 28 9 ? * 1,2
  6. 14 28 9 ? * 2#1,2#2
  7. 14 28 9 ? * 2#1
  8. 14 28 9 1,2 * ?
  9. 14 28 9 ? 1,2 2#1
  10. 14 28 9 19 11 ?
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

农民

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表