1. 程式人生 > >springmvc、 springboot 專案全域性異常處理

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