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 extends Payload>[] 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;
}