依赖

cron-utils的github地址:https://github.com/jmrozanec/cron-utils

<dependency>
<groupId>com.cronutils</groupId>
<artifactId>cron-utils</artifactId>
<version>9.2.1</version>
</dependency>

基本使用

定义cron表达式的支持范围

// 创建cron定义,自定义cron表达式支持的范围
CronDefinition cronDefinition =
CronDefinitionBuilder.defineCron()
.withSeconds().and()
.withMinutes().and()
.withHours().and()
.withDayOfMonth()
.supportsHash().supportsL().supportsW().and()
.withMonth().and()
.withDayOfWeek()
.withIntMapping(7, 0)
.supportsHash().supportsL().supportsW().and()
.withYear().optional().and()
.instance(); // 传入要生成的cron表达式类型获取cron定义
cronDefinition = CronDefinitionBuilder.instanceDefinitionFor(CronType.QUARTZ);

支持定时任务的类型:

  1. CRON4J
  2. QUARTZ
  3. UNIX
  4. SPRING
  5. SPRING53

生成cron表达式

import static com.cronutils.model.field.expression.FieldExpressionFactory.*;

Cron cron = CronBuilder.cron(CronDefinitionBuilder.instanceDefinitionFor(CronType.QUARTZ))
.withYear(always())
.withDoM(between(SpecialChar.L, 3))
.withMonth(always())
.withDoW(questionMark())
.withHour(always())
.withMinute(always())
.withSecond(on(0))
.instance(); String cronAsString = cron.asString(); // 0 * * L-3 * ? *

各方法对应cron表达式关系:

  1. always:表示*
  2. questionMark:表示?
  3. on:表示具体值
  4. between:表示-,例如,between(0,5)表示0-5
  5. and:表示,,例如,and(on(1),on(5))表示0,5
  6. every:表示/,例如,every(on(2),3)表示2/3

获取cron表达式描述

public class Test {

    public static void main(String[] args) {
// 创建cron描述器
CronDescriptor descriptor = CronDescriptor.instance();
// 创建cron定义
CronDefinition cronDefinition = CronDefinitionBuilder.instanceDefinitionFor(QUARTZ);
// 创建cron解析器
CronParser cronParser = new CronParser(cronDefinition);
String describe = descriptor.describe(cronParser.parse("0 0 12 ? * 6"));
System.out.println(describe);
describe = descriptor.describe(cronParser.parse("*/45 * * * * ?"));
System.out.println(describe); // 设置语言
descriptor = CronDescriptor.instance(Locale.CHINESE);
describe = descriptor.describe(cronParser.parse("0 0 12 ? * 6"));
System.out.println(describe);
describe = descriptor.describe(cronParser.parse("*/45 * * * * ?"));
System.out.println(describe);
}
}
// 运行结果:
at 12:00 at Friday day
every 45 seconds
在 12:00 在 星期五 天
每 45 秒

校验cron表达式的正确性

public class Test {

    public static void main(String[] args) {
CronDefinition cronDefinition = CronDefinitionBuilder.instanceDefinitionFor(QUARTZ);
CronParser cronParser = new CronParser(cronDefinition);
Cron cron = cronParser.parse("0 0 12 ? * 6");
// 校验cron表达式
cron.validate();
cron = cronParser.parse("0 0 12 ? * ?");
cron.validate();
}
}

工具类

WeekEnum

定义星期的枚举类信息

@Getter
@AllArgsConstructor
public enum WeekEnum { SUNDAY(1, "星期天"),
MONDAY(2, "星期一"),
TUESDAY(3, "星期二"),
WEDNESDAY(4, "星期三"),
THURSDAY(5, "星期四"),
FRIDAY(6, "星期五"),
SATURDAY(7, "星期六"); private Integer code; private String desc;
}

CycleTypeEnum

定义要生成的cron表达式类型枚举类信息

@Getter
@AllArgsConstructor
public enum CycleTypeEnum { MINUTE(1, "分钟"),
HOUR(2, "小时"),
DAY(3, "日"),
WEEK(4, "周"),
MONTH(5, "月"),
QUARTER(6, "季度"),
YEAR(7, "年"); private Integer code; private String desc;
}

RepeatRuleEnum

定义要生成月、季度的cron表达式循环规则枚举类信息

@Getter
@AllArgsConstructor
public enum RepeatRuleEnum { WEEK(1, "周"),
DATE(2, "日期"); private Integer code; private String desc;
}

CronDto

定义cron表达式工具类的请求体信息

@Data
public class CronDto { /**
* 周期类型 minute:分钟 hour: 小时; day: 天; week: 周; month: 月; quarter: 季; year: 年
*/
private Integer cycleType; /**
* 执行时间
*/
private LocalDateTime executionTime; /**
* 指定一周哪几天
*/
private List<Integer> weekDays; /**
* 指定一个月哪几天
*/
private List<Integer> monthDays; /**
* 指定一年哪几月
*/
private List<Integer> quartzMonths; /**
* 一周的星期几
*/
private Integer dayOfWeek; /**
* 第几周
*/
private Integer week; /**
* 重复规则:周 天
*/
private Integer repeatRule;
}

CronUtils

根据年、月、日、时、分、秒、星期、季度实现不同的cron表达式

注意:生成年、月、季度的cron表达式时可以根据日或者星期额外判断

public class CronUtils {

    /**
* 星期
*/
private static final List<Integer> WEEKS = Arrays.stream(WeekEnum.values()).map(WeekEnum::getCode).collect(Collectors.toList()); public static String createCron(CronDto cronDto) {
Integer cycleType = cronDto.getCycleType();
LocalDateTime executionTime = cronDto.getExecutionTime();
CronBuilder cronBuilder = CronBuilder.cron(CronDefinitionBuilder.instanceDefinitionFor(CronType.QUARTZ));
// 每分钟一次
if (Objects.equals(CycleTypeEnum.MINUTE.getCode(), cycleType)) {
return getSecondCron(cronBuilder, executionTime);
}
// 每小时一次
if (Objects.equals(CycleTypeEnum.HOUR.getCode(), cycleType)) {
return getMinuteCron(cronBuilder, executionTime);
}
// 每日一次
if (Objects.equals(CycleTypeEnum.DAY.getCode(), cycleType)) {
return getDayCron(cronBuilder, executionTime);
}
// 每周一次
if (Objects.equals(CycleTypeEnum.WEEK.getCode(), cycleType)) {
return getWeekCron(cronDto, cronBuilder, executionTime);
}
// 每月一次
if (Objects.equals(CycleTypeEnum.MONTH.getCode(), cycleType)) {
return getMonthCron(cronDto, cronBuilder, executionTime);
}
// 每季度一次
if (Objects.equals(CycleTypeEnum.QUARTER.getCode(), cycleType)) {
return getQuarterCron(cronDto, cronBuilder, executionTime);
}
// 每年一次
if (Objects.equals(CycleTypeEnum.YEAR.getCode(), cycleType)) {
return getYearCron(cronBuilder, executionTime);
}
return "";
} public static String getYearCron(CronBuilder cronBuilder, LocalDateTime executionTime) {
return cronBuilder.withSecond(on(executionTime.getSecond()))
.withMinute(on(executionTime.getMinute()))
.withHour(on(executionTime.getHour()))
.withDoM(on(executionTime.getDayOfMonth()))
.withMonth(on(executionTime.getMonthValue()))
.withDoW(questionMark())
.instance()
.asString();
} public static String getQuarterCron(CronDto cronDto, CronBuilder cronBuilder, LocalDateTime executionTime) {
List<FieldExpression> flist = new ArrayList<>();
cronDto.getQuartzMonths().forEach(e -> flist.add(FieldExpressionFactory.on(e)));
return cronBuilder.withSecond(on(executionTime.getSecond()))
.withMinute(on(executionTime.getMinute()))
.withHour(on(executionTime.getHour()))
.withDoM(questionMark())
.withMonth(and(flist))
.withDoW(on(WEEKS.get(cronDto.getDayOfWeek()), SpecialChar.HASH, cronDto.getWeek()))
.instance()
.asString();
} public static String getMonthCron(CronDto cronDto, CronBuilder cronBuilder, LocalDateTime executionTime) {
Integer repeatRule = cronDto.getRepeatRule();
// 按周
if (Objects.equals(RepeatRuleEnum.WEEK.getCode(), repeatRule)) {
List<FieldExpression> weekDays = new ArrayList<>();
if (!CollectionUtils.isEmpty(cronDto.getWeekDays())) {
cronDto.getWeekDays().forEach(e -> weekDays.add(FieldExpressionFactory.on(WEEKS.get(cronDto.getDayOfWeek()),
SpecialChar.HASH, e)));
}
return cronBuilder.withSecond(on(executionTime.getSecond()))
.withMinute(on(executionTime.getMinute()))
.withHour(on(executionTime.getHour()))
.withDoM(questionMark())
.withMonth(always())
.withDoW(CollectionUtils.isEmpty(weekDays) ? on(WEEKS.get(cronDto.getDayOfWeek()), SpecialChar.HASH,
cronDto.getWeek()) : and(weekDays))
.instance()
.asString(); }
// 按天
if (Objects.equals(RepeatRuleEnum.DATE.getCode(), repeatRule)) {
List<FieldExpression> monthDays = new ArrayList<>();
cronDto.getMonthDays().forEach(e -> monthDays.add(FieldExpressionFactory.on(e)));
return cronBuilder.withSecond(on(executionTime.getSecond()))
.withMinute(on(executionTime.getMinute()))
.withHour(on(executionTime.getHour()))
.withDoM(and(monthDays))
.withMonth(always())
.withDoW(questionMark())
.instance()
.asString();
}
return "";
} public static String getWeekCron(CronDto cronDto, CronBuilder cronBuilder, LocalDateTime executionTime) {
List<FieldExpression> weekDays = new ArrayList<>();
cronDto.getWeekDays().forEach(e -> weekDays.add(FieldExpressionFactory.on(e)));
return cronBuilder.withSecond(on(executionTime.getSecond()))
.withMinute(on(executionTime.getMinute()))
.withHour(on(executionTime.getHour()))
.withDoM(questionMark())
.withMonth(always())
.withDoW(and(weekDays))
.instance()
.asString();
} public static String getDayCron(CronBuilder cronBuilder, LocalDateTime executionTime) {
return cronBuilder.withSecond(on(executionTime.getSecond()))
.withMinute(on(executionTime.getMinute()))
.withHour(on(executionTime.getHour()))
.withDoM(always())
.withMonth(always())
.withDoW(questionMark())
.instance()
.asString();
} public static String getMinuteCron(CronBuilder cronBuilder, LocalDateTime executionTime) {
return cronBuilder.withSecond(on(executionTime.getSecond()))
.withMinute(on(executionTime.getMinute()))
.withHour(always())
.withDoM(always())
.withMonth(always())
.withDoW(questionMark())
.instance()
.asString();
} public static String getSecondCron(CronBuilder cronBuilder, LocalDateTime executionTime) {
return cronBuilder.withSecond(on(executionTime.getSecond()))
.withMinute(always())
.withHour(always())
.withDoM(always())
.withMonth(always())
.withDoW(questionMark())
.instance()
.asString();
}
}

使用案例

public class Test {
public static void main(String[] args) {
CronDto cronDto = new CronDto();
cronDto.setCycleType(1);
cronDto.setExecutionTime(LocalDateTime.now());
String cron = createCron(cronDto);
System.out.println(cron); cronDto.setCycleType(2);
cron = createCron(cronDto);
System.out.println(cron); cronDto.setCycleType(3);
cron = createCron(cronDto);
System.out.println(cron); cronDto.setCycleType(4);
cronDto.setWeekDays(Arrays.asList(1, 2));
cron = createCron(cronDto);
System.out.println(cron); cronDto.setCycleType(5);
cronDto.setRepeatRule(1);
cronDto.setDayOfWeek(1);
cron = createCron(cronDto);
System.out.println(cron); cronDto.setCycleType(5);
cronDto.setRepeatRule(1);
cronDto.setWeek(1);
cronDto.setDayOfWeek(1);
cronDto.setWeekDays(null);
cron = createCron(cronDto);
System.out.println(cron); cronDto.setCycleType(5);
cronDto.setRepeatRule(2);
cronDto.setMonthDays(Arrays.asList(1, 2));
cron = createCron(cronDto);
System.out.println(cron); cronDto.setCycleType(6);
cronDto.setQuartzMonths(Arrays.asList(1, 2));
cron = createCron(cronDto);
System.out.println(cron); cronDto.setCycleType(7);
cron = createCron(cronDto);
System.out.println(cron);
}
}
// 运行结果:
14 * * * * ?
14 28 * * * ?
14 28 9 * * ?
14 28 9 ? * 1,2
14 28 9 ? * 2#1,2#2
14 28 9 ? * 2#1
14 28 9 1,2 * ?
14 28 9 ? 1,2 2#1
14 28 9 19 11 ?

定时任务Cron表达式工具类Cron Util的更多相关文章

  1. Thymeleaf 表达式工具类

    Thymeleaf默认提供了丰富的表达式工具类,这里列举一些常用的工具类. Objects工具类 1 2 3 4 5 6 7 8 /* * 当obj不为空时,返回obj,否则返回default默认值 ...

  2. JavaSE-基础语法(二)-系统类(java.lang.*)和工具类(java.util.*)

    系统类(java.lang.*)和工具类(java.util.*) 一.系统类(java.lang.*) 这个包下包含java语言的核心类,如String.Math.System和Thread类等,使 ...

  3. vue项目工具文件utils.js javascript常用工具类,javascript常用工具类,util.js

    vue项目工具文件utils.js :https://blog.csdn.net/Ajaxguan/article/details/79924249 javascript常用工具类,util.js : ...

  4. 百度地图LV1.5实践项目开发工具类bmap.util.jsV1.0

    /** * 百度地图使用工具类-v1.5 * * @author boonya * @date 2013-7-7 * @address Chengdu,Sichuan,China * @email b ...

  5. 转载及总结:cron表达式详解,cron表达式写法,cron表达式例子

    cron表达式格式:{秒数} {分钟} {小时} {日期} {月份} {星期} {年份(可为空)}例  "0 0 12 ? * WED" 在每星期三下午12:00 执行(年份通常 ...

  6. 005-guava 集合-集合工具类-java.util.Collections中未包含的集合工具[Maps,Lists,Sets],Iterables、Multisets、Multimaps、Tables

    一.概述 工具类与特定集合接口的对应关系归纳如下: 集合接口 属于JDK还是Guava 对应的Guava工具类 Collection JDK Collections2:不要和java.util.Col ...

  7. cron表达式详解,cron表达式写法,cron表达式例子

    (cron = "* * * * * *") cron表达式格式:{秒数} {分钟} {小时} {日期} {月份} {星期} {年份(可为空)}例  "0 0 12 ? ...

  8. 百度地图LV1.5实践项目开发工具类bmap.util.jsV1.3

    /** * 百度地图使用工具类-v1.5 * * @author boonya * @date 2013-7-7 * @address Chengdu,Sichuan,China * @email b ...

  9. 百度地图LV1.5实践项目开发工具类bmap.util.jsV1.2

    /** * 百度地图使用工具类-v1.5 * * @author boonya * @date 2013-7-7 * @address Chengdu,Sichuan,China * @email b ...

  10. 百度地图LV1.5实践项目开发工具类bmap.util.jsV1.1

    /** * 百度地图使用工具类-v1.5 * * @author boonya * @date 2013-7-7 * @address Chengdu,Sichuan,China * @email b ...

随机推荐

  1. Educational Codeforces Round 168 (Rated for Div. 2)

    题目链接:Educational Codeforces Round 168 (Rated for Div. 2) 总结:题目较简单,但是发挥很一般.A,B题一直读假题,卡了半个小时:C题用char存i ...

  2. 2025-01-22:使二进制数组全部等于 1 的最少操作次数Ⅱ。用go语言,给定一个二进制数组 nums,你可以对数组进行以下操作任意次(包括0次): 选择任何一个下标 i,并将从该下标开始到数组末

    2025-01-22:使二进制数组全部等于 1 的最少操作次数Ⅱ.用go语言,给定一个二进制数组 nums,你可以对数组进行以下操作任意次(包括0次): 选择任何一个下标 i,并将从该下标开始到数组末 ...

  3. 十. Redis 事务和 “锁机制”——> 并发秒杀处理的详细说明

    十. Redis 事务和 "锁机制"--> 并发秒杀处理的详细说明 @ 目录 十. Redis 事务和 "锁机制"--> 并发秒杀处理的详细说明 1 ...

  4. xshell连接服务器无法用password登录,只能用public key的解决办法

    xshell无法用password登录服务器,只能用public key的解决办法 只能用public key登录, 那么我们用阿里云后台的远程连接按钮进入服务器,进入后 修改/etc/ssh/ssh ...

  5. SQL注入之报错注入

    SQL注入之报错注入 一.报错注入原理 报错注入的原理基于应用程序在处理数据库查询时产生的错误信息.当应用程序执行一个含有恶意SQL代码的查询时,如果查询出错(例如,由于语法错误或权限不足),数据库系 ...

  6. [阿里DIN] 模型保存,加载和使用

    [阿里DIN] 模型保存,加载和使用 0x00 摘要 Deep Interest Network(DIN)是阿里妈妈精准定向检索及基础算法团队在2017年6月提出的.其针对电子商务领域(e-comme ...

  7. 局域网 yum仓库

    有时候在局域网环境中,每台机器上挂载本地镜像充当yum仓库太麻烦. 可以选择局域网一台服务器生成yum仓库,局域网其他服务器通过http协议访问这台服务器的yum仓库. 一.准备 两台虚拟机,其中 A ...

  8. ABC323E Playlist 题解

    考虑第 \(i\) 时刻时,第 \(j\) 首歌刚好结束与第 \(i-j\) 时刻有关,因此设 \(dp_{i,j}\) 表示第 \(i\) 时刻第 \(j\) 首歌刚好结束的概率,那么 \(dp\) ...

  9. Mysql创建数据库字符集的选择

    字符集选择: 在国内正常都是用[UTF-8] 排序选择:排序一般分为两种:utf_bin和utf_general_cibin 是二进制, a 和 A 会别区别对待. utf8_general_ci [ ...

  10. 数据挖掘 | 数据隐私(2) | 差分隐私 | 数据重构化攻击(Reconstruction Attacks)

    L2-Reconstruction Attacks 本节课的目的在于正式地讨论隐私,但是我们不讨论算法本身有多隐私,取而代之去讨论一个算法隐私性有多么的不可靠.并且聚焦于 Dinur 与 Nissim ...