SpringBoot Validator使用

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


Validator注册

启动时WebMvcAutoConfiguration将会自动获取Validator

springboot自定义配置文件放在哪里 springboot自定义validator_spring

获取Validator时,会优先获取已经注册的Validator,如果没有注册的Validator,则将自动创建Vaidator(new OptionalValidatorFactoryBean())

springboot自定义配置文件放在哪里 springboot自定义validator_java_02

springboot自定义配置文件放在哪里 springboot自定义validator_spring boot_03


而自动创建的ValidatorAdapotr将没有Validator,如图:

SpringValidator.java

springboot自定义配置文件放在哪里 springboot自定义validator_字符串_04

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

ConfigurableWebBindingInitializer.java

springboot自定义配置文件放在哪里 springboot自定义validator_字符串_05

SpringValidatorAdapoer.java

springboot自定义配置文件放在哪里 springboot自定义validator_字符串_06

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

所以如果想要使用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>

springboot自定义配置文件放在哪里 springboot自定义validator_spring boot_07


Validator是如何进行验证的

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

DispatcherServlet.java

springboot自定义配置文件放在哪里 springboot自定义validator_spring boot_08

  1. 然后开始解析参数

HandlerMethodArgumentResolverComposite.java

springboot自定义配置文件放在哪里 springboot自定义validator_字符串_09

  1. 解析参数时需要创建WebDataBind进行数据解析绑定[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
  2. springboot自定义配置文件放在哪里 springboot自定义validator_java_10

  3. 创建完后需要初始化DataBind,而初始化时就需要设置Validator,而设置Validator的条件就是上面说过的supports函数
  4. springboot自定义配置文件放在哪里 springboot自定义validator_java_11


  5. springboot自定义配置文件放在哪里 springboot自定义validator_java_12

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

RequestReponseBodyMethodProcess.java

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

AbstractMessageConverterMethodArgumentReslover.java

ValidationAnnotationUtils.java

springboot自定义配置文件放在哪里 springboot自定义validator_spring_13

  1. 再对捕获的类进行校验,校验就是通过前面所注册的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官网