全部產品
Search
文件中心

Mobile Platform as a Service:網關輔助類使用說明

更新時間:Jul 16, 2024

本文對網關中用到的相關輔助類,包括攔截器類、MobileRpcHolder,以及網關錯誤碼的使用進行說明。

實現攔截器功能

攔截器只適用於非 HTTP 類型服務。

mobilegw-unify-spi-adapter.jar 實際上是通過 Java 的反射調用業務方法,即OperatioinType 所指定的方法。在方法調用的過程中,業務方可以實現 SPI 包中定義的攔截器,從而實現擴充。

網關的 SPI 包定義了兩個攔截器:AbstractMobileServiceInterceptor 抽象類別和 MobileServiceInterceptor 介面。

AbstractMobileServiceInterceptor

MobileServiceInterceptor 主要提供了四個方法,分別是 beforeInvokeafterInvoke(分為兩種:一種入參為業務返回的 Object;另一種入參為 Object 轉成的 JSON string)、throwsInvokegetOrder

43

如上圖所示,攔截器主要在以下三種情況下進行攔截:

  • 方法調用前:即 beforeInvoke方法,該方法有傳回值。一旦該方法的傳回值不為空白,那麼網關認定攔截成功,將會跳過剩餘攔截器的 beforeInvoke 方法,同時跳過調用業務方的方法,直接進入攔截器的 afterInvoke 方法。

  • 方法調用後: 即 afterInvoke 方法。afterInvoke 有兩種,一種入參為 Object,即業務方返回的對象,該方法沒有傳回值,所有的攔截器的該方法都會執行;另一種入參為 Object 轉成的 JSON string,該方法可以改變傳入的 JSON 資料並返回。一旦傳回值不為空白,那麼網關認定攔截成功,後續的攔截器將被忽略。

  • 方法出現異常:即 throwsInvoke 方法。該方法沒有傳回值,所有攔截器的該方法都會被執行。在業務方出現異常時會被調用。

MobileServiceInterceptor

MobileServiceInterceptor 繼承了架構的 Ordered 介面,因此,業務方實現的攔截器還可以通過實現 getOrder方法指定執行順序,設定的數值越小,執行的優先順序越高;設定的數值越大,執行的優先順序越低。

使用樣本

  1. 編碼自己的攔截器類,繼承 AbstractMobileServiceInterceptor 類,或者實現MobileServiceInterceptor 介面。

    public class MyInterceptor implements MobileServiceInterceptor {
    
     /*
     參數說明
         method:即業務方的方法(@OperatioinType 定義的方法)
         args:  一個對象數組,即業務方方法的傳入參數,傳入參數個數即等於數組大小。
              使用時業務方根據需要進行類型轉換。    
         bean: 即業務方的介面執行個體。
     傳回值說明:
         Object:可以在攔截器中返回資料,一旦傳回值不為空白,則網關認為已被攔截,就不會再調用業務方法
             同時,直接跳過其他攔截器的 beforeInvoke 方法,執行攔截器中的 afterInvoke 方法。       
     */
    
     @Override
     public Object beforeInvoke(Method method, Object[] args, Object target) {
         //Do Something
         return null;
     }
    
     /*
     *參數說明
     *returnValue: 業務方法返回的對象
     * 其它參數同上  
     */
     @Override
     public void afterInvoke(Object returnValue, Method method, Object[] args, Object target) {
         //注意:這裡入參是業務方返回的 Object
     }
    
     @Override
     public String afterInvoke(String returnJsonValue, Method method, Object[] args, Object target) {
         //注意:這裡入參是由業務方返回的 object,轉換而成的 JSON 格式的 string
         //可以返回新的 JSON 資料
         return null;
     }
    
     @Override
     public void throwsInvoke(Throwable t, Method method, Object[] args, Object target) {
     }
    
     @Override
     public int getOrder() {
         //最進階(數值最小)和最低級(數值最大)。
         return 0;
     }
    }
  2. 發布實現的類 MyInterceptor,成為 Bean。

    • Spring Boot:直接在該類加註解 @service

      @service
      public class MyInterceptor implements MobileServiceInterceptor{}
    • Spring:在配置的 xml 檔案聲明。

      <bean id="myInterceptor" class="com.xxx.xxx.MyInterceptor"/>

MobileRpcHolder 輔助類

MobileRpcHoldermobilegw-unify-spi-adapter.jar 中提供的一個靜態輔助類,該類定義了一個請求過程中的相關資訊,最主要的定義如下:

Map<String, String> session     儲存請求的 session
Map<String, String> header      儲存請求的頭部相關資訊
Map<String, String> context     儲存網關調用的上下文資訊
String        operationType     儲存此次請求的 operationType

在業務方的服務(即 OperationType)被調用之前,SPI 服務會根據網關轉寄的請求 MobileRpcRequest 去設定 MobileRpcHolder中的資訊。在調用業務方服務之後這些資訊會被清除。

MobileRpcHolder 的生命週期為整個服務的調用過程,調用後清除。

業務方也可以根據需要去設定這些資訊,這些資訊會在調用業務的服務過程中一直存在,在調用過程中商務服務可以擷取這些資訊。具體的設定可以通過攔截器,在方法調用前後動態地修改 MobileRpcHolder 中儲存的資訊。

以下通過例子說明 MobileRpcHolder 如何使用。

使用樣本

這裡以修改和擷取 session 為例。

  1. 修改 session。 建立攔截器,具體過程參考上面的攔截器樣本。下面以在方法調用前攔截為例:

     @Override
     public Object beforeInvoke(Method method, Object[] args, Object target) {
         Map<String, String> session = MobileRpcHolder.getSession();
         session.put("key_test", "value_test");
         MobileRpcHolder.setSession(session);
     }

    這樣就能修改 MobileRpcHolder 中的 session 資訊。

  2. 擷取 session。 業務方在自己定義的服務中可以擷取 session 資訊。

     @OperationType("com.alipay.account.query")
     public String mock2(String s) {
         Map<String, String> session = MobileRpcHolder.getSession();
     }

    其他資訊(如 header、context)的修改和擷取方式同上。

     // 擷取 header 所有資訊
     Map<String,String> headers = MobileRpcHolder.getHeaders();
     // 這裡上下文資訊指的是請求中的上下文資訊
     Map<String,String> context = MobileRpcHolder.getRequestCtx(); 
     // 擷取 OperationType
     String opt = MobileRpcHolder.getOperationType();

使用網關錯誤碼

移動網關有自己的一套錯誤碼規範,詳見 網關結果碼說明

需要注意 BizException 6666,此錯誤是業務出現異常後,網關會拋出的異常。

如果想要在出現具體錯誤時,返回其他錯誤碼,可以通過拋出 RpcException(ResultEnum resultCode) 來控制 RPC 層的錯誤,比如 resultCode=1001,會返回給用戶端“沒有許可權訪問”。

程式碼範例

@Override
public String mock2(String s) throws RpcException {
    try{
        test();
    }catch (Exception e){
        throw new RpcException(IllegalArgument);
    }
    return "11111111";
}

自訂錯誤碼

如果想使用自訂錯誤碼,那麼在調用業務方法時不能往外拋異常。

業務方法只要出現異常,就會返回狀態代碼 6666。同時用戶端收到該狀態代碼,即認為服務出錯,不會去解析業務返回的資料。用戶端只有在接收到 1000 狀態代碼時,才會去解析返回的資料。

具體做法是,服務端和用戶端約定好具體的錯誤碼,然後在調用業務方法時捕獲(catch)所有的異常,將自訂錯誤碼放在返回的資料中。這樣即使業務出現異常,網關也會返回 1000 成功。同時用戶端去解析返回的資料,提取自訂錯誤碼。