Springboot學習05-自定義錯誤頁面完整分析
阿新 • • 發佈:2018-12-22
Springboot學習06-自定義錯誤頁面完整分析
前言
接著上一篇部落格,繼續分析Springboot錯誤頁面問題
正文
1-自定義瀏覽器錯誤頁面(只要將自己的錯誤頁面放在指定的路徑下即可)
1-1-Springboot錯誤頁面匹配機制(以404錯誤為例):
- 1-在模板引擎下:找templates/error/404.html;如果沒有,則繼續匹配
- 2-在模板引擎下:找templates/error/4XX.html;如果沒有,則繼續匹配
- 3-在靜態資源下:找static/error/404.html;如果沒有,則繼續匹配
- 4-匹配最後的“圍牆”:WhiteLevel Erro Page頁面
1-2-補充說明
- 1-模板引擎下的匹配規則;原始碼分析,請參考本人部落格:https://www.cnblogs.com/wobuchifanqie/p/10144151.html
- 2-靜態資源下的錯誤頁面,不一定在static路徑下,只需要符合靜態資源對映規則即可;原始碼分析,請參考本人部落格:https://www.cnblogs.com/wobuchifanqie/p/10112302.html
- 3-WhiteLevel Erro Page頁面是動態生成,原始碼分析,請參考本人部落格:https://www.cnblogs.com/wobuchifanqie/p/10144151.html
1-3-demo示例
1-4-簡單自定義頁面的缺陷
- 1-只能展示Springboot預設的返回資訊:timestamp時間戳;status狀態;error錯誤提示;exception異常物件;message異常訊息等簡單返回資訊;無法返回自定義業務資料
2-自定義錯誤的json
2-1-原始碼分析
//1-自定義Exception public class DataException extends RuntimeException {public DataException() { super("資料不存在!"); } } //2-自定義handleException方法 @ControllerAdvice public class MyExceptionHandler { @ResponseBody @ExceptionHandler(DataException.class) public Map<String,Object> handleException(Exception e){ Map<String,Object> map = new HashMap<String,Object>(); map.put("code","data error"); map.put("msg",e.getMessage()); return map; } } //3-測試介面 @Controller public class DemoController { @GetMapping(value="test") public String toExceptionPage( ){ throw new DataException(); } }
2-2-頁面效果
2-3-缺點:瀏覽器請求也返回了json資料;不符合期望
3-自定義錯誤頁面,自適應瀏覽器請求和客戶端請求
3-1-原始碼示例
//1-自定義Exception public class DataException extends RuntimeException { public DataException() { super("資料不存在!"); } } //2-自定義handleException方法 @ControllerAdvice public class MyExceptionHandler { @ExceptionHandler(DataException.class) public String handleException(Exception e, HttpServletRequest request){ //傳入我們自己的錯誤狀態碼 4xx 5xx,否則就不會進入定製錯誤頁面的解析流程 request.setAttribute("javax.servlet.error.status_code",500); Map<String,Object> map = new HashMap<String,Object>(); map.put("code","data error"); map.put("msg",e.getMessage()); return "forward:/error"; } } //3-測試介面 @Controller public class DemoController { @GetMapping(value="test") public String toExceptionPage( ){ throw new DataException(); } }
3-2-demo示例
3-3-缺點:雖然已經相容了瀏覽器請求和客戶端請求;但是無法展示業務資料
4-自定義頁面終版:自適應瀏覽器請求和客戶端請求,並且允許返回業務資料
4-1-原始碼解析
//1-自定義ErrorAttributes @Component public class MyErrorAttributes extends DefaultErrorAttributes { //重寫getErrorAttributes方法-新增自己的專案資料 public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) { Map<String, Object> errorAttributes = super.getErrorAttributes(webRequest,includeStackTrace); errorAttributes.put("myName","我不吃番茄");//自定義資料 errorAttributes.put("myAge","不告訴你");//自定義資料 return errorAttributes; } } //2-自定義Exception public class DataException extends RuntimeException { public DataException() { super("資料不存在!"); } } //3-自定義handleException方法 @ControllerAdvice public class MyExceptionHandler { @ExceptionHandler(DataException.class) public String handleException(Exception e, HttpServletRequest request){ //傳入我們自己的錯誤狀態碼 4xx 5xx,否則就不會進入定製錯誤頁面的解析流程 request.setAttribute("javax.servlet.error.status_code",500);//這裡只接受500狀態錯誤 Map<String,Object> map = new HashMap<String,Object>(); map.put("code","data error"); map.put("msg",e.getMessage()); request.setAttribute("extra", map);//放在request中的資料,在前端頁面中都可以取出來 return "forward:/error";//並不直接返回檢視名稱或json資料,請求轉發到"/error",讓Springboo按流程處理處理,從而達到自適應瀏覽器請求和客戶端請求; } } //4-測試介面 @Controller public class DemoController { @GetMapping(value="test") public String toExceptionPage( ){ throw new DataException();//主動丟擲一個500錯誤,用於測試 } }
//templates/error/5XX.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>自定義頁面 --路徑:templates/error/5XX.html頁面 --優先級別:2</h1> <h1>status:[[${status}]]</h1> <h2>timestamp:[[${timestamp}]]</h2> <h2>exception:[[${exception}]]</h2> <h2>myName:[[${myName}]]</h2> <h2>myAge:[[${myAge}]]</h2> <h2>extra-code:[[${extra.code}]]</h2> <h2>extra-msg:[[${extra.msg}]]</h2> </body> </html>
4-2-demo示例