参数规则校验-限定枚举值的校验

api中,有个字段为订单状态,限定为“开启”和“关闭”,不满足条件了一律不接受。要实现,可以在处理方法中增加条件判断,但是如何做的通用一点呢?或许可以用validation试一下。

首先,定义一个基础的枚举接口,只要实现了此接口的枚举方可校验枚举值。
public interface BaseIntEnum {Integer getCode(); String getDesc(); }

接下来定义我们自己的枚举值
public enum OrderStatusEnum implements BaseIntEnum{OPEN(1,"开启"), CLOSE(2, "关闭"); private Integer code; private String desc; OrderStatusEnum(int code, String desc){ this.code = code; this.desc = desc; } public Integer getCode() { return code; }public String getDesc() { return desc; }}

【参数规则校验-限定枚举值的校验】定义枚举校验注解
@Target( { METHOD, FIELD, ANNOTATION_TYPE }) @Retention(RUNTIME) @Constraint(validatedBy = CheckEnumValidator.class) @Documented public @interface CheckEnum { String message() default "枚举不合规范"; Class[] groups() default {}; Class[] payload() default {}; Class enumClass(); }

然后是枚举校验器
public class CheckEnumValidator implements ConstraintValidator { private Class enumClass; @Override public void initialize(CheckEnum constraintAnnotation) { enumClass = constraintAnnotation.enumClass(); }@Override public boolean isValid(Integer value, ConstraintValidatorContext context) { Type[] types = enumClass.getGenericInterfaces(); if (!needValidate(types)) { return true; } try { return validate(value); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } return false; }/** * 是否需要校验 * 只有implements接口BaseIntEnum,才能校验 * @return */ private boolean needValidate(Type[] types){ boolean needValidate = false; //是否需要校验 for (Type type : types) { if (type.getTypeName().equals(BaseIntEnum.class.getName())) { needValidate = true; } } return needValidate; }/** * 遍历枚举code值,校验value是否存在其中 * @param value * @return * @throws NoSuchMethodException * @throws InvocationTargetException * @throws IllegalAccessException */ private boolean validate(Integer value) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { Method valuesMethod = enumClass.getMethod("values"); if (null == valuesMethod) { return true; } BaseIntEnum inter[] = (BaseIntEnum[]) valuesMethod.invoke(null); for(BaseIntEnum iter : inter){ if(iter.getCode().equals(value)){ return true; } } return false; } }

最后,写个实体类验证一下
@Getter @Setter public class EnumDTO { @CheckEnum(enumClass = OrderStatusEnum.class) Integer orderStatus; }

public static void main(String[] args) { EnumDTO enumDTO = new EnumDTO(); enumDTO.setOrderStatus(3); ValidateCheckUtils.check(enumDTO); }

此方法比较通用,只要实现了BaseIntEnum接口的枚举类,都可以被校验,但也局限。code必须为Integer类型,如果为String类型,需要重新定义接口,并重写枚举注解和校验器。一般实际生产中,字符串用的比较多。
后续:我有点傻,直接把基础枚举改为这样就不纠结是int还是String了。
@Getter @Setter public class EnumDTO {@CheckEnum(enumClass = OrderStatusEnum.class) Integer orderStatus; }

    推荐阅读