如何实现后端开发框架(二)-全局异常处理

后续文章更新请关注我的个人博客

https://www.randy0098.com

如何实现后端开发框架(二)-全局异常处理

1. 问题描述

后端系统开发时需要处理各种异常情况,有些是框架本身的异常,有些是业务系统自定义的异常,如何将这些异常信息封装成统一的数据结构,然后返回给前端进行显示和处理呢?

在《如何实现后端开发框架(一)-自动封装返回值》文章里后端的数据结构已经封装成统一的数据结构了(如下所示),那么异常信息是否也能使用同样的数据结构呢?

{
    "code": 200,
    "message": "成功",
    "data": {
        "xxx": "xxx",
        "xxx": "xxx"
}

2. 实现思路

使用Spring中的@ControllerAdvice配合@ExceptionHandler来实现系统中的全局异常处理。

3. 实现步骤

3.1 实现自定义异常

/** 自定义异常基类 */
public class MyBaseException extends RuntimeException {
  protected ResultCode resultCode;

  public MyBaseException() {
    super();
  }

  public MyBaseException(String message) {
    super(message);
  }

  public MyBaseException(ResultCode resultCode) {
    super(resultCode.getMessage());
    this.resultCode = resultCode;
  }

  public ResultCode getResultCode() {
    return resultCode;
  }

  public void setResultCode(ResultCode resultCode) {
    this.resultCode = resultCode;
  }
}
/** 自定义业务异常 */
public class BusinessException extends MyBaseException {
  public BusinessException(String message) {
    super(message);
  }

  public BusinessException(ResultCode resultCode) {
    super(resultCode);
  }
}

3.2 实现全局异常处理

/** 全局异常处理 */
@ControllerAdvice
public class GlobalExceptionHandler {
  private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

  /**
   * 处理自定义业务异常
   *
   * @param request
   * @param response
   * @param businessException
   * @return
   */
  @ExceptionHandler(BusinessException.class)
  @ResponseBody
  public Object businessException(
      HttpServletRequest request,
      HttpServletResponse response,
      BusinessException businessException) {
    // 设置HTTP状态码
    response.setStatus(ResultCode.FAIL.getCode());
    // 设置前端返回值
    MyResult result = new MyResult();
    // 当ResultCode存在时按它返回异常信息
    ResultCode resultCode = businessException.getResultCode();
    if (resultCode != null) {
      result.setCode(resultCode.getCode());
      result.setMessage(resultCode.getMessage());
    }
    // 当ResultCode不存在时就按message异常信息
    else {
      result.setCode(ResultCode.FAIL.getCode());
      result.setMessage(businessException.getMessage());
    }
    return result;
  }

  /**
   * 处理系统中的所有Exception异常
   *
   * @param request
   * @param response
   * @param exception
   * @return
   */
  @ExceptionHandler(Exception.class)
  @ResponseBody
  public Object commonException(
      HttpServletRequest request, HttpServletResponse response, Exception exception) {
    response.setStatus(ResultCode.FAIL.getCode());
    MyResult result = new MyResult();
    result.setCode(ResultCode.FAIL.getCode());
    result.setMessage("系统异常");
    String str = getExceptionStackTrace(exception);
    result.setData(str);
    return result;
  }

  private String getExceptionStackTrace(Exception exception) {
    StringWriter sw = new StringWriter();
    exception.printStackTrace(new PrintWriter(sw, true));
    String str = sw.toString();
    logger.error(str);
    return str;
  }
}

4. 测试代码

@Slf4j
@RestController
@RequestMapping("/test")
public class TestController {
  @GetMapping(value = "/test1")
  public int test1() {
    int result = 1 / 0;
    return result;
  }

  @GetMapping(value = "/test2")
  public void test2() {
    throw new BusinessException("业务异常1");
  }

  @GetMapping(value = "/test3")
  public void test3() {
    throw new BusinessException(ResultCode.FAIL);
  }
}

5. 完整代码

完整代码见以下Git仓库中的global-exception子项目:

https://github.com/randy0098/framework-samples

6. 后续文章更新请关注我的个人博客

https://www.randy0098.com

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值