Kitty Cloud(HTTP_RPC)的全局異常處理

項目地址

https://github.com/yinjihuan/kitty-cloud

異常處理不用我講,大家都清楚。單獨的異常處理太繁瑣,全局異常處理可以在一個應用中統一進行異常的處理,非常方便。目前全局異常處理用的也越來越廣泛,今天跟大家來聊一聊 Kitty Cloud 中的全局異常是如何處理的?

爲什麼要使用全局異常處理呢?

使用全局異常處理後,我們不需要定義固定類型的返回值,當業務代碼報錯的時候直接通過異常處理方式來返回給前端或者 API 調用方錯誤信息。

不使用全局異常處理案例

Web 層

比如我們定義了一個 ResponseData 用來返回固定格式的數據,正常情況下不會有問題,給前端返回的格式也是固定的,如下:

{
  "code":200,
  "data":{
    "name":"yinjihuan"
  },
  "message":"success",
}

如果業務發生異常,那麼這個接口就不會返回上面那樣固定格式的數據了,會給我們返回錯誤頁面。除了代碼異常還有一種情況就是當訪問的 Uri 錯誤的時候,也會給調用方返回 404 的錯誤頁面,如下:

如果是傳統的 Web 項目,裏面包含了頁面這是沒問題的,我們也可以自定義錯誤頁面讓用戶體驗更好一點。但是在這個基本上是前後端分離的開發模式下,後端只提供的數據的 API,不會有頁面的內容。所以就算出錯了,就算使用者調用的 API 路徑錯了,也應該返回固定的格式,並且告訴調用方路徑錯了。所以我們需要全局的異常處理。

業務層

在業務層最常見的用法就是我們可以直接拋出自定義異常,這樣在全局異常處理後給調用方返回的還是固定的格式,如果沒有全局異常處理,我們可能會用固定的 Response 來做這件事,比如下面的代碼:

public Response createOrder(CreateOrderParam param) {
    Response checkResponse = paramsCheck(param);
    if (!checkResponse.isSuccess()) {
       return checkResponse();
    }
    ...........
}
private Response paramsCheck(CreateOrderParam param) {
     if (param.getTotalPrice() <= 0){
        return Response.fail("金額錯誤");
     }

     if (param.getGoodsCount() <= 0){
        return Response.fail("數量錯誤");
     }
     return Response.success();
}

當我們有了全局異常處理後,這邊就直接可以拋出自定義的異常了,代碼看起來會簡潔一些。

public Response createOrder(CreateOrderParam param) {
    paramsCheck(param);
    ...........
}
private void paramsCheck(CreateOrderParam param) {
     if (param.getTotalPrice() <= 0){
        throw new BizException(
           ResponseCode.PARAM_ERROR_CODE, "金額錯誤");
     }

     if (param.getGoodsCount() <= 0){
        throw new BizException(
           ResponseCode.PARAM_ERROR_CODE, "數量錯誤")
     }
}

業務層的異常跑出去後,在全局異常中會進行處理成固定的格式,然後返回給調用方。像很多開放平臺的 API 都會有很多的 code 來表示不同的異常類型。

內部服務層

內部服務層也就是說內部服務之間的調用,比如我們用 Dubbo, 如果被調用的服務中沒有進行全局異常處理,那麼當調用的某個接口報錯的時候,調用者這邊就會直接報錯。

如果我們想就算報錯了,調用方這邊還是能夠獲取到正常的響應內容,只不過是內容中會告訴我這個請求是成功的還是失敗的。

比如下面的遠程調用,如果有全局異常處理,那麼就可以根據響應判斷是否成功,如果沒有的話就直接報錯了,如果需要對錯誤進行處理,還得捕獲異常進行處理。

ResponseData<UserResponse> user =
                        userRemoteService.getUser(userId);
if(user.isSuccess()) {
  .......
}

全局異常處理

Http 全局異常處理

關於 Http 的全局異常處理,這邊就不細講了,大家可以查看我的這篇文章:https://mp.weixin.qq.com/s/sIkrZTzGP4caKHzKYKqT7A

處理後如果有報錯,那麼返回的也是固定的數據格式:

{
  code: 500,
  message: "/ by zero",
  data: null,
  domain: "kitty-cloud-article-provider",
  errors: null,
  requestId: "52a9f30323e80d82",
  success: false
}

Rpc(Dubbo)全局異常處理

Dubbo 的全局異常處理可以通過 Filter 進行處理,獲取執行的結果去進行處理,如果有異常信息就將相應的內容改成統一的失敗格式進行返回。

需要注意的是要將 Result 中的 Exception 設置爲 null, 因爲 Dubbo 內部的 org.apache.dubbo.rpc.filter.ExceptionFilter 也會對異常進行處理,移除掉後 ExceptionFilter 就不會執行對應的邏輯了。

Dubbo 處理後的效果也是會返回固定格式,如下:

關於作者:尹吉歡,簡單的技術愛好者,《Spring Cloud 微服務-全棧技術與案例解析》, 《Spring Cloud 微服務 入門 實戰與進階》作者, 公衆號 猿天地 發起人。個人微信 jihuan900, 歡迎勾搭。

感興趣的可以關注下我的微信公衆號 猿天地,更多技術文章第一時間閱讀。我的GitHub也有一些開源的代碼 https://github.com/yinjihuan

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章