1.定义主对象
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@ApiModel("定时任务corn对象")
public class TimingCornVo {
@ApiModelProperty(value = "corn字符串")
String corn;
@ApiModelProperty(value = "corn转换后数据集合")
List<TimingCornSubVo> subVoList;
}
2.定义子对象,用于存放corn的每个部分数据
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.ArrayUtils;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@ApiModel("定时任务corn子对象")
public class TimingCornSubVo {
@ApiModelProperty(value = "数据类型[0:秒,1:分,2时,3:日,4:月,5:周,6:年]")
Integer type;
@ApiModelProperty(value = "使用类型[0:不指定,1:每单位执行,2:周期执行内单位频率执行,3:指定开始时间和频率,4:指定时间执行,5最后一个(日和周,月中最后一个月或月中最后的星期)]")
Integer useType;
@ApiModelProperty(value = "执行时间数据[useType2:两个数据,表示x-y,useType3:任意个合法范围内数值],useType4:两个数据,表示x/y")
Integer[] data;
/**
* 参数校验
* 在工具类中对顺序进行了排序,因此此处不校验大小问题
*/
public void checkParam() throws Exception {
if (null==type||type<0||type>6){
throw new Exception("类型取值不合法");
}
if (null==useType||useType<0||useType>5){
throw new Exception("使用类型取值不合法");
}
if (useType == 0){
if (type<3){
throw new Exception("秒,分,时使用类型不能为不指定");
}
}else if (useType == 2){
if (ArrayUtils.isEmpty(data)||data.length!=2){
throw new Exception("周期执行类型数据必须为两个");
}
}else if (useType == 3){
if (ArrayUtils.isEmpty(data)||data.length!=2){
throw new Exception("指定开始和频率类型数据必须为两个");
}
}else if (useType == 4){
if (ArrayUtils.isEmpty(data)&&type!=6){
throw new Exception("指定时间类型数据不能为空");
}
for (Integer datum : data) {
switch (type){
case 0:
if (datum<0||datum>59){
throw new Exception("秒只能为1-60");
}
break;
case 1:
if (datum<0||datum>59){
throw new Exception("分只能为1-60");
}
break;
case 2:
if (datum<0||datum>23){
throw new Exception("时只能为1-24");
}
break;
case 3:
if (datum<1||datum>31){
throw new Exception("日只能为1-31");
}
break;
case 4:
if (datum<1||datum>12){
throw new Exception("月只能为1-12");
}
break;
case 5:
if (datum<1||datum>7){
throw new Exception("周只能为1-7");
}
break;
case 6:
if (datum<1970||datum>2099){
throw new Exception("年只能为1970-2099");
}
break;
}
}
}else if (useType == 4){
if (type!=3||type!=5){
throw new Exception("最后一个使用类型仅日和周可以使用");
}else if (type==5){
if (ArrayUtils.isEmpty(data)||data.length!=1){
throw new Exception("最后一个使用类型必须指定一个星期数值");
}
}
}
}
}
3.创建对象和corn字符串转换工具类
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.*;
import java.util.regex.Pattern;
/**
* corn转换工具类
*/
public class TimingCornUtil {
//corn正则校验
private static final String regEx = "^\\s*($|#|\\w+\\s*=|(\\?|\\*|(?:[0-5]?\\d)(?:(?:-|\\/|\\,)(?:[0-5]?\\d))?(?:,(?:[0-5]?\\d)(?:(?:-|\\/|\\,)(?:[0-5]?\\d))?)*)\\s+(\\?|\\*|(?:[0-5]?\\d)(?:(?:-|\\/|\\,)(?:[0-5]?\\d))?(?:,(?:[0-5]?\\d)(?:(?:-|\\/|\\,)(?:[0-5]?\\d))?)*)\\s+(\\?|\\*|(?:[01]?\\d|2[0-3])(?:(?:-|\\/|\\,)(?:[01]?\\d|2[0-3]))?(?:,(?:[01]?\\d|2[0-3])(?:(?:-|\\/|\\,)(?:[01]?\\d|2[0-3]))?)*)\\s+(\\?|\\*|(?:0?[1-9]|[12]\\d|3[01])(?:(?:-|\\/|\\,)(?:0?[1-9]|[12]\\d|3[01]))?(?:,(?:0?[1-9]|[12]\\d|3[01])(?:(?:-|\\/|\\,)(?:0?[1-9]|[12]\\d|3[01]))?)*)\\s+(\\?|\\*|(?:[1-9]|1[012])(?:(?:-|\\/|\\,)(?:[1-9]|1[012]))?(?:L|W)?(?:,(?:[1-9]|1[012])(?:(?:-|\\/|\\,)(?:[1-9]|1[012]))?(?:L|W)?)*|\\?|\\*|(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:(?:-)(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC))?(?:,(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(?:(?:-)(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC))?)*)\\s+(\\?|\\*|(?:[0-6])(?:(?:-|\\/|\\,|#)(?:[0-6]))?(?:L)?(?:,(?:[0-6])(?:(?:-|\\/|\\,|#)(?:[0-6]))?(?:L)?)*|\\?|\\*|(?:MON|TUE|WED|THU|FRI|SAT|SUN)(?:(?:-)(?:MON|TUE|WED|THU|FRI|SAT|SUN))?(?:,(?:MON|TUE|WED|THU|FRI|SAT|SUN)(?:(?:-)(?:MON|TUE|WED|THU|FRI|SAT|SUN))?)*)(|\\s)+(\\?|\\*|(?:|\\d{4})(?:(?:-|\\/|\\,)(?:|\\d{4}))?(?:,(?:|\\d{4})(?:(?:-|\\/|\\,)(?:|\\d{4}))?)*))$";
private static final Pattern cornPattern = Pattern.compile(regEx);
/**
* obj转corn字符串
* @param cornVo
* @return
* @throws Exception
*/
public static String objToStr(TimingCornVo cornVo) throws Exception {
List<TimingCornSubVo> subVoList = cornVo.getSubVoList();
//年数据可以没有,因此子数据集合为6-7个
if (CollectionUtils.isEmpty(subVoList)||subVoList.size()<6||subVoList.size()>7){
throw new Exception("数据错误");
}
//对数据按照日期类型排序
subVoList.sort(Comparator.comparing(TimingCornSubVo::getType));
//使用空格对字符串进行拼接
StringJoiner cornStrJoiner = new StringJoiner(" ");
for (int i = 0; i < subVoList.size(); i++) {
TimingCornSubVo subVo = subVoList.get(i);
//校验参数
subVo.checkParam();
Integer[] data = subVo.getData();
if (subVo.getType()!=i){
throw new Exception("数据日期类型错误,必须含有秒,分,时,日,月,周这6种数据");
}
if (ArrayUtils.isNotEmpty(data)){
//对数据进行排序,防止出现填反的情况
Arrays.sort(data);
}
//i-type-0:秒,1:分,2时,3:日,4:月,5:周,6:年
//useType0:不指定,1:每单位执行,2:周期执行内单位频率执行,3:指定开始时间和频率,4:指定时间执行,5最后一个
switch (subVo.getUseType()){
case 0:
cornStrJoiner.add("?");
break;
case 1:
cornStrJoiner.add("*");
break;
case 2:
cornStrJoiner.add(data[0]+"-"+data[1]);
break;
case 3:
cornStrJoiner.add(data[0]+"/"+data[1]);
break;
case 4:
StringJoiner dataJoiner = new StringJoiner(",");
for (Integer datum : data) {
dataJoiner.add(datum+"");
}
cornStrJoiner.add(dataJoiner.toString());
break;
case 5:
if (i==3){
cornStrJoiner.add("L");
}else {
cornStrJoiner.add(data[0]+"L");
}
break;
}
}
cornVo.setCorn(cornStrJoiner.toString());
return cornStrJoiner.toString();
}
/**
* corn字符串转obj
* @param corn
* @return
*/
public static TimingCornVo strToObj(String corn) throws Exception {
if (StringUtils.isEmpty(corn)){
throw new Exception("corn表达式为空");
}
if (!cornPattern.matcher(corn).matches()){
throw new Exception("corn表达式格式有误");
}
String[] data = corn.split(" ");
List<TimingCornSubVo> subVoList = new ArrayList<>();
TimingCornVo result = TimingCornVo.builder()
.corn(corn)
.subVoList(subVoList).build();
for (int i = 0; i < data.length; i++) {
TimingCornSubVo subVo = TimingCornSubVo.builder()
.type(i).build();
String subStr = data[i];
//useType0:不指定,1:每单位执行,2:周期执行内单位频率执行,3:指定开始时间和频率,4:指定时间执行,5最后一个
if ("?".equals(subStr)){
subVo.setUseType(0);
}else if ("*".equals(subStr)){
subVo.setUseType(1);
}else if (subStr.contains("-")){
subVo.setUseType(2);
String[] split = subStr.split("-");
Integer[] subStrSplitData = new Integer[2];
subStrSplitData[0] = Integer.parseInt(split[0]);
subStrSplitData[1] = Integer.parseInt(split[1]);
subVo.setData(subStrSplitData);
}else if (subStr.contains("/")){
subVo.setUseType(3);
String[] split = subStr.split("/");
Integer[] subStrSplitData = new Integer[2];
subStrSplitData[0] = Integer.parseInt(split[0]);
subStrSplitData[1] = Integer.parseInt(split[1]);
subVo.setData(subStrSplitData);
}else if (subStr.contains("L")){
subVo.setUseType(5);
if (i==5){
Integer[] subStrSplitData = new Integer[1];
subStrSplitData[0] = Integer.parseInt(subStr.replace("L",""));
subVo.setData(subStrSplitData);
}
}else{
subVo.setUseType(4);
String[] split = subStr.split(",");
Integer[] subStrSplitData = new Integer[split.length];
for (int i1 = 0; i1 < subStrSplitData.length; i1++) {
subStrSplitData[i1] = Integer.parseInt(split[i1]);
}
subVo.setData(subStrSplitData);
}
subVoList.add(subVo);
}
return result;
}
}
4.测试
public static void main(String[] args) throws Exception {
String corn = "0 15,17,19 10/5 ? * 6L 2002-2005";
TimingCornVo timingCornVo = TimingCornUtil.strToObj(corn);
for (TimingCornSubVo subVo : timingCornVo.getSubVoList()) {
System.out.println(subVo.getType()+"|"+subVo.getUseType()+"|"+ArrayUtils.toString(subVo.getData()));
}
System.out.println(corn);
System.out.println(TimingCornUtil.objToStr(timingCornVo));
//测试结果可以看出corn字符串转换对象符合预期并且可以正确转回corn字符串
}
本文详细介绍了在JAVA中如何设计定时任务Corn的相关对象,并提供了从Corn字符串到对象的转换工具类,涵盖了主对象、子对象的定义及转换测试的过程。
331

被折叠的 条评论
为什么被折叠?



