try....catch...finally,在catch中捕獲、處理異常web
設置默認的全局異常處理器。spring
發生異常時,一級一級往上拋,數據庫
這個過程當中,若是異常被catch捕獲、處理,那就沒事了;瀏覽器
若是沒有對應的catch來捕獲、處理異常,最終被拋到DispatcherServlet、web服務器,web服務器的處理方式是:傳回一堆錯誤信息顯示在瀏覽器中給用戶看。服務器
咱們能夠設置一個默認的全局異常處理器,拋到DispatcherServlet時,由DispatcherServlet調用默認的全局異常處理器來處理異常。app
至關於設置了一個全局的catch。jvm
新建一個類,實現HandlerExceptionResolver接口便可:ide
@Component public class MyExceptionResolver implements HandlerExceptionResolver { @Override public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) { ModelAndView mav = new ModelAndView("error"); mav.addObject("msg", e.getMessage()); return mav; } }
本來會在瀏覽器頁面上顯示一堆錯誤信息,全是專業名詞、仍是英文,對用戶很不友好。函數
此種方式,能夠指定視圖、自定義要顯示的信息,對用戶很友好。this
缺點是統一處理未經捕獲的異常,無論什麼樣的異常,處理方式都同樣,太籠統。
使用自定義的異常類。
好比轉帳,可能出現:
public class NoMoneyException extends Exception{ private String msg; public NoMoneyException(String msg) { super(); this.msg = msg; } public String getMsg() { return msg; } }
提供String類型的字符串來表示異常信息,對應的構造函數來建立異常對象,提供對應的getter方法來獲取異常信息。
以一樣的方式建立其它2個異常。
alt+insert時,不要使用String message,這個是基類Exception的參數,表示代碼執行的錯誤信息。用咱們本身寫的變量就OK。
咱們自定義的異常不是爲了處理代碼錯誤,代碼錯誤直接try...catch就行了,不必自定義異常。
自定義異經常使用於友好提示用戶,好比說dao層查詢到餘額不足,我直接拋一個NoMoneyException,代碼執行自己是沒有錯誤的,異常是手動拋的。
public class UserDao{ public void transfer(int to,int from,double amount) throws NoMoneyException,UserNotFoundException,FrozenException { //此處省略鏈接數據庫查詢 //..... //餘額不足 if (餘額不足){ throw new NoMoneyException("您當前餘額xx元,餘額不足,沒法完成轉帳!"); } //對方帳號不存在 if (對方帳號不存在){ throw new UserNotFoundException("對方帳號xxxxxxxxxx不存在!"); } //對方帳號被凍結 if (對方帳號被凍結){ throw new FrozenException("對方帳號xxxxxxxxxx已被凍結,沒法向對方轉帳!"); } //.... } }
不使用catch來處理,要在方法簽名上拋出異常。
在對應的service層的方法簽名上也要拋出來:
public class UserService{ public void transfer(int to,int from,double amount) throws NoMoneyException,UserNotFoundException,FrozenException { //調用dao層 } }
@org.springframework.stereotype.Controller public class UserController { @RequestMapping("/transfer") public ModelAndView transfer() { try { //調用service層 }catch (NoMoneyException e){ //能夠調用e.getMsg()獲取自定義的異常信息,轉發到某個視圖、傳遞數據 //..... }catch (UserNotFoundException e){ //.... }catch (FrozenException e){ //...... } } }
也能夠在全局異常類中處理:
@Component public class MyExceptionResolver implements HandlerExceptionResolver { @Override public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) { //按異常的種類來進行對應的處理, if (e instanceof NoMoneyException){ //..... } if (e instanceof UserNotFoundException){ //..... } if (e instanceof FrozenException){ //..... } } }
若是處理方式都相同,好比都是轉發到某個視圖、顯式自定義的錯誤信息,那就沒必要寫if判斷來區分異常類型,直接寫處理。
一樣能夠調用視圖、傳遞數據。
方式三一般和try...catch配合使用: