SpringBoot Validator使用

SpringBoot Validator使用

官方文档优先: https://docs.spring.io/spring-boot/docs/2.7.6/reference/htmlsingle/


Validator注册

启动时WebMvcAutoConfiguration将会自动获取Validator

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XRz0SOoR-1672369985404)(/home/hhoa/snap/marktext/9/.config/marktext/images/2022-11-29-11-23-52-image.png)]

获取Validator时,会优先获取已经注册的Validator,如果没有注册的Validator,则将自动创建Vaidator(new OptionalValidatorFactoryBean())
在这里插入图片描述

在这里插入图片描述
而自动创建的ValidatorAdapotr将没有Validator,如图:

SpringValidator.java

在这里插入图片描述

如果没有Validator,则在数据到达时无法进行验证

ConfigurableWebBindingInitializer.java

SpringValidatorAdapoer.java

在这里插入图片描述

具体为什么无法验证呢?我们在后面对此做出讲解。

所以如果想要使用Validator功能,要么使用官方依赖,要么自定义Validator。

.gradle

implementation org.springframework.boot:spring-boot-starter-validationspring-boot-starter-validation

maven

<dependency> 
    <groupId>org.springframework.boot</groupId>  
    <artifactId>spring-boot-starter-validation</artifactId> 
</dependency>

在这里插入图片描述


Validator是如何进行验证的

  1. 首先DispatcherServlet.java开始处理数据

DispatcherServlet.java

  1. 然后开始解析参数

HandlerMethodArgumentResolverComposite.java

在这里插入图片描述

  1. 解析参数时需要创建WebDataBind进行数据解析绑定[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传在这里插入图片描述

  2. 创建完后需要初始化DataBind,而初始化时就需要设置Validator,而设置Validator的条件就是上面说过的supports函数
    在这里插入图片描述
    在这里插入图片描述

  3. 初始化完DataBind后,就需要解析参数并进行校验了

    RequestReponseBodyMethodProcess.java

    在这里插入图片描述

  4. 校验的过程就是先捕获所有带有Validated或Valid注解的类

    AbstractMessageConverterMethodArgumentReslover.java

    在这里插入图片描述

    ValidationAnnotationUtils.java

    在这里插入图片描述

  5. 再对捕获的类进行校验,校验就是通过前面所注册的Validator(自定义Validator Bean或官方spring-boot-starter-validation包等)进行的,这里就不多说了。

    DataBinder.java

    在这里插入图片描述


spring-boot-starter-validation 包

  1. Controller添加@Validated注解

    在这里插入图片描述

  2. Bean 添加约束

    public class AmsArticle implements Serializable {
          
             
    @Size(min = 2)
    private String title;
    
    }
    
注解 功能
@AssertFalse 可以为null,如果不为null的话必须为false
@AssertTrue 可以为null,如果不为null的话必须为true
@DecimalMax 设置不能超过最大值
@DecimalMin 设置不能超过最小值
@Digits 设置必须是数字且数字整数的位数和小数的位数必须在指定范围内
@Future 日期必须在当前日期的未来
@Past 日期必须在当前日期的过去
@Max 最大不得超过此最大值
@Min 最大不得小于此最小值
@NotNull 不能为null,可以是空
@Null 必须为null
@Pattern 必须满足指定的正则表达式
@Size 集合、数组、map等的size()值必须在指定范围内
@Email 必须是email格式
@Length 长度必须在指定范围内
@NotBlank 字符串不能为null,字符串trim()后也不能等于“”
@NotEmpty 不能为null,集合、数组、map等size()不能为0;字符串trim()后可以等于“”
@Range 值必须在指定范围内
@URL 必须是一个URL
  1. 全局ValidateException处理

    public class GlobalExceptionHandler {
          
          
    
    /**
     * 处理Validated校验异常
     * <p>
     * 注: 常见的ConstraintViolationException异常, 也属于ValidationException异常
     *
     * @param e
     *         捕获到的异常
     * @return 返回给前端的data
     */
        @ResponseStatus(code = HttpStatus.BAD_REQUEST)
        @ExceptionHandler(value = {
          
          BindException.class, ValidationException.class, MethodArgumentNotValidException.class})
        public Map<String, Object> handleParameterVerificationException(Exception e) {
          
          
            log.error(" handleParameterVerificationException has been invoked", e);
            Map<String, Object> resultMap = new HashMap<>(4);
            resultMap.put("code", "100001");
            String msg = null;
                if (e instanceof MethodArgumentNotValidException) {
          
          
                BindingResult bindingResult = ((MethodArgumentNotValidException) e).getBindingResult();
                // getFieldError获取的是第一个不合法的参数(P.S.如果有多个参数不合法的话)
                FieldError fieldError = bindingResult.getFieldError();
                if (fieldError != null) {
          
          
                    msg = fieldError.getDefaultMessage();
                }
            } else if (e instanceof BindException) {
          
          
                // getFieldError获取的是第一个不合法的参数(P.S.如果有多个参数不合法的话)
                FieldError fieldError = ((BindException) e).getFieldError();
                if (fieldError != null) {
          
          
                    msg = fieldError.getDefaultMessage();
                }
            } else if (e instanceof ConstraintViolationException) {
          
          
                /*
                 * ConstraintViolationException的e.getMessage()形如
                 *     {方法名}.{参数名}: {message}
                 *  这里只需要取后面的message即可
                 */
                msg = e.getMessage();
                if (msg != null) {
          
          
                    int lastIndex = msg.lastIndexOf(':');
                    if (lastIndex >= 0) {
          
          
                        msg = msg.substring(lastIndex + 1).trim();
                    }
                }
                /// ValidationException 的其它子类异常
            } else {
          
          
                msg = "处理参数时异常";
            }
            resultMap.put("msg", msg);
            return resultMap;
        }
    }
    

其他

官方文档…

参考:

  1. SpringBoot官网

猜你喜欢

转载自blog.csdn.net/HHoao/article/details/128492961
今日推荐