接口入参在很多时候是枚举类型,校验范围限定为枚举类中的几个值。
通过实现自定义枚举校验器,注解声明在DTO相应的字段上,即可校验枚举类型。
1.定义校验器EnumValidator.java
package com.pld.product.center.common.utils;
import com.pld.product.center.common.enums.ProductResultCodeEnum;
import com.pld.product.center.common.exceptions.PldException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.Payload;
import java.lang.annotation.*;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* @author tlj
* @date 2019/7/9
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
@Constraint(validatedBy = EnumValidator.EnumValidatorHandle.class)
public @interface EnumValidator {
Class<?> value();
String message() default "入参值不在正确枚举中";
String method() default "getCode";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
/**
* @author tlj
* @date 2019/7/9
*/
@Slf4j
class EnumValidatorHandle implements ConstraintValidator<EnumValidator, Object>, Annotation {
private List<Object> values = new ArrayList<>();
@Override
public void initialize(EnumValidator enumValidator) {
Class<?> clz = enumValidator.value();
Object[] objects = clz.getEnumConstants();
try {
Method method = clz.getMethod(enumValidator.method());
if (Objects.isNull(method)) {
throw new PldException(ProductResultCodeEnum.PRODUCT_PARAM_ERROR,String.format("枚举对象%s缺少名为%s的方法",clz.getName(),enumValidator.method()));
}
Object value;
for (Object obj : objects) {
value = method.invoke(obj);
values.add(value);
}
} catch (Exception e) {
log.error("处理枚举校验异常:{}", e);
}
}
@Override
public Class<? extends Annotation> annotationType() {
return null;
}
@Override
public boolean isValid(Object value, ConstraintValidatorContext constraintValidatorContext) {
if (value instanceof String) {
String valueStr = (String)value;
return StringUtils.isEmpty(valueStr)|| values.contains(value);
}
return Objects.isNull(value) || values.contains(value);
}
}
}
2.枚举类:
/**
* @author tlj
* @date 2019/7/9
*/
@Getter
public enum SxWhetherIntEnum {
YES(1, "是"),
NO(2, "否");
private Integer code;
private String msg;
SxWhetherIntEnum(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
}
3.使用的时候,注解作用在DTO字段上:
/**
* 是否可转定,1-是,2-否
*/
@ApiModelProperty(value = "是否可转定,1-是,2-否(补充)")
@EnumValidator(value = SxWhetherIntEnum.class,message = "是否可转定可选值:1是2否")
private Integer payable;