springboot開發之配置自定義的錯誤介面和錯誤資訊
如何定製錯誤頁面?
(1)在有模板引擎的情況下:在templates資料夾下的error/狀態碼;即將錯誤頁面命名為:錯誤狀態碼.html放在templates資料夾裡面的error資料夾下,發生此狀態碼的錯誤會來到對應的頁面。
頁面可以獲得的資訊:
timestamp:時間
status:狀態碼
error:錯誤提示
exception:異常物件
message:異常訊息
errors:JSR303資料校驗的錯誤都在這裡
(2)如果沒有模板引擎,就在靜態資原始檔static下的error資料夾下找。
(3)如果都沒有,則返回系統的預設錯誤頁面。
在錯誤頁面可以這麼獲取到資料:
<h1>status:[[${status}]]</h1> <h2>timestamp:[[${timestamp}]]</h2>
如何定製錯誤的json資料?
首先我們在com.gong.springbootcurd下新建一個exception資料夾,該資料夾中定義一個異常:UserNoExistException.java
package com.gong.springbootcurd.exception; public class UserNotExistException extends RuntimeException { public UserNotExistException() { super("使用者不存在"); } }
然後在com.gong.springbootcurd.component下新建一個異常處理器:MyExceptionHandler.java
package com.gong.springbootcurd.component; import com.gong.springbootcurd.exception.UserNotExistException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest; import java.util.HashMap; import java.util.Map; @ControllerAdvice public class MyExceptionHandler { //1、瀏覽器客戶端返回的都是json @ResponseBody @ExceptionHandler(UserNotExistException.class) public Map<String,Object> handleException(Exception e){ Map<String,Object> map = new HashMap<>(); map.put("code","user.notexist"); map.put("message",e.getMessage()); return map; } }
在com.gong.springbootcurd.controller的HelloController.java中新增:
@ResponseBody @RequestMapping("/hello") public String hello(@RequestParam("user") String user){ if(!user.equals("aaa")){ throw new UserNotExistException(); } return "hello world"; }
我們在伺服器種模擬請求:
會顯示我們自定的json錯誤資訊。
如何設定自適應的顯示錯誤頁面?
也就是說瀏覽器顯示的就是錯誤頁面,而客戶端顯示的是json的錯誤資訊。
修改MyExceptionHandler.java裡面為:
@ExceptionHandler(UserNotExistException.class) public String handleException(Exception e, HttpServletRequest request){ Map<String,Object> map = new HashMap<>(); //傳入我們自己的錯誤狀態碼 4xx 5xx /** * Integer statusCode = (Integer) request .getAttribute("javax.servlet.error.status_code"); */ request.setAttribute("javax.servlet.error.status_code",500); map.put("code","user.notexist"); map.put("message","使用者出錯啦"); request.setAttribute("ext",map); //轉發到/error return "forward:/error"; }
需要注意的是我們必須要設定響應的狀態碼,最後轉發到錯誤error請求。
在自己定義的5xx.html中可以這麼獲取資訊了:
<h1>status:[[${status}]]</h1> <h2>timestamp:[[${timestamp}]]</h2> <h2>exception:[[${exception}]]</h2> <h2>message:[[${message}]]</h2> <h2>ext:[[${ext.code}]]</h2> <h2>ext:[[${ext.message}]]</h2>
當訪問http://localhost:8080/curd/hello?user=aa時,會看到:
這裡exception獲取不到???暫時還不知道什麼原因。
如何定製自己的錯誤資訊到頁面中?
向上述的ext.code和 ext.message是我們異常處理器給我們帶的欄位,如果我們想新增自己的欄位:
在com.gong.springbootcurd.component中新建一個MyErrorAttributes.java
package com.gong.springbootcurd.component; import com.gong.springbootcurd.exception.UserNotExistException; import org.springframework.boot.web.servlet.error.DefaultErrorAttributes; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.WebRequest; import java.util.Map; //給容器中加入我們自己定義的ErrorAttributes @Component public class MyErrorAttributes extends DefaultErrorAttributes { //返回值的map就是頁面和json能獲取的所有欄位 public Map<String, Object> getErrorAttributes(WebRequest requestAttributes, boolean includeStackTrace) { Map<String, Object> map = super.getErrorAttributes(requestAttributes, includeStackTrace); //map.put("exception", UserNotExistException.class.getName()); map.put("company","gong"); //我們的異常處理器攜帶的資料 Map<String,Object> ext = (Map<String, Object>) requestAttributes.getAttribute("ext", 0); map.put("ext",ext); return map; } }
說明:我們先從請求域中得到與系統預設的錯誤相關的屬性,然後再新增自己定義的屬性,最後從請求域中得到自定義異常處理器中的屬性,全部都傳給map進行返回。對於沒有打印出來的exception,我們可以這麼進行處理,在自定義的異常處理器中:
map.put("exception",e.getClass().getName());
我們自己來獲得異常的名字,然後傳給exception,只不過最後我們在5xx.html中這麼取值:
<h1>status:[[${status}]]</h1> <h2>timestamp:[[${timestamp}]]</h2> <h2>exception:[[${exception}]]</h2> <h2>error:[[${error}]]</h2> <h2>message:[[${message}]]</h2> <h2>company:[[${company}]]</h2> <h2>ext:[[${ext.code}]]</h2> <h2>ext:[[${ext.message}]]</h2> <h2>ext:[[${ext.exception}]]</h2>
最後在瀏覽器輸入:loclahost:8080/curd/hello?user=aa