SpringBoot各种参数效验

SpringBoot各种参数效验

原文章地址https://mp.weixin.qq.com/s/63_AKBz780xMf2YVyLAv5g

01 简单使用

  • 引入依赖

  • requestBody参数校验

  • requestParam/PathVariable参数校验

  • 统一异常处理

引入依赖

引入依赖

如果spring-boot版本小于2.3.x,spring-boot-starter-web会自动传入hibernate-validator依赖。如果spring-boot版本大于2.3.x,则需要手动引入依赖:

 <dependency>
     <groupId>org.hibernate</groupId>
     <artifactId>hibernate-validator</artifactId>
     <version>6.0.1.Final</version>
 </dependency>

对于web服务来说,为防止非法参数对业务造成影响,在Controller层一定要做参数校验的!大部分情况下,请求参数分为如下两种形式:

  • POST、PUT请求,使用requestBody传递参数;

  • GET请求,使用requestParam/PathVariable传递参数。

requestBody参数校验

POST、PUT请求一般会使用requestBody传递参数,这种情况下,后端使用DTO对象进行接收。只要给DTO对象加上@Validated或@Valid注解就能实现自动参数校验

 

DTO表示数据传输对象(Data Transfer Object),用于服务器和客户端之间交互传输使用的。在spring-web项目中可以表示用于接收请求参数的Bean对象。

在DTO字段上声明约束注解
 @Data
 public class ParamDto {
     
     @NotBlank(message = "姓名不能为空")
     private String name;
     
     @NotNull(message = "年龄不能为空")
     private Integer age;
     
     @NotBlank(message = "信息不能为空")
     private String message;
 }

 

注意事项:对于dto,@Validated或@Valid注解必须加在形参上,加在类上不生效

get的请求参数也能用dto接收,但不能用@RequestBody,否则会报错:org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing

requestParam/PathVariable参数校验

GET请求一般会使用requestParam/PathVariable传参。如果参数比较多(比如超过6个),还是推荐使用DTO对象接收。

如果在入参上声明约束注解(如@Min等)@Length等则必须在controller类上声明注解@Validated

如果校验失败,会抛出ConstraintViolationException异常。

统一异常处理

前面说过,如果校验失败,会抛出MethodArgumentNotValidException或者ConstraintViolationException异常。在实际项目开发中,通常会用统一异常处理来返回一个更友好的提示。

比如我们系统要求无论发送什么异常,http的状态码必须返回200,由业务码去区分系统的异常情况。

 

 @RestControllerAdvice
 public class GlobalExceptionHandler {
      /**
      * 效验参数异常捕获器
      * @param e
      * @return
      */
     @ExceptionHandler(MethodArgumentNotValidException.class)
     public String methodArgumentNotValidException(MethodArgumentNotValidException e){
         BindingResult bindingResult = e.getBindingResult();
         StringBuilder sb = new StringBuilder("校验失败:");
         for (FieldError fieldError : bindingResult.getFieldErrors()) {
             sb.append(fieldError.getField()).append(":").append(fieldError.getDefaultMessage()).append(", ");
        }
         String msg=null;
         if (sb.lastIndexOf(",")+2==sb.length()) {
             msg=sb.substring(0,sb.lastIndexOf(","));
        }else{
             msg = sb.toString();
        }
 ​
         return msg;
    }
     
     @ExceptionHandler(ConstraintViolationException.class)
     @ResponseStatus(HttpStatus.OK)
     @ResponseBody
     public Result handleConstraintViolationException(ConstraintViolationException ex) {
         return Result.fail(BusinessCode.参数校验失败, ex.getMessage());
    }
 }

注解

@ResponseStatus(HttpStatus.OK),返回正常的状态码200

@NotNull,@NotBlank,@NotEmpty的区别
  • @NotNull 验证任何类型的字段不为null

  • @NotBlank 验证字符串不为null且长度大于1

  • @NotEmpty 验证集合不为null,且长度大于1

其他注解

@Min,@Max 验证一个数字类型最小和最大,

@Length(min=1,max=11,message="错误提示") 验证字符串类型的长度

 

 

 

 

 

 

 

 

上一篇:如何通过多线程保证服务的可用性


下一篇:JPA的Dto Projection驼峰命名问题(未解决)