在spring boot 中,Controller 中抛出的异常默认交给 /error 来处理(Controller 中匹配此路径的方法),应用程序可以将 /error 映射到一个特定的Controller 中处理,应用可以继承 AbstractErrorController 来统一处理系统的各种异常。
请看下面代码,有解释。读者可以复制这段代码到项目中,故意抛出异常来测试,代码中示例的页面error.btl 读者请自己写。btl 即beetl ,是一种页面技术,类似freemarker和jsp。
@RestController
public class ErrorController extends AbstractErrorController {
Log log = LogFactory.getLog(ErrorController.class);
/**
* 因为继承的AbstractErrorController没有无参数构造器,所以要添加这个构造器
* @param errorAttributes
*/
public ErrorController(ErrorAttributes errorAttributes) {
super(errorAttributes);
}
@RequestMapping("error")
public ModelAndView getErrorPath(HttpServletRequest request, HttpServletResponse response) {
Map<String, Object> model =
Collections.unmodifiableMap(getErrorAttributes(request, false));
//获取异常,有可能为空
Throwable cause = getCause(request);
int status = (Integer) model.get("status");
//错误信息
String message = (String) model.get("message");
//友好提示
String errorMessage = getErrorMessage(cause);
//后台打印日志信息方便差错
log.info(status + "," + message, cause);
response.setStatus(status);
if (!isJsonRequest(request)) {
//error.btl 显示详细的错误信息。这个页面您自己写,根据下面的属性获取信息。
ModelAndView view = new ModelAndView("/error.btl");
view.addAllObjects(model);
view.addObject("errorMessage", errorMessage);
view.addObject("status", status);
view.addObject("cause", cause);
view.addObject("message", message);
return view;
} else {
//如果请求是json 类型数据
Map error = new HashMap();
error.put("success", false);
error.put("errorMessage", errorMessage);
error.put("message", message);
//writeJson(response,error);
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
try {
response.getWriter().write(error.toString());
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
/**
* 获取通俗的异常信息给用户
* @param ex
* @return
*/
protected String getErrorMessage(Throwable ex) {
return "服务器错误,请联系管理员。";
}
/**
* 获取异常的具体信息
* @param request
* @return Throwable
*/
protected Throwable getCause(HttpServletRequest request) {
Throwable error = (Throwable) request.getAttribute("javax.servlet.error.exception");
if (error != null) {
while (error instanceof ServletException && error.getCause() != null) {
error = ((ServletException) error).getCause();
}
}
return error;
}
/**
* 判断response 请求的是否json 类型
* @param request
* @return boolean
*/
protected boolean isJsonRequest(HttpServletRequest request) {
String requestURI = (String) request.getAttribute("javax.servlet.error.request_uri");
String header = request.getHeader("Accept");
if (requestURI != null && requestURI.endsWith(".json")) {
return true;
} else if (header.contains("application/json")) {
return true;
} else {
return false;
}
}
@Override
public String getErrorPath() {
return null;
}
}
把本人简易的错误展示页面 error.btl 贴一下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>error message</title>
</head>
<body>
<h5>error message</h5>
<p>${status}</p>
<p>${errorMessage}</p>
<p>${cause}</p>
<p>${message}</p>
</body>
</html>