異常在項目中那是不可避免的,通常情況下,我們需要對全局異常進行處理,下面介紹兩種比較常用的情況。
準備工作:
在捕獲到異常的時候,我們通常需要返回給前端錯誤碼,錯誤信息等,所以我們需要手動封裝一個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