1. 程式人生 > >SpringMVC自定義註解進行引數校驗(以校驗列舉值是否合法為例)

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;
}