異常傳遞
如圖:服務層和dao層的異常最終都會到達控制層,控制層的異常則會自動記入logback日誌系統。所以我們應該在控制層來捕獲系統異常 捕獲控制層異常
[java] view plain copy import org.slf4j.Logger; import org.slf4j.LoggerFactory; @Controller public class SampleController { //用來手動記錄日誌 private static final Logger log = LoggerFactory.getLogger(SampleController.class); //觸發除0異常 @GetMapping("/test1") public void test1() { int i=1/0; } //觸發null 指標異常 @GetMapping("/test2") public void test2() { String a=null; a.length(); } //捕獲除0異常 @ExceptionHandler(ArithmeticException.class) public void exception1(ArithmeticException e){ System.out.println("處理除0異常"); //繼續拋出異常,才能被logback的error層級日誌捕獲 throw e; } //捕獲null 指標異常 @ExceptionHandler(NullPointerException.class) public String exception2(NullPointerException e){ System.out.println("處理null 指標異常"); //手動將異常寫入logback的error層級日誌 log.error("null 指標異常",e); return "/null.html"; } }
這個控制類有兩個映射,分別拋出兩個不同的異常,@ExceptionHandler的方法會分別捕獲其參數對應的異常。
現在訪問http://localhost/test1,程式最後拋出異常,會跳轉到一個系統預設的error頁面,這個頁面對使用者是很不友好的。不過如果你配置了http響應碼的跳轉頁面(以後會講),或者搭建了nginx之類的Proxy 伺服器,可以根據這裡的500響應碼跳轉到一個自訂的友好頁面
訪問http://localhost/test2,如果沒有配置動態網頁面,最終會跳轉到靜態null.html,這樣可以給我們使用者一個友好的提示頁面。注意不能用error.html,這個頁面已經被系統佔用
捕獲所有控制層異常
上面這個類只能捕獲當前@Controller的異常,如果要捕獲系統中所有@Controller的異常,只需要把類註解@Controller換成@ControllerAdvice。這就變成了一個專門處理異常的類,不過@GetMapping映射就不能再放在這裡了
[java] view plain copy @ControllerAdvice public class SampleController {