• SpringBoot接口 - 如何优雅的写Controller并统一异常处理?


    内容目录

    • 为什么要优雅的处理异常

    • 实现案例@ControllerAdvice异常统一处理Controller接口运行测试

    • 进一步理解@ControllerAdvice还可以怎么用?@ControllerAdvice是如何起作用的(原理)?

    • 示例源码

    • 更多内容


    SpringBoot接口如何对异常进行统一封装,并统一返回呢?以上文的参数校验为例,如何优雅的将参数校验的错误信息统一处理并封装返回呢?@pdai

    为什么要优雅的处理异常

    如果我们不统一的处理异常,经常会在controller层有大量的异常处理的代码, 比如:

    1. @Slf4j
    2. @Api(value = "User Interfaces", tags = "User Interfaces")
    3. @RestController
    4. @RequestMapping("/user")
    5. public class UserController {
    6. /**
    7. * http://localhost:8080/user/add .
    8. *
    9. * @param userParam user param
    10. * @return user
    11. */
    12. @ApiOperation("Add User")
    13. @ApiImplicitParam(name = "userParam", type = "body", dataTypeClass = UserParam.class, required = true)
    14. @PostMapping("add")
    15. public ResponseEntity add(@Valid @RequestBody UserParam userParam) {
    16. // 每个接口充斥着大量的异常处理
    17. try {
    18. // do something
    19. } catch(Exception e) {
    20. return ResponseEntity.fail("error");
    21. }
    22. return ResponseEntity.ok("success");
    23. }
    24. }

    那怎么实现统一的异常处理,特别是结合参数校验等封装?

    实现案例

    简单展示通过@ControllerAdvice进行统一异常处理。

    @ControllerAdvice异常统一处理

    对于400参数错误异常

    1. /**
    2. * Global exception handler.
    3. *
    4. * @author pdai
    5. */
    6. @Slf4j
    7. @RestControllerAdvice
    8. public class GlobalExceptionHandler {
    9. /**
    10. * exception handler for bad request.
    11. *
    12. * @param e
    13. * exception
    14. * @return ResponseResult
    15. */
    16. @ResponseBody
    17. @ResponseStatus(code = HttpStatus.BAD_REQUEST)
    18. @ExceptionHandler(value = { BindException.class, ValidationException.class, MethodArgumentNotValidException.class })
    19. public ResponseResult<ExceptionData> handleParameterVerificationException(@NonNull Exception e) {
    20. ExceptionData.ExceptionDataBuilder exceptionDataBuilder = ExceptionData.builder();
    21. log.warn("Exception: {}", e.getMessage());
    22. if (e instanceof BindException) {
    23. BindingResult bindingResult = ((MethodArgumentNotValidException) e).getBindingResult();
    24. bindingResult.getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage)
    25. .forEach(exceptionDataBuilder::error);
    26. } else if (e instanceof ConstraintViolationException) {
    27. if (e.getMessage() != null) {
    28. exceptionDataBuilder.error(e.getMessage());
    29. }
    30. } else {
    31. exceptionDataBuilder.error("invalid parameter");
    32. }
    33. return ResponseResultEntity.fail(exceptionDataBuilder.build(), "invalid parameter");
    34. }
    35. }

    对于自定义异常

    1. /**
    2. * handle business exception.
    3. *
    4. * @param businessException
    5. * business exception
    6. * @return ResponseResult
    7. */
    8. @ResponseBody
    9. @ExceptionHandler(BusinessExc
  • 相关阅读:
    代码随想录训练营二刷第二十三天 | 669. 修剪二叉搜索树 108.将有序数组转换为二叉搜索树 538.把二叉搜索树转换为累加树
    EVPN基本原理
    B. Sorted Adjacent Differences
    Python开发运维:Python3.7安装Django3.2
    忘记密码,如何解除Excel的限制保护?
    JUC编程中锁引发的“见解”
    【react-笔记】
    选择最佳路线(单源最短路扩展应用)
    同步异常、External abort、Serror、prefetch abort、data abort的区别
    android HAL 执行权限写法
  • 原文地址:https://blog.csdn.net/Java_zhujia/article/details/128145553