实际项目开发中,对于请求参数校验是必不可少的,现实中很多人校验参数都是写在service中,代码极其不友好。
普通型
| 1 | @PostMapping("/user/add") | 
每个字段都依靠if来进行判断,代码量多不说还非常不友好
优雅型
validator来帮我们实现优雅的校验参数,validator内置很多注解,如@NotNull、@NotEmpty等。
UserDTO增加验证注解1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20@Data
public class UserDTO {
    /**
     * 登录名
     */
    @NotEmpty(message = "登录名不能为空")
    private String loginName;
    /**
     * 登录密码
     */
    @NotEmpty(message = "登录密码不能为空")
    private String password;
    /**
     * 手机号码
     */
    @NotEmpty(message = "手机号码不能为空")
    private String phone;
}
Controller修改后1
2
3
4
5@PostMapping("/user/add")
public ResultVO<Long> add(@Validated @RequestBody UserDTO userDTO) {
    Long id = userService.insert(userDTO);
    return ResultVO.ok().data(id);
}
只需要在入参增加@Validated即可自动校验参数,校验不通过则会抛出异常。因此我们还需要结合统一异常捕获即可优雅的校验参数。
统一校验异常捕获
只需新建一个类打上@RestControllerAdvice注解即可自动捕获异常1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56@RestControllerAdvice
public class ApiExceptionHandle {
    /**
     * 校验参数异常统一处理
     *
     * @param e
     * @return
     * @Validated @RequestBody 没有RequestBody时候抛出此异常
     * https://github.com/spring-projects/spring-framework/issues/14790
     */
    @ExceptionHandler(BindException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ResultVO handleBindException(BindException e) {
        log.error("参数校验异常", e);
        BindingResult bindingResult = e.getBindingResult();
        return ResultVO.failed().msg(bindingResult.getFieldError().getDefaultMessage());
    }
    /**
     * 校验参数异常统一处理
     *
     * @param e
     * @return
     * @Validated @RequestBody 一起的时候抛出此异常
     * https://github.com/spring-projects/spring-framework/issues/14790
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ResultVO handleMethodArgumentNotValid(MethodArgumentNotValidException e) {
        log.error("参数校验异常", e);
        BindingResult bindingResult = e.getBindingResult();
        StringBuilder stringBuilder = new StringBuilder();
        for (FieldError error : bindingResult.getFieldErrors()) {
            String field = error.getField();
            Object value = error.getRejectedValue();
            String msg = error.getDefaultMessage();
            String message = String.format("错误字段:%s,错误值:%s,原因:%s;", field, value, msg);
            stringBuilder.append(message).append("\r\n");
        }
        return ResultVO.failed().msg(stringBuilder.toString());
    }
    /**
     * 其他异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public Object handleException(HttpServletRequest request, HandlerMethod handlerMethod, Exception e) {
        log.error("内部错误", e);
        return ResultVO.failed().msg(ErrCodeEnum.INTERNAL_SERVER_ERROR.getMsg());
    }
}
更详细的校验可参考另一篇文章:参数校验异常处理