有天上飛的概念,就要有落地的實現html
概念十遍不如代碼一遍,朋友,但願你把文中全部的代碼案例都敲一遍git
先贊後看,養成習慣web
SpringBoot 圖文教程系列文章目錄面試
本文教程示例代碼見碼雲倉庫:https://gitee.com/bingqilinpeishenme/boot-demospring
異常處理在Java中是一種很常規的操做,在代碼中咱們經常使用的方法是try catch或者上拋異常。json
可是,若是Controller發生異常了怎麼辦?業務層的異常能夠在Controller捕獲,Controller拋出的異常怎麼捕獲?SpringMvc的異常怎麼捕獲?springboot
這個時候常見的操做有兩種:app
今天咱們就簡單的來說解一下SpringBoot中如何進行異常處理,跳轉404或者封裝錯誤信息響應。webapp
在SpringBoot中 error page錯誤頁面是有默認配置的,默認配置是這樣jsp
若是在static目錄中存在error文件夾,而且文件夾中存在400.html,或者500.html,出現對應的響應狀態的時候(404和500的使用),會跳轉到對應的頁面
若是你使用的是webapp目錄,也是同樣的,只要在webapp目錄中存在400.jsp頁面(html也同樣),出現對應的響應狀態的時候(404和500的使用),會跳轉到對應的頁面
以上是默認配置,只要是SpringBoot的項目都會生效,接下來咱們來測試一下
在static目錄下建立error文件夾,400.html以及500.html
寫一個會報錯的Controller方法 test500
啓動項目分別訪問一個不存在的路徑【測試】和訪問會報錯的Controller方法,效果以下
以上是SpringBoot關於錯誤頁面的默認配置,可是不少時候咱們的需求比SpringBoot的默認配置要複雜不少,例如:404頁面不想放在error文件夾下,500錯誤的時候也不想跳轉頁面,而是響應給頁面一個json的數據等。
這個時候須要作的就是修改SpringBoot的默認配置了。
實現的目標:
- 404的時候跳轉到static下的404頁面
- 500的時候響應頁面一句話:「後臺錯誤 請聯繫管理員」
第一步:建立一個可以響應 「後臺錯誤 請聯繫管理員」 這句話的Controller方法,將404頁面放在static下面【若是是webapp也同樣】
第二步:建立錯誤頁面的配置類,修改默認的配置
/** * 錯誤頁面配置 * * 繼承錯誤頁面註冊器 ErrorPageRegistrar */ @Configuration public class ErrorConfig implements ErrorPageRegistrar { @Override public void registerErrorPages(ErrorPageRegistry registry) { /** * 配置錯誤頁面 * * ErrorPage 有兩個參數 * 參數1 響應狀態碼 NOT_FOUND 404 INTERNAL_SERVER_ERROR 500 * 參數2 出現響應狀態碼的時候的跳轉路徑 能夠自定義跳轉路徑 */ ErrorPage error404 = new ErrorPage(HttpStatus.NOT_FOUND, "/404.html"); ErrorPage error500 = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/testData"); /** * 將ErrorPage 註冊到註冊器中 */ registry.addErrorPages(error404,error500); } }
第三步:啓動項目,能夠看到以下效果
訪問不存在的路徑,跳轉404頁面
訪問 http://localhost:8802/test500 效果以下:
以上就是跳轉404和統一響應數據的操做,可是還有問題,什麼問題呢?
以上的操做實際上沒有針對異常進行捕獲,而是根據響應的狀態碼進行不一樣的處理的,那麼若是才能針對不一樣的異常進行捕獲呢?這就要用到全局異常捕獲了。
還記得文章開頭說過的第二個場景嗎?使用Result對象(自定義的實體類)統一封裝異常狀態碼,異常信息,進行返回。經過全局異常捕獲就能夠實現。
測試的要求是:
- 捕獲自定義異常,封裝Result對象以json的格式響應
- 捕獲自定義異常,跳轉到錯誤頁面
在應用開發過程當中,除系統自身的異常外,不一樣業務場景中用到的異常也不同,不少時候須要自定義異常,因此咱們自定義兩個異常,分別是:
ErrorReturnResultException
package com.lu.bootexception.exception; public class ErrorReturnResultException extends RuntimeException { /** * 錯誤碼 */ private int code; public ErrorReturnResultException() { } public ErrorReturnResultException(String message) { super(message); } public ErrorReturnResultException(String message, int code) { super(message); this.code = code; } public int getCode() { return code; } public void setCode(int code) { this.code = code; } }
ErrorReturnPageException
package com.lu.bootexception.exception; public class ErrorReturnPageException extends RuntimeException { /** * 錯誤碼 */ private int code; public ErrorReturnPageException() { } public ErrorReturnPageException(String message, int code) { super(message); this.code = code; } public ErrorReturnPageException(String message) { super(message); } public int getCode() { return code; } public void setCode(int code) { this.code = code; } }
定義返回的異常信息的格式,這樣異常信息風格更爲統一
package com.lu.bootexception.exception; import lombok.Data; @Data @NoArgsConstructor @AllArgsConstructor public class Result { private int code; private String message; }
利用Spring的API定義一個全局異常處理的類,代碼和註釋以下:
package com.lu.bootexception.exception; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; /** * @ControllerAdvice 加強Controller的註解 能夠實現全局異常捕獲 */ @ControllerAdvice public class GlobalExceptionHandler { /** * @ExceptionHandler 指明要捕獲那個異常 * 不加@ResponseBody 會使用視圖解析器跳轉頁面 * 形參處是Exception 簡單來講就是會把捕獲到的異常經過形參傳入方法中 */ @ExceptionHandler(ErrorReturnPageException.class) public String errorReturnPageException(Exception e){ // 打印錯誤信息 System.out.println(e.getMessage()); // 跳轉500頁面 return "forward:/500.html"; } /** * 捕獲 ErrorReturnResultException 異常 * 經過 @ResponseBody 註解響應數據 會以json的格式響應 */ @ExceptionHandler(ErrorReturnResultException.class) @ResponseBody public Result errorReturnResultException(final Exception e) { ErrorReturnResultException exception = (ErrorReturnResultException) e; /** * Result 中能夠寫入自定義的異常狀態碼 */ return new Result(5001, exception.getMessage()); } /** * 捕獲 RuntimeException 異常 */ @ExceptionHandler(RuntimeException.class) @ResponseBody public Result runtimeExceptionHandler(final Exception e) { RuntimeException exception = (RuntimeException) e; /** * Result 中能夠寫入自定義的異常狀態碼 */ return new Result(4004, exception.getMessage()); } }
代碼中用到的註解
- @ControllerAdvice 捕獲拋出的異常,若是添加
@ResponseBody
返回信息則爲JSON
格式。- @RestControllerAdvice 至關於
@ControllerAdvice
與@ResponseBody
的結合體。- @ExceptionHandler 指明要捕獲那個異常
訪問 http://localhost:8802/testReturnPage 會跳轉錯誤頁面
訪問 http://localhost:8802/testReturnResult 會返回統一的json數據
恭喜你完成了本章的學習,爲你鼓掌!若是本文對你有幫助,請幫忙點贊,評論,轉發,這對做者很重要,謝謝。
讓咱們再次回顧本文的學習目標
- 掌握SpringBoot中異常處理的基本使用
要掌握SpringBoot更多的用法,請持續關注本系列教程。
歡迎關注本人公衆號:鹿老師的Java筆記,將在長期更新Java技術圖文教程和視頻教程,Java學習經驗,Java面試經驗以及Java實戰開發經驗。