@Constraint自定义验证类型注解

Posted Java_小墨

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了@Constraint自定义验证类型注解相关的知识,希望对你有一定的参考价值。

/**
 * 银行卡校验
 */
@Target(METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER)
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = StringChecker.class, ObjectChecker.class)
public @interface BankCard 

   String message() default "银行卡号格式错误";

   Class<?>[] groups() default ;

   Class<? extends Payload>[] payload() default ;

   /**
    * ConstraintValidator<A extends Annotation, T>
    *   A 第一个是自定义的注解类
    *   T 第二个就是要验证的数据的类型
    *   例如写了String, 那么这个类只接收String类型的参数, 写了Long就接收Long类型的参数...
    *   还可以写Object, 那么这个类就接收所有类型的参数, 可以用instanceof区分, 例子在下一个类
    */
   class StringChecker implements ConstraintValidator<BankCard, String> 
      /**
       * 定义的银行卡号验证正则表达式
       */
      private Pattern pattern = Pattern.compile("(^\\d19$)");
      
      @Override
      public void initialize(BankCard constraintAnnotation) 
         // 初始化方法
         System.out.println("StringChecker init");
      

      @Override
      public boolean isValid(String value, ConstraintValidatorContext context) 
         // 验证的逻辑方法; 这里String类型的value 就是需要校验的对象, 它可能为空;
         // 可以配合@NotNull, @NotBlank, @NotEmpty等来限制他是否为空
         if (StringUtils.isEmpty(value)) 
            return true;
         
         Matcher matcher = pattern.matcher(value);
         // matches精确匹配
         return matcher.matches();
      
   

   /**
    * 接收@BankCard注解标注的字段, 由于是Object, 所以接收的类型不限
    */
   class ObjectChecker implements ConstraintValidator<BankCard, Object> 

      @Override
      public void initialize(BankCard constraintAnnotation) 
      

      @Override
      public boolean isValid(Object value, ConstraintValidatorContext context) 
         if (null == value) 
            return true;
         
         
         // Object类型的value, 可以接收任何数据类型的数据
         if (value instanceof String) 
            System.out.println("它是String类型的值: " + value);
          else if (value instanceof Long) 
            System.out.println("它是Long类型的值: " + value);
          // 等等...
         
         return false;
      
   


在上面的这个自定义验证注解中,
@Constraint(validatedBy = StringChecker.class)
validatedBy里可以定义多个, 用括起来, 在这一行代码中, StringChecker类用来处理String类型的逻辑

这个内部类可以再外部定义, 这里是为了方便

class StringChecker implements ConstraintValidator<BankCard, String> 

用@Constraint注解, 必须实现ConstraintValidator接口
里面有两个泛型, 第一个是自定义的注解类, 第二个是需要验证的数据类型, 可以用Object, 表示所有类型都支持, 根据不同类型走不同逻辑方法.

这个接口里面有两个方法, initialize和isValid.
第一个是初始化验证器, 初始化完成后的结果让isValid调用,
第二个是验证逻辑, 不同的逻辑方法就是在这里实现. 返回true, 则验证通过,false则不通过, 然后会抛出message里面自定义的异常信息。

另外:

这个自定义注解逻辑处理类由于实现了ConstraintValidator接口,所以它默认被spring管理成bean, 所以可以在这个逻辑处理类里面用@Autowiredu或者@Resources注入别的服务,而且不用在类上面用@Compent注解成spring的bean.

自定义验证类型注解类里面由于是用于验证数据,一般在里面加上

String message() default “用户不存在或者不属于当前组织”;

Class<?>[] groups() default ;

Class<? extends Payload>[] payload() default ;

备注:

  • @Retention :用来说明该注解类的生命周期。它有以下三个参数:
  • RetentionPolicy.SOURCE : 注解只保留在源文件中
  • RetentionPolicy.CLASS : 注解保留在class文件中,在加载到JVM虚拟机时丢弃
  • RetentionPolicy.RUNTIME : 注解保留在程序运行期间,此时可以通过反射获得定义在某个类上的所有注解。
  • @Target : 用来说明该注解可以被声明在那些元素之前。
  • ElementType.TYPE:说明该注解只能被声明在一个类前。
  • ElementType.FIELD:说明该注解只能被声明在一个类的字段前。
  • ElementType.METHOD:说明该注解只能被声明在一个类的方法前。
  • ElementType.PARAMETER:说明该注解只能被声明在一个方法参数前。
  • ElementType.CONSTRUCTOR:说明该注解只能声明在一个类的构造方法前。
  • ElementType.LOCAL_VARIABLE:说明该注解只能声明在一个局部变量前。
  • ElementType.ANNOTATION_TYPE:说明该注解只能声明在一个注解类型前。
  • ElementType.PACKAGE:说明该注解只能声明在一个包名前。

以上是关于@Constraint自定义验证类型注解的主要内容,如果未能解决你的问题,请参考以下文章

@Constraint自定义验证类型注解

@Constraint自定义验证类型注解

springboot学习(二十二)_ 使用@Constraint注解自定义验证注解

自定义注解编写以及讲解(以异常处理为例)

自定义注解标签验证

自定义hibernate后端参数验证注解