本文對網關中用到的相關輔助類,包括攔截器類、MobileRpcHolder,以及網關錯誤碼的使用進行說明。
實現攔截器功能
攔截器只適用於非 HTTP 類型服務。
mobilegw-unify-spi-adapter.jar 實際上是通過 Java 的反射調用業務方法,即OperatioinType 所指定的方法。在方法調用的過程中,業務方可以實現 SPI 包中定義的攔截器,從而實現擴充。
網關的 SPI 包定義了兩個攔截器:AbstractMobileServiceInterceptor 抽象類別和 MobileServiceInterceptor 介面。
AbstractMobileServiceInterceptor
MobileServiceInterceptor 主要提供了四個方法,分別是 beforeInvoke、afterInvoke(分為兩種:一種入參為業務返回的 Object;另一種入參為 Object 轉成的 JSON string)、throwsInvoke 和 getOrder。

如上圖所示,攔截器主要在以下三種情況下進行攔截:
方法調用前:即
beforeInvoke方法,該方法有傳回值。一旦該方法的傳回值不為空白,那麼網關認定攔截成功,將會跳過剩餘攔截器的beforeInvoke方法,同時跳過調用業務方的方法,直接進入攔截器的afterInvoke方法。方法調用後: 即
afterInvoke方法。afterInvoke有兩種,一種入參為 Object,即業務方返回的對象,該方法沒有傳回值,所有的攔截器的該方法都會執行;另一種入參為 Object 轉成的 JSON string,該方法可以改變傳入的 JSON 資料並返回。一旦傳回值不為空白,那麼網關認定攔截成功,後續的攔截器將被忽略。方法出現異常:即
throwsInvoke方法。該方法沒有傳回值,所有攔截器的該方法都會被執行。在業務方出現異常時會被調用。
MobileServiceInterceptor
MobileServiceInterceptor 繼承了架構的 Ordered 介面,因此,業務方實現的攔截器還可以通過實現 getOrder方法指定執行順序,設定的數值越小,執行的優先順序越高;設定的數值越大,執行的優先順序越低。
使用樣本
編碼自己的攔截器類,繼承
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; } }發布實現的類
MyInterceptor,成為 Bean。Spring Boot:直接在該類加註解
@service。@service public class MyInterceptor implements MobileServiceInterceptor{}Spring:在配置的
xml檔案聲明。<bean id="myInterceptor" class="com.xxx.xxx.MyInterceptor"/>
MobileRpcHolder 輔助類
MobileRpcHolder 是 mobilegw-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 為例。
修改 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 資訊。擷取 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 成功。同時用戶端去解析返回的資料,提取自訂錯誤碼。