java validation內沒有對枚舉的校驗工具,但是離散的枚舉值校驗確實是有必要的。javax.validation包提供了方便的自定義校驗的入口,就是javax.validation.ConstraintValidator,故可以通過自定義校驗枚舉類型方式實現。
一、定義一個校驗註解,類似於@NotNull @Size等等那樣
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {EnumIntegerValidator.class})
@Documented
public @interface EnumIntegerValid {
String message() default "";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
Class<?>[] target() default {};
/**
* 允許的枚舉
* @return
*/
Class<? extends Enum<?>> enumClass();
}
二、自定義枚舉校驗的處理類,該類必須實現ConstraintValidator接口
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
/**
* @description value值是Integer類型的枚舉校驗器
*/
public class EnumIntegerValidator implements ConstraintValidator<EnumIntegerValid,Integer> {
private Class<? extends Enum> enumClass;
@Override
public void initialize(EnumIntegerValid enumIntegerValid) {
enumClass = enumIntegerValid.enumClass();
}
@Override
public boolean isValid(Integer value, ConstraintValidatorContext context) {
if (value == null) {
return true;
}
EnumValidate[] enums = (EnumValidate[]) enumClass.getEnumConstants();
if(enums ==null || enums.length == 0){
return false;
}
return enums[0].existValidate(value);
}
}
三、代碼中使用
1、定義一個枚舉值校驗接口
/**
* @description 枚舉值校驗
*/
public interface EnumValidate<T> {
/**
* 校驗枚舉值是否存在
*/
boolean existValidate(T value);
}
2、定義一個Integer類型枚舉類
/**
* @description 測試類型枚舉類
*/
public enum TestTypeEnum implements EnumValidate<Integer> {
A(1, "測試A"),
B(2, "測試B");
private final Integer code;
private final String desc;
TestTypeEnum(Integer code, String desc) {
this.code = code;
this.desc = desc;
}
public Integer getCode() {
return this.code;
}
public String getDesc() {
return this.desc;
}
@Override
public boolean existValidate(Integer value) {
if (value == null) {
return false;
}
for (TestTypeEnum testTypeEnum : TestTypeEnum.values()) {
if (testTypeEnum.getCode().intValue() == value.intValue()) {
return true;
}
}
return false;
}
}
3、參數校驗該枚舉,注意接收參數類型必須爲Integer,否則使用String的枚舉校驗器。
public class TestRequest implements Serializable {
private static final long serialVersionUID = -8739613309305982051L;
@NotNull
@EnumIntegerValid(message = "測試類型輸入錯誤", enumClass = TestTypeEnum.class)
private Integer type;
}
4、Controller中直接加上@Validated 或 @Valid即可
@RequestMapping("/test")
public ApiResponse doSomething(@Validated @RequestBody TestRequest request) {
log.info("doSomething");
log.info(request.toString());
return ApiResponse.retOK();
}
或:
private static Validator validator = Validation.byProvider(HibernateValidator.class)
.configure()
.failFast(true)
.buildValidatorFactory()
.getValidator();
public static <T> void validParam(T param) {
validParamNonNull(param);
Set<ConstraintViolation<T>> constraintViolations = validator.validate(param, Default.class);
StringBuilder sb = new StringBuilder();
if (constraintViolations != null && !constraintViolations.isEmpty()) {
for (ConstraintViolation<T> constraintViolation : constraintViolations) {
sb.append(constraintViolation.getPropertyPath())
.append(":")
.append(constraintViolation.getMessage())
.append(".");
}
throw new IllegalArgumentException(sb.toString());
}
}
四、對於String類型的枚舉類
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {EnumStringValidator.class})
@Documented
public @interface EnumStringValid {
String message() default "";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
Class<?>[] target() default {};
/**
* 允許的枚舉
* @return
*/
Class<? extends Enum<?>> enumClass();
}
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
/**
* @description value值是String類型的枚舉校驗器
*/
public class EnumStringValidator implements ConstraintValidator<EnumStringValid,String> {
private Class<? extends Enum> enumClass;
@Override
public void initialize(EnumStringValid enumStringValid) {
enumClass = enumStringValid.enumClass();
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if (value == null || "".equals(value)) {
return true;
}
EnumValidate[] enums = (EnumValidate[]) enumClass.getEnumConstants();
if(enums ==null || enums.length == 0){
return false;
}
return enums[0].existValidate(value);
}
}
/**
* 測試枚舉類
*/
public enum TestEnum implements EnumValidate<String> {
NONE("NONE", "無"),
C("C", "測試C");
private final String code;
private final String desc;
TestEnum(String code, String desc) {
this.code = code;
this.desc = desc;
}
public String getCode() {
return this.code;
}
public String getDesc() {
return this.desc;
}
@Override
public boolean existValidate(String value) {
if (value == null || "".equals(value)) {
return false;
}
for (TestEnum testEnum : TestEnum.values()) {
if (testEnum.getCode().equalsIgnoreCase(value)) {
return true;
}
}
return false;
}
}
public class TestRequest implements Serializable {
private static final long serialVersionUID = -8739613309305982051L;
@NotNull
@EnumStringValid(message = "測試類型輸入錯誤", enumClass = TestEnum.class)
private String test;
}
參考:https://blog.csdn.net/lqadam/article/details/103446179?utm_source=distribute.pc_relevant.none-task