前言
后端开发API的时候经常遇到要验证前端传过来的参数。一个一个的校验未免太不优雅了。那么使用springboot怎么优雅解决呢?
传统的校验参数的方法
传统的方式,会将前端传过来的参数一一校验,虽然也能达到效果,但是耗费了精力,代码也比较长
    @RequestMapping("add")
    public R<String> add( @RequestBody Banner banner){
        R<String> r =new R<>();
        if (StringUtils.isEmpty(banner.getName())) {
            return r.fail("名字不能为空");
        }
        if (StringUtils.isEmpty(banner.getUrl())) {
            return r.fail("url不能为空");
        }
        //假装有业务操作
        return r.success("ok");
    }
更简洁的校验方式
我们可以使用spring提供的validation组件
<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-validation</artifactId>
</dependency>
首先需要设计一个入参的对象
@Data
public class Banner implements Serializable {
    /**
     * 名字
     */
    private String name;
    /**
     * 链接
     */
    private String url;
}
当我们需要对指定的入参进行校验的时候,使用注解就能指定校验规则(支持多个)
下面是封装好的规则,找到需要的直接使用就可以了
| 注解 | 规则 | 
|---|---|
| @Null | 被注释的元素必须为 null | 
| @NotNull | 被注释的元素必须不为 null | 
| @AssertTrue | 被注释的元素必须为 true | 
| @AssertFalse | 被注释的元素必须为 false | 
| @Min(value) | 被注释的元素必须是一个数字,其值必须大于等于指定的最小值 | 
| @Max(value) | 被注释的元素必须是一个数字,其值必须小于等于指定的最大值 | 
| @DecimalMin(value) | 被注释的元素必须是一个数字,其值必须小于等于指定的最小值 | 
| @DecimalMax(value) | 被注释的元素必须是一个数字,其值必须小于等于指定的最大值 | 
| @Size(max,min) | 被注释的元素的大小必须在指定的范国内 | 
| @Digits (integer, fraction) | 被注释的元素必须是一个数宇,其值必须在可接受的范田内 | 
| @Past | 被注释的元素必须是一个过去的日期 | 
| @Future | 被注释的元素必须是一个将来的日期 | 
| @Pattern (value) | 被注释的元素必须符合指定的正则表达式 | 
当我们需要name、url这两个参数不能为空时,选择加上@NotNull注解就可以了
然后再完善下controller,在入参的地方加上@Vaild,就代表需要做参数校验
@RequestMapping("banner")
@RestController
public class BannerController {
    @RequestMapping("add")
    public R<String> add(@Valid @RequestBody Banner banner){
        R<String> r =new R<>();
        //假装有业务逻辑代码在这里调用
        return r.success("ok");
    }
}
参数校验效果
当我们把参数设置为不能为空,就可以启动web服务试试效果了

缺参数的时候

完整参数的时候
上面图片展示了,有参数校验通过的情况,和参数校验不通过的情况。我们能看到,在校验不通过的时候,响应的code 是
400。这样虽然参数校验到位了,但是报错也不够友好,不利于后续排查问题。所以我们希望当参数不合规时,把错误的的原因通过接口返回。
优化返回参数
我们在控制台发现刚刚出现参数校验不通过的时候,实际上是抛出了一个异常

抛出异常
我们可以试试将这个异常捕获,然后将错误信息抓出来返回给客户端
首先来看下异常里面有哪些我们可以使用的信息
1. 全局异常控制
@ControllerAdvice
@ResponseBody
public class ExceptionHandle {
    @ExceptionHandler
    public R ParamExceptionHandle(MethodArgumentNotValidException e){
        System.out.println(e);//这里打断点,看看异常类里有什么东西
        return null;
    }
}
通过将异常捕获器,看看异常里面的内容

错误信息
从错误消息中我们可以看到有校验不通过的字段名和默认的错误消息
那我们把这两个字段组合一下,就变成了"url"+"字段"+"不能为null”
2. 下面进行对全局异常捕获的改造
@Slf4j
@ControllerAdvice
@ResponseBody
public class ExceptionHandle {
    @ExceptionHandler
    public R ParamExceptionHandle(MethodArgumentNotValidException e){
        log.info("捕获参数校验异常",e);
        List<String> failError= new ArrayList<>();
        for (FieldError fieldError : e.getBindingResult().getFieldErrors()) {
            String field = fieldError.getField();//字段名
            String defaultMessage = fieldError.getDefaultMessage();
            StringBuilder sb=new StringBuilder();
            sb.append("参数:").append(field).append(",校验异常。").append("原因:").append(defaultMessage);
            failError.add(sb.toString());
        }
        R<List<String>> r=new R<>();
        return r.fail(failError.toString());
    }
}
3.重启服务看看效果

单个参数校验不通过

多个参数校验不通过

参数校验通过
尾巴
spring提供的validate工具结合全局异常管理,可以让控制器瘦身,减少代码量的同时,在设计入参字段的同时设计校验规则,更符合直觉,不容易出错。感谢阅读!如果觉得我内容还不错的话,记得关注和点赞