springboot自定義異常處理
springboot異常處理
Author:SimpleWu
預設錯誤處理機制
SpringBoot預設的錯誤處理直接回返回對應的錯誤檢視頁面。比如404錯誤。
如果是其它客戶端訪問,預設相應一個json資料。比如通過postman來訪問當前頁面。
springboot錯誤頁面處理過程:
SpringBoot的錯誤資訊配置是通過ErrorMvcAutoConfiguration來進行配置的,這個類中幫我們註冊了一下元件。
- DefaultErrorAttributes:幫我們在頁面上共享錯誤資訊。
- BasicErrorController:處理預設的/error請求。分為兩種處理請求的方式,一種是html方式,一種是json方式。
- ErrorPageCustomizer:系統發生錯誤後,該物件就會生效,來定義請求規則。
- DefaultErrorViewResolver:預設的錯誤檢視解析器,將錯誤資訊解析到相應的錯誤檢視。
處理error請求過程: 一旦系統出現4xx或者 5xx之類的錯誤, ErrorPageCustomizer就會生效(定義錯誤的相應規則),就會來到/error請求。就會被BasicErrorController處理。BasicErrorController會根據請求頭RequestHeaders中的Accept來區分是瀏覽器傳送的請求還是其它工具發出的請求。分為兩個處理方法,一個是errorHtml()和error(),在errorHtml()方法中,獲取錯誤狀態資訊,由resolveErrorView解析器解析到預設的錯誤檢視頁面。錯誤頁面是/error/404.html頁面。如果templates中error裡面有這個頁面404錯誤就會精確匹配404.html如果沒有這個404.html他會模糊匹配4xx.html頁面,如果templates中沒有找到錯誤頁面,它就會去static檔案中找。
頁面可以獲取的錯誤資訊:
- timestamp:時間戳。
- status:狀態碼。
- error:錯誤提示。
- exception:異常物件。
- message:異常訊息。
- errors:資料效驗相關的資訊。
注意:static資料夾存放的是靜態頁面,它沒有辦法使用模板引擎表示式
瞭解了上面的計息過程以後,我們自定義錯誤就簡單了。自定義html錯誤頁面分為兩種情況:
有模板引擎的情況下,在templates資料夾下建立一個error資料夾,裡面以錯誤號的方式新增錯誤頁面。我們也可以使用4xx和5xx作為錯誤頁面的檔名來匹配這種型別的其它錯誤,精確優先。
沒有模板引擎的情況下,在靜態資原始檔夾下新增以錯誤號命名的錯誤頁面。
自定義異常返回JSON資料
這種異常處理方式沒有自適應效果,不論頁面還是其它工具都會返回json格式的資料。
@ControllerAdvice public class MyExceptionHandler { @ResponseBody @ExceptionHandler(RuntimeException.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; } }
這種處理方式錯誤碼是500他首先會去模板引擎error中找定製的錯誤頁面,沒有就會去靜態資原始檔中error資料夾去。
@ControllerAdvice public class MyExceptionHandler { @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",e.getMessage()); //轉發到/error return "forward:/error"; } }