dubbo和spring mvc全局異常處理器實現(xiàn)

spring mvc 的全局異常處理器

@ExceptionHandler
當(dāng)它在一個 controller 內(nèi)部聲明時,它將被用于那個controller(或它的子類)的 @RequestMapping方法拋出的異常. 你也可以在 @ControllerAdvice 類里面聲明 @ExceptionHandler 方法,它將會處理很多controller的 @RequestMapping方法拋出的異常. 我的例子就是寫一個異常處理類,其被@ControllerAdvice注解。
例如:

@ControllerAdvice
public class BizExceptionFilter implements Filter {
  @ExceptionHandler(value = Exception.class)
  public Object handleIOException(Exception e){
    log.info("Catch exception", e);
    String exceptionName=e.getClass().getName();
    ResultExceptionInfoBean resultExceptionInfoBean=getInfoBean(exceptionName);
    FResponse rsp = new FResponse<Object>();
    rsp.setCode(resultExceptionInfoBean.getCode());
    rsp.setMessage(resultExceptionInfoBean.getMessage());
    rsp.setData(e);
    return rsp;
  }

@ExceptionHandler 的value可以設(shè)置一個需要被處理的異常數(shù)組. 如果一個異常被拋出并且包含在這個異常列表中, 然后就會調(diào)用 @ExceptionHandler 方法. 如果沒有設(shè)置value,
那么就會使用參數(shù)里面的異常.
和標(biāo)準(zhǔn)controller的 @RequestMapping 方法很相似, @ExceptionHandler 方法的參數(shù)值和返回值相當(dāng)靈活. 比如說, HttpServletRequest 可以在 Servlet 環(huán)境中被接收, PortletRequest 在 Portlet 環(huán)境中被接收. 返回值可以是 String, 它將解釋為一個視圖, 可以是 ModelAndView 對象, 可以是 ResponseEntity 對象, 或者你可以添加 @ResponseBody 方法直接返回消息.

dubbo的異常處理

由于spring 的全局異常處理只能對http請求有效,所以對于dubbo的調(diào)用不起作用。

那么為了實現(xiàn)對dubbo調(diào)用異常的處理,我們可以使用dubbo的攔截擴(kuò)展.
具體配置方式詳見 API.
將擴(kuò)展方法寫到spring 的全局異常處理器中,使其繼承Filter,然后配置服務(wù)方調(diào)用攔截。
當(dāng)服務(wù)被調(diào)用時就會執(zhí)行該方法。
例如:

 @ControllerAdvice
public class BizExceptionFilter implements Filter {

@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
    log.debug("BizExceptionFilter:{},{}", invoker.getInterface(),
    JsonUtil.jsonFromObject(invocation.getArguments()));
    Result result = invoker.invoke(invocation);
    Object realResult = result.getValue();
    FResponse rsp = new FResponse<Object>();
    if (result.hasException()) {
      try {
        ExceptionHandlerMethodResolver resolver=new   ExceptionHandlerMethodResolver(this.getClass());
        Exception exception=(Exception) result.getException();
        Method method=resolver.resolveMethod(exception);
        realResult = method.invoke(this, exception);

        return new RpcResult(realResult);
      } catch (Throwable e) {
        log.error("Exception handler error. Caused Exception:{}", result.getException());
      }
    }
    rsp.setCode("0000");
    rsp.setMessage("Success");
    rsp.setData(realResult);
    return new RpcResult(rsp);
    }

  @ExceptionHandler(value = NullPointerException.class)
  public Object handleIOException(NullPointerException e){
    log.info("Catch exception", e);
    String exceptionName=e.getClass().getName();
    ResultExceptionInfoBean resultExceptionInfoBean=getInfoBean(exceptionName);
    FResponse rsp = new FResponse<Object>();
    rsp.setCode(resultExceptionInfoBean.getCode());
    rsp.setMessage(resultExceptionInfoBean.getMessage());
    rsp.setData(e);
    return rsp;
  }
  @ExceptionHandler(value = IndexOutOfBoundsException.class)
  public Object handleIOException(IndexOutOfBoundsException e){
    log.info("Catch exception", e);
    String exceptionName=e.getClass().getName();
    ResultExceptionInfoBean resultExceptionInfoBean=getInfoBean(exceptionName);
    FResponse rsp = new FResponse<Object>();
    rsp.setCode(resultExceptionInfoBean.getCode());
    rsp.setMessage(resultExceptionInfoBean.getMessage());
    rsp.setData(e);
    return rsp;
  }

解析:
Result result = invoker.invoke(invocation);這行代碼之前的代碼,是在服務(wù)被調(diào)用錢執(zhí)行,之后的代碼是在服務(wù)被調(diào)用后執(zhí)行。

Object realResult = result.getValue();獲得執(zhí)行結(jié)果.

result.hasException()是否拋出了異常.

A912450C-D6D7-4E83-85E4-12034B2569B4.png
這段代碼就是利用反射機(jī)制,獲得當(dāng)前的類的方法,然后調(diào)用該對象的有exception參數(shù)的方法,并將結(jié)果返回。

2017-3-15 更新
Exception exception=(Exception) result.getException(); 這行代碼的作用是獲得此類中被@ExceptionHandler注解的方法。
Method method=resolver.resolveMethod(exception);這行代碼的作用是從被@ExceptionHandler注解的所有方法中找出value為exception的方法對象。
realResult = method.invoke(this, exception); 執(zhí)行這個方法。
如圖:

6D14283E-035B-443E-9FDA-276DA93643AB.png

這樣保持了和spring 的全局異常處理一致,即被@ExceptionHandler注解的方法去處理異常。
spring 相關(guān)源碼如下:
Paste_Image.png

測試:
我在服務(wù)類中直接拋出了異常。

8EB375E9-8266-4A82-BD85-0FD9BFEC085F.png

順利執(zhí)行:

CB3B887D-FB1D-432B-A9CA-150FE7E3E93C.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,554評論 19 139
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 47,273評論 6 342
  • 八朝古都,文化名城。位處中州腹地,立夏商舊畿之上,皇天后土,群雄逐鹿場;背臨九曲黃河,懷千里平川沃野,華夏搖籃,農(nóng)...
    樸雨閱讀 2,795評論 5 5
  • 大v賺錢嗎,其實依照銷售界提成10%已不算少了,可總覺得還是很少,還是因銷售量沒上去,可還是我忍不住去推廣,一是因...
    姝墨閱讀 179評論 0 0
  • 突然有點失落,不是因為不能出遠(yuǎn)門,而是生完孩子了也看完那么多書后,越發(fā)現(xiàn)自己的無能,總想認(rèn)真學(xué)習(xí)考試,卻因為一切的...
    文澍閱讀 290評論 0 0

友情鏈接更多精彩內(nèi)容