springmvc、 springboot 專案全域性異常處理
異常在專案中那是不可避免的,通常情況下,我們需要對全域性異常進行處理,下面介紹兩種比較常用的情況。
準備工作:
在捕獲到異常的時候,我們通常需要返回給前端錯誤碼,錯誤資訊等,所以我們需要手動封裝一個jsonData物件,這裡為了方便,我直接通過返回布林型別來進行判斷成功或失敗,在實際的專案中更多是返回狀態碼 比如 0、1 、404 、500 等,在這裡不影響我們演示。
jsondata物件
自定義一個異常 (注意需要繼承RuntimeException,因為在spring中僅有RuntimeException支援事務)
情況一、對全域性進行捕獲,並統一返回json資料
我們通過@ControllerAdvice的方式來捕獲全域性異常
主要程式碼如下:
import com.me.exception.RbacException; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @ControllerAdvice @Slf4j public class ExceptionHandReturnJson { private final String UNKNOW_EX_MSG = "未知錯誤"; @ExceptionHandler(Exception.class) @ResponseBody public JsonData handle(Exception e){ JsonData result = new JsonData(); /*判斷異常的型別*/ // 如果是自定義異常 if(e instanceof RbacException){ log.error("【自定義異常】:{}"+e.getMessage()); result = JsonData.fail(e.getMessage()); }else{ log.error("【系統異常】:{}"+e.getMessage()); result = JsonData.fail(UNKNOW_EX_MSG); } return result; } }
然後確保我們這個類所在的包被掃描到即可。
下面我們自定義一個類,並手動產生一個異常:
執行結果:
情況二、對全域性異常進行捕獲,返回modelandview型別
我們通過實現HandlerExceptionResolver 的方式來捕獲全域性異常
主要程式碼如下:
package com.me.common; import com.me.exception.RbacException; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.HashMap; import java.util.Map; /** * 全域性異常處理 */ @Slf4j public class ExceptionHand implements HandlerExceptionResolver { private final String UNKNOW_EX_MSG = "未知錯誤"; /** * 通過實現HandlerExceptionResolver 介面,對捕獲到的異常進行處理 * 當然,我們需要在spring容器中建立這個bean * @param request * @param response * @param o * @param e * @return */ @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object o, Exception e) { // 請求地址 // String url = request.getRequestURL().toString(); ModelAndView mav = new ModelAndView(); // 如果是自定義異常 if(e instanceof RbacException){ log.error("【自定義異常】:{}"+e.getMessage()); JsonData result = JsonData.fail(e.getMessage()); mav.addObject("result",result); }else{ log.error("【系統異常】:{}"+e.getMessage()); JsonData result = JsonData.fail(UNKNOW_EX_MSG); mav.addObject("result",result); } // 設定異常處理返回的頁面,在/views/exception.jsp mav.setViewName("exception"); return mav; } }
然後我們需要在spring容器中建立這個類的bean , 按照springmvc和springboot不同的做法都可以。
同樣,我們還是用剛才的方法進行測試
因為返回的是modelAndView型別的物件,所以我們需要建立一個view
執行結果:
===========================================================================================
總結:
上面就是兩種捕獲全域性異常進行處理的不同方式,
1.實現HandlerExceptionResolver介面,返回modelAndView型別
2.通過@ControllerAdvice註解捕獲,並通過@ResponseBody返回json型別
具體使用哪種看實際的專案,個人更喜歡第二種,統一返回json型別。
其他:
更規範的json返回物件是code碼而不是boolean型別的,這裡只為了做演示。那麼在我們使用code碼的時候,我們拋異常的時候可以自定義傳入code以及msg ,這時建議用列舉來管理二者關係,拋異常的時候傳入列舉型別,捕獲的時候再從列舉中取值。
更詳細的課程教學,請看廖師兄的課程 https://www.imooc.com/learn/810