服務API設計之——API錯誤返回規範

API錯誤返回規範

禁止經過拋異常形式返回API業務錯誤

API禁止拋Checked異常,即業務處理上的參數錯誤、邏輯錯誤、業務錯誤等禁止經過拋異常形式返回,應用Response#code, message表達業務錯誤。瀏覽器

注:不要逼調用方處處寫try{}catch()。分佈式

  • 正例:
1
Response<T> saveDesposit(...);
  • 反例:
1
T saveDesposit(...) throws ServiceException, IllegalArgumentException, ValidationException;

禁止經過拋異常形式返回API業務錯誤

API禁止拋Checked異常,即業務處理上的參數錯誤、邏輯錯誤、業務錯誤等禁止經過拋異常形式返回,應用Response#code, message表達業務錯誤。工具

注:不要逼調用方處處寫try{}catch()。編碼

  • 正例:
1
Response<T> saveDesposit(...);
  • 反例:
1
T saveDesposit(...) throws ServiceException, IllegalArgumentException, ValidationException;

須要調用方作錯誤細分處理的,API提供方務必一併提供判斷工具類

  • 正例:
1
2
3
4
5
6
7
8
9
10
11
public void saveXXX(){
    Response<T> result = xxxWriteService(...)
    if (!result.isSuccess()){
        if (xxxUtils.isBankUnSupport(result.getCode)){   <<<API提供方提供工具類解析code含義,且code含義可持續迭代更新,調用方無感知。
            //銀行渠道未開通,須要特殊提示
            ...
        }else{
            ...
        }
    }
}
  • 反例:
1
2
3
4
5
6
7
8
9
10
11
public void saveXXX(){
    Response<T> result = xxxWriteService(...)
    if (!result.isSuccess()){
        if ("10101".equals(result.getCode)){   <<<調用方按API提供方的錯誤碼值作硬編碼,代碼耦合。
            //銀行渠道未開通,須要特殊提示
            ...
        }else{
            ...
        }
    }
}

【推薦】API返回可直接顯示給用戶的中文提示信息

API失敗時,只有API實現方最清楚是什麼緣由,該怎麼提示。那麼,請提供對應的提示信息。spa

咱們系統中存在一些用國際化風格的error message,而當前的國際化實現方式真如你想的那麼好用嗎?code

error message國際化原理:

  • 代碼中的提示信息國際化配置文件

image-20180930154223074

  • 國際化提示原理

image-20180930162340975

1) 提示信息國際化的行爲發生在Web層,Web層啓動時會加載Web層的resources/messages提示信息文件get

2)當REST API須要返回提示信息時,Web會根據HTTP 請求中的Locale值(例如:zh_CN、zh_TW、en_US、es_ES_Traditional_WIN等)來決定返回哪種語言的提示信息。將errorMessage以此種語言方式返回給瀏覽器進行提示。it

問題:io

1)在分佈式系統中,各個應用按領域自治,其resources/messages只維護了自身業務須要的errorMessage。table

2)當圖中C Service 將errorMessage = template.status.not.match 返回給 XX Service,XX Service直接透傳給XX Web的狀況下,XX Web的resources/messages是不包括template.status.not.match的,因此此errorMessage將沒法正確的展現其本應該提示的信息。

因此,推薦API返回可直接顯示給用戶的中文提示信息。

  • 正例:
1
2
3
4
5
6
7
8
9
10
11
12
public Response<Boolean> saveTemplate(...) {

    try{
        ...
    }catch(StateMachineException e){
        log.warn("...");
        ...
        return Response.fail("模板配置正在審覈中,請在審覈完成後再更新");
    }catch(Exception e){
        ...
    }
}
  • 反例:
1
2
3
4
5
6
7
8
9
10
11
12
public Response<Boolean> saveTemplate(...) {

    try{
        ...
    }catch(StateMachineException e){
        log.warn("...");
        ...
        return Response.fail("模板管理狀態機異常");
    }catch(Exception e){
        ...
    }
}

【推薦】返回具有可讀性,引導性的錯誤提示信息

  • 正例:
1
2
3
4
5
6
7
8
9
10
11
12
public Response<Boolean> saveTemplate(...) {

    try{
        ...
    }catch(StateMachineException e){
        log.warn("...");
        ...
        return Response.fail("模板配置正在審覈中,請在審覈完成後再更新");
    }catch(Exception e){
        ...
    }
}
  • 反例:

例1

1
2
3
4
5
6
7
8
9
10
11
12
public Response<Boolean> saveTemplate(...) {

    try{
        ...
    }catch(StateMachineException e){
        log.warn("...");
        ...
        return Response.fail("模板管理狀態機異常");  <<<< 你做爲用戶,是否是嚇一跳?
    }catch(Exception e){
        ...
    }
}

例2

1
2
3
4
5
6
7
8
9
10
11
12
public Response<Boolean> saveTemplate(...) {

    try{
        ...
    }catch(StateMachineException e){
        log.warn("...");
        ...
        return Response.fail(e.getMessage());    <<<< message誰都看不懂,沒有任何意義
    }catch(Exception e){
        ...
    }
}
相關文章
相關標籤/搜索