在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>