SpringMVC自定义注解进行参数校验(以校验枚举值是否合法为例)

pom引入springMVC依赖,以springboot项目为例

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
   <version>2.0.6.RELEASE</version>
</dependency>

编写自定义注解

package validation;

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER})
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {EnumValueValidator.class})// 与约束注解关联的校验器
public @interface EnumValue {
  // 默认错误消息
   String message() default "the integer is not one of the enum values";

  // 约束注解在验证时所属的组别
  Class<?>[] groups() default {};

  // 约束注解的有效负载
  Class<? extends Payload>[] payload() default {};

  Class<? extends Enum> value();

  // 同时指定多个时使用
  @Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER})
  @Documented
  @Retention(RetentionPolicy.RUNTIME)
  @interface List{
    EnumValue[] value();
  }
}

编写自定义校验器

package validation;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.lang.reflect.Method;

public class EnumValueValidator implements ConstraintValidator<EnumValue, Integer>{
  private Class<? extends Enum> enumClass;
  private static final String METHOD_NAME = "toEnum";
  
  //这个方法做一些初始化校验
  public void initialize(EnumValue constraintAnnotation) {
    enumClass = constraintAnnotation.value();
    try {
      // 先判断该enum是否实现了toEnum方法
      enumClass.getDeclaredMethod(METHOD_NAME, int.class);
    } catch (NoSuchMethodException e){
      throw new IllegalArgumentException("the enum class has not toEnum method", e);
    }
  }

  // 这个方法写具体的校验逻辑:校验数字是否属于指定枚举类型的范围
  public boolean isValid(Integer value, ConstraintValidatorContext constraintValidatorContext) {
    Method declareMethod;
    try {
      declareMethod = enumClass.getDeclaredMethod(METHOD_NAME, int.class);
    }catch (NoSuchMethodException e){
      return false;
    }
    try {
      declareMethod.invoke(null, value);
    } catch (Exception e) {
      return false;
    }
    return true;
  }
}

需要校验的枚举

package validation;

public enum Gender {
  male(0),
  female(1);

  private int value;

  Gender(int value) {
    this.value = value;
  }

  // 为了使注解校验器能生效,必须有这个方法
  public static Gender toEnum(int value) {
    switch (value) {
      case 0:
        return Gender.male;
      case 1:
        return Gender.female;
      default:
        throw new IllegalArgumentException("invalid value , only [0, 1] is allowed");
    }
  }
}

使用示例

package validation;

public class Person {
  @EnumValue(Gender.class)
  Gender gender;
}

猜你喜欢

转载自blog.csdn.net/weixin_43221845/article/details/84855764