• 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
  • 相关阅读:
    gin框架
    C++vector的简单模拟实现
    Redis实战 - 01 Redis 和 SpringSecurity Oauth2 实现认证授权中心
    【微电网优化】基于matlab遗传算法求解微电网经济优化问题【含Matlab源码 2062期】
    芯片调试记录,芯片频率,添加摄像头,CAN,SPI
    springboot整合Excel填充数据
    MySQL学习笔记23
    【SNMP】snmp trap 与介绍、安装、命令以及Trap的发送与接收java实现
    Axios中每次发送post请求前都会发送options请求
    P3709 大爷的字符串题(莫队+离散)
  • 原文地址:https://blog.csdn.net/Java_zhujia/article/details/128145553