出发点是为了在系统抛出异常的时候,前端仍然可以获取到统一的报文格式,所以后端所有的异常都得捕获,并处理
Spring boot 在处理异常的时候,500/404默认都会转发到/error,而这个异常的处理类是
ErrorController,所以我们重写一个
ErrorController的子类即可:
@RestControllerpublic class GlobalExceptionController extends AbstractErrorController {private static final Logger LOGGER = LoggerFactory.getLogger(GlobalExceptionController.class);private static final String ERROR_PATH = "/error";public GlobalExceptionController(ErrorAttributes errorAttributes) {super(errorAttributes);}@Overridepublic String getErrorPath() {return ERROR_PATH;}@RequestMapping(value = ERROR_PATH)public Response error(HttpServletRequest request) {WebRequest webRequest = new ServletWebRequest(request);Throwable e = getError(webRequest);if (e == null) {Map<String, Object> attributes = getErrorAttributes(request, false);Object timestamp = attributes.get("timestamp");Object status = attributes.get("status");String error = attributes.get("error").toString();Object path = attributes.get("path");LOGGER.error("status {} error {} path{} timestamp {}", status, error, path, timestamp);return Response.failure(Integer.parseInt(status.toString()), error);}if (e instanceof TokenExpiredException) {TokenExpiredException tokenExpiredException = (TokenExpiredException) e;return Response.failure(tokenExpiredException.getHttpStatus().value(), tokenExpiredException.getHttpStatus().getReasonPhrase());} else if (e instanceof CodeException) {CodeException codeException = (CodeException) e;String message = e.getMessage();if (StringUtils.isEmpty(message)) {message = String.format("[%s][%s]", codeException.getErrCode(), codeException.getErrMsg());}return Response.failure(message);} else {return Response.failure("系统繁忙,请稍后再试");}}private Throwable getError(WebRequest webRequest) {return (Throwable) this.getAttribute(webRequest, "javax.servlet.error.exception");}private Object getAttribute(RequestAttributes requestAttributes, String name) {return requestAttributes.getAttribute(name, 0);}}
Spring Boot 全局异常处理(400/404/500) 顺便解决过滤器中异常未捕获到的问题 让RestApi 任何时候都能获取统一的格式代码