@ControllerAdvice的異常捕獲與響應增強處理


       做WEB項目,發展到現在,前后端分離的框架已經成為主流面對前后端分離項目,基本思路都是后端提供restful接口,前端接受數據往組件上綁定(vue)。但是想要把框架做好,接口、數據的統一是繞不開的話題,這是基礎中的基礎。本篇內容將先分析springboot框架下的ControllerAdvice是怎樣對異常、response進行統一攔截處理的。而后會附上一篇示例代碼,用程序來講述其運用。

  下面這張圖是我跟蹤源碼后簡單畫下來的(源碼內容過多不宜粘貼),只求達意,並不是完整的運行流程。需要知道的是ResponseBodyAdvice是在將數據最終寫入response流前發生的,一定在異常處理的后面。

源碼:查詢Bean工廠中的ControllerAdvice類型的Bean

 

源碼:對ControllerAdviceBean進行解析,獲取繼承自ResponseBodyAdvice的Bean,解析有異常處理程序的Bean


 

  接下來附上我的測試示例。其作用一是捕獲自己定義的業務校驗類異常,二是將restful接口的返回值統一封裝成 JsonResult 這樣的一個對象。前端項目在解析接口返回值的時候,不管是異常還是正常數據,其基礎結構都是一致的,偏於編寫統一處理的代碼。(小東西,用途很大)東西比較簡單,不細說了,大家看看就好。

  一、異常捕獲

/**
 * @author simm
 */
@ControllerAdvice
public class MyExceptionHandlerAdvice {
    /**
     * 處理業務異常
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @return
     */
    @ExceptionHandler(BizException.class)
    @ResponseBody
    JsonResult handleBizException(HttpServletRequest request, HttpServletResponse response, HandlerMethod handler, Throwable ex) {
        JsonResult result = new JsonResult(false);
        result.error(ex.getMessage());
        return result;
    }

    /**
     * 處理業務異常
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @return
     */
    @ExceptionHandler(Exception.class)
    @ResponseBody
    JsonResult handleException(HttpServletRequest request, HttpServletResponse response, HandlerMethod handler, Throwable ex) {
        JsonResult result = new JsonResult(false);
        result.error(Throwables.getStackTraceAsString(ex));
        return result;
    }
}

  二、responsebody統一封裝

/**
 * 數據返回結構統一組裝
 *
 * @author simm
 */
@ControllerAdvice
public class MyResponseBodyAdvice implements ResponseBodyAdvice {
    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return true;
    }

    /**
     * 處理string轉換器
     */
    private final static String HTTP_MESSAGE_CONVERTER = "StringHttpMessageConverter";

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
                                  Class selectedConverterType,
                                  ServerHttpRequest request, ServerHttpResponse response) {
        if(JsonResult.class.isAssignableFrom(body.getClass())){
            //異常已經被包裝
            return body;
        }
        //將返回值包裝成jsonresult結構
        JsonResult<Object> jsonResult = new JsonResult<>(true);
        jsonResult.setData(body);
//        if (selectedConverterType.getSimpleName().contains(HTTP_MESSAGE_CONVERTER)) {
//            return JSON.toJSONString(jsonResult);
//        }
        return jsonResult;
    }
}

  三、拋個業務異常試試

/**
 * 測試異常
 * @author simm
 */
@Controller
@RequestMapping("exception")
public class ExceptionTestController {
    /**
     * 拋出業務異常
     * @return
     */
    @RequestMapping("/biz")
    @ResponseBody
    public Object biz() {
        throw new BizException("這是我的自定義異常");
    }

    /**
     * 拋出程序異常
     * @return
     */
    @RequestMapping("/process")
    @ResponseBody
    public Object process() {
        int i = 0;
        int j = 100/0;
        return true;
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM