出发点是为了在系统抛出异常的时候,前端仍然可以获取到统一的报文格式,所以后端所有的异常都得捕获,并处理
Spring boot 在处理异常的时候,500/404默认都会转发到/error,而这个异常的处理类是
ErrorController,所以我们重写一个
ErrorController的子类即可:
@RestController
public 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);
}
@Override
public 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);
}
}