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示例