SpringBoot 使用validation数据校验之自定义校验注解·源码分析+实例 - 第410篇

缘起

         在前面我们介绍了validation的基本使用以及分组校验,但是我们会发现有些场景下,上面提供的注解不能满足我们多样化的需求,那这种情况下,要怎么办呢?

         那我们会想validation框架是否允许我们自定义校验注解呢?

         如果可以的话,那么问题就不攻自破了。欧了,这节我们就来一探究竟。

         Spring Boot validation系列:

(1)✅《SpringBoot 使用validation数据校验-超级详细超级多干货

(2)✅《SpringBoot 使用validation数据校验之分组校验怎么玩?·分组还有这么多的讲究

(3)✅《SpringBoot 使用validation数据校验之自定义校验注解·源码分析+实例》

(4)《SpringBoot 使用validation数据校验之国际化问题怎么搞?》满满的干货

         这一节我们先来看看《SpringBoot 使用validation数据校验之自定义校验注解》。

一、如何实现

         具体要怎么实现呢,最简单的方式就是百度找个例子,就可以看看别人怎么搞就可以搞定了。

         但这里我采用解读源码的方式进行探索(要是百度没有例子的话,那不是就玩玩了)。

         这里我们看看@Email是如何实现的?

1.1 进入到@Email

         进入到注解Email

                           

         这里有一个重要的属性@Constraint(validatedBy = { }):约束/限定,被校验,但是这里居然没有指向具体的实现类,那就是底层自己进行约定俗成进行查找了。

         那我们查找Email可以可以找到搜索出来EmailValidator,这个类很有可能就是它的实现类。

1.2 进入到EmailValidator

         进入到EmailValidator:



         可以看到核心的两个方法,一个方法用于初始化,一个方法用于校验。

         此类又是继承了AbstractEmailValidator,我们进入看下:

         所以这里的核心是接口ConstraintValidator:

         到这里我们就有了一个大概的思路了:

(1)定义注解接口

(2)通过实现ConstraintValidator来实现注解

二、实现一个电话验证的例子

2.1步骤说明

(1)定义注解接口

(2)通过实现ConstraintValidator来实现注解

2.2 具体编码

2.2.1 定义注解Mobile

         定义注解:

import javax.validation.Constraint;import javax.validation.Payload;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** * 电话校验 * * @author 悟纤「公众号SpringBoot」 * @date 2021-10-15 * @slogan 大道至简 悟在天成 */@Target({ElementType.FIELD, ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)@Constraint(validatedBy={MobileValidator.class})public @interface Mobile {    String message() default"手机号校验错误";    Class<?>[] groups() default {};    Class<? extends Payload>[] payload() default {};}

         注解的实现:

2.2.2 注解的实现

import javax.validation.ConstraintValidator;import javax.validation.ConstraintValidatorContext;import java.util.regex.Matcher;import java.util.regex.Pattern;/** * Mobile校验 的实现类 * * @author 悟纤「公众号SpringBoot」 * @date 2021-10-15 * @slogan 大道至简 悟在天成 */public class MobileValidator implements ConstraintValidator<Mobile,String> {    //电话正则表达式    private  Pattern p = Pattern.compile("^0?1[1|2|3|4|5|6|7|8|9][0-9]\\d{8}$");    //初始化方法 - 非必须要实现//    @Override//    public void initialize(Mobile constraintAnnotation) {////    }    @Override    public boolean isValid(String value, ConstraintValidatorContext context) {        System.out.println(value);        if(value == null){            //如果没有的情况下?认为是正确的            return true;        }        Matcher m = p.matcher(value);        boolean b = m.matches();        return b;    }}

2.2.3 使用自定义注解

         这里就可以使用我们自定的注解了@Mobile:

@NotBlank(message = "手机号不能为空")@Mobile(message="手机号格式有误")private String mobile;

         到这里自定义注解就搞定了,是不是很轻松,很easy.

         当然对于分组校验,我们这个也是支持的:

@NotBlank(message = "手机号不能为空")@Mobile(message="手机号格式有误",groups ={ ValidGroup.Insert.class})private String mobile;

2.3 更简单的实现方式

@Target({ElementType.FIELD, ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)//@Constraint(validatedBy={MobileValidator.class})@Constraint(validatedBy = {})@Pattern(regexp = "^0?1[1|2|3|4|5|6|7|8|9][0-9]\\d{8}$")public @interface Mobile {    String message() default"手机号校验错误";    Class<?>[] groups() default {};    Class<? extends Payload>[] payload() default {};}

         这里使用@Pattern进行实现,那么@Constraint可以不需要具体的实现了。


购买完整视频,请前往:http://www.mark-to-win.com/TeacherV2.html?id=287