参数规则校验-限定枚举值的校验
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;
}
推荐阅读
- 难道你仅会钻规则的漏洞吗()
- Jsr303做前端数据校验
- [源码解析]|[源码解析] NVIDIA HugeCTR,GPU版本参数服务器---(3)
- 接口|axios接口报错-参数类型错误解决
- performSelectorOnMainThread:withObject:waitUntilDone:参数设置为NO或YES的区别
- SwiftUI|SwiftUI iOS 瀑布流组件之仿CollectionView不规则图文混合(教程含源码)
- iview|iview upload 动态改变上传参数
- 整理大部分Eslint规则
- 读《12条生活规则》,在噪杂混乱的环境里找到生活的目的和意义
- 小程序开发|小程序开发 - 页面传值url类型