future.png
珠玑随笔

联系:

future.png

版权 © 2022 by Hsu

技术: Gatsby

样式: Bulma

许可: CC BY NC SA 4.0

Spring Boot DTO 层的数据验证及错误拦截

2022年01月10日

Hsu

2分钟

背景

数据传输对象(DTO)(Data Transfer Object),用来接收前端数据并进行验证.

定义

@Getter
@Setter
public class UserDto {

  @NotBlank(message = "用户名不能为空!")
  private String username;

  @NotBlank(message = "密码不能为空!")
  private String password;

  @NotBlank(message = "电子邮箱不能为空!")
  private String email;

  @NotNull(message = "生日不能为空!")
  private Date birthDate;

  @NotNull(message = "房间名不能为空!")
  private int roomNumber;
}

使用 @Valid 装饰器开启验证功能.

@RestController
public class DemoController {

  @PostMapping("/user")
  User createUser(@Valid @RequestBody UserDto user) {
    return userService.createUser(user);
  }
}

异常

如果数据不是标准 JSON 格式, 抛出 HttpMessageNotReadableException 异常.

如果无法匹配验证规则, 抛出 MethodArgumentNotValidException 异常, 该异常是数组.

@RestControllerAdvice
public class GlobalExceptionHandler {

  @ExceptionHandler(HttpMessageNotReadableException.class)
  public final ResponseEntity<ExceptionResponse> handleAllExceptions(
    HttpMessageNotReadableException ex, WebRequest request) {

    ExceptionResponse exceptionResponse = new ExceptionResponse(400, "参数不合法");

    return new ResponseEntity<>(exceptionResponse, HttpStatus.BAD_REQUEST);
  }

  @ExceptionHandler(MethodArgumentNotValidException.class)
  public ResponseEntity<?> handleMethodArgumentNotValidException(
    MethodArgumentNotValidException ex, WebRequest request) {
    List<String> errors = new ArrayList<>();

    // 获取所有验证错误信息
    ex.getBindingResult().getAllErrors()
                         .forEach(i -> errors.add(i.getDefaultMessage()));

    Map<String, List<String>> result = new HashMap<>();

    result.put("errors", errors);

    ExceptionResponse exceptionResponse = new ExceptionResponse(400, result);

    return new ResponseEntity<>(exceptionResponse, HttpStatus.BAD_REQUEST);
  }
}