阅读 1316

Spring Boot 统一异常管理

前言

在日常开发中经常会出现各种异常,怎么处理这些统一处理这些异常成为了一个问题,Spring Boot 支持多种异常处理机制,今天我们就简单的介绍一下常用的统一异常处理机制。

@ControllerAdvice方式

通过使用@ControllerAdvice@ExceptionHandler定义统一的异常处理类,而不是在每个Controller中逐个定义。

HTML异常
定义统一的异常处理控制器
@ControllerAdvice
class GlobalExceptionHandler {

    public static final String DEFAULT_ERROR_VIEW = "error";

    @ExceptionHandler(value = Exception.class)
    public ModelAndView defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
        ModelAndView mav = new ModelAndView();
        mav.addObject("exception", e);
        mav.addObject("url", req.getRequestURL());
        mav.setViewName(DEFAULT_ERROR_VIEW);
        return mav;
    }
}
复制代码
定义统一的异常处理页面
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8" />
    <title>统一异常处理</title>
</head>
<body>
    <h1>Error Handler</h1>
    <div th:text="${url}"></div>
    <div th:text="${exception.message}"></div>
</body>
</html>
复制代码
JSON异常
定义统一的异常响应JSON
@Data
public class ErrorResult<T> {
	private Integer code;
    private String message;
    private String url;
    private T data;
}
复制代码
定义统一的异常处理控制器
@ControllerAdvice
public class GlobalExceptionHandler {
    //捕获自定义业务异常
    @ExceptionHandler(value = BizException.class)
    @ResponseBody
    public ErrorResult<Object> jsonErrorHandler(HttpServletRequest req,BizException e) throws Exception {
        ErrorResult<Object> r = new ErrorResult<>();
        r.setMessage(e.getMessage());
        r.setCode(ErrorInfo.ERROR);
        r.setUrl(req.getRequestURL().toString());
        return r;
    }
}
复制代码

2. BasicErrorController方式

使用这种方案,无需自己判断请求的接口是 HTML 还是 RESTful API

定义统一异常处理器
@Controller
@RequestMapping("/error")
public class GlobalErrorController extends BasicErrorController {

    @Autowired
    public GlobalErrorController(ErrorAttributes errorAttributes, ServerProperties serverProperties) {
        super(errorAttributes, serverProperties.getError());
    }

    @RequestMapping(produces = "text/html")
    @Override
    public ModelAndView errorHtml(HttpServletRequest request,
                                  HttpServletResponse response) {
        return super.errorHtml(request, response);
    }

    @RequestMapping
    @ResponseBody
    @Override
    @SuppressWarnings("unchecked")
    public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
        Map<String, Object> body = super.getErrorAttributes(request,
                isIncludeStackTrace(request, MediaType.ALL));

        String message = body.get("message") != null ? (String) body.get("message") : null;
        Integer statusCode = body.get("status") != null ? (Integer) body.get("status") : null;

        Object exception = body.get("exception");
        if (exception instanceof TradeBizException) {
            TradeBizException bre = (TradeBizException) exception;
            statusCode = bre.getCode();
        }

        Wrapper<Object> wrap = WrapMapper.wrap(statusCode == 0 ? Wrapper.ERROR_CODE : statusCode, message);
        Map res = null;
        try {
            ObjectMapper mapper = new ObjectMapper();
            String s = mapper.writeValueAsString(wrap);
            res = mapper.readValue(s, Map.class);
        } catch (IOException e) {
            e.printStackTrace();
        }

        HttpStatus status = super.getStatus(request);
        return new ResponseEntity<Map<String, Object>>(res, status);
    }
}
复制代码

参考文章

统一异常管理

Spring Boot中Web应用的统一异常处理

文章分类
后端
文章标签