WebX實踐指南_WebXRPC(四)
WebX RPC顧名思義,是基於webx框架之上支援非同步請求的一種擴充套件,是輕量級的RPC框架。
參考:http://docs.alibaba-inc.com/display/opentech/Web-RPC
WebX RPC說明
1.1、意義
1. 對webx框架的擴充套件,使webx能夠更好的支援ajax請求
2. 統一各個站點對webx ajax的使用規範
1.2、不解決的問題
1. 不提供類似DWR框架的client端js輸出
2. 不是一個REST的實現(**?**)
1.3、應用範圍 & 特性
- 應用範圍:
1. 需要使用ajax技術的webx專案
2. 已經用過ajax在webx當中的專案 - 特性:
1. 支援annotation的資料繫結和驗證
2. 統一的錯誤處理流程
3. 支援json、xml、jsonp的輸出格式
4. 可擴充套件MimeResult自定義輸出格式
5. 可擴充套件RPCResultGenerator來完成對生成結果的自定義包裝
6. 提供全域性的攔截器和方法級別的攔截器
7. 框架內建的XSS和CSRF安全過濾器 [前端如何實現]
1.4、快速開始
- 新增Maven庫依賴pom.xml 片段:
<dependency>
<groupId>com.alibaba.platform.shared</groupId>
<artifactId>webx3.extension.rpc</artifactId>
<version>0.2.6</version>
</dependency>
<!--fasttext配置 begin -->
<dependency>
<groupId>com.alibaba.platform.shared</groupId>
<artifactId>fasttext.all</artifactId>
<version>1.3</version>
</dependency>
- 配置Web-RPC的基礎服務
- pipeline.xml中增加對RPC的攔截支援,pipeline.xml片段
<when>
<pl-conditions:target-extension-condition extension="json,jsonp,xml,xhtml" />
<valve class="com.alibaba.citrus.extension.rpc.integration.RPCServiceHandlerValve" />
</when>
- 在webx-component.xml中配置以下服務,Spring配置檔案片段
<!-- =================================================== -->
<!-- WebX3 RPC 服務配置 (開始)-->
<!-- =================================================== -->
<!-- RPC 資料繫結服務 -->
<beans:bean id=`rpcDatabindService` class=`com.alibaba.citrus.extension.rpc.databind.RPCDatabindServiceImpl`>
<beans:property name="registry">
<beans:bean id=`databinderRegistry` class=`com.alibaba.nonda.databind.impl.DatabinderRegistryImpl`>
<beans:property name="binderFactories">
<beans:list>
<beans:bean class="com.alibaba.citrus.extension.rpc.databind.RPCDatabinderFactory"/>
</beans:list>
</beans:property>
</beans:bean>
</beans:property></beans:bean>
<!-- RPC 資料驗證服務 -->
<beans:bean id=`rpcValidateService` class="com.alibaba.nonda.integration.webx3.validation.ValidateService4WebX3" />
<!-- RPC URL與元件的對映服務 -->
<beans:bean id=`rpcUrlComponentMapping` class="com.alibaba.citrus.extension.rpc.impl.URLComponentMappingImpl">
<!-- 標識RPC服務的名稱空間(通過不同的namespace來模板化不同的業務) -->
<beans:property name="namespace" value="${component}" />
<!-- 是否啟用URL的馱峰轉換,預設為true -->
<beans:property name="useCamelCaseURL" value="false" /></beans:bean>
<!-- RPC 處理請求的核心服務 --><beans:bean id=`rpcServiceHandler` class="com.alibaba.citrus.extension.rpc.impl.RPCServiceHandlerImpl">
<!-- 示例:覆蓋預設的 resultGenerator -->
<beans:property name="resultGenerator">
<beans:bean class="com.alibaba.sample.showcase.web.rpc.common.generator.MyCustomResultGenerator" />
</beans:property>
<!-- 示例:新增全域性自定義的Interceptor -->
<beans:property name="interceptors">
<beans:list>
<beans:bean class="com.alibaba.sample.showcase.web.interceptors.SecurityInterceptor" />
</beans:list>
</beans:property>
<!-- 示例:配置全域性的屬性過濾器 -->
<beans:property name="propertyFilters">
<beans:list>
<!-- Trim2Null過濾器 -->
<beans:bean class="com.alibaba.citrus.extension.rpc.response.impl.Trim2NullPropertyFilter" />
</beans:list>
</beans:property>
<!-- xssType配置選擇項有兩種: 1.delete會直接刪除xss標籤 2.escape會將xss標籤做轉義輸出 系統預設delete-->
<beans:property name="xssType" value="escape" />
</beans:bean>
• 在webx-應用模組.xml中增加對RPC型別元件的掃瞄支援
webx-應用模組.xml中的module-loader片段
<!-- 裝載模組。 -->
<services:module-loader>
<ml-factories:class-modules>
<ml-factories:search-packages type="$1" packages="xxx.yyy.module.*" />
</ml-factories:class-modules>
<ml-adapters:adapter class="com.alibaba.citrus.extension.rpc.integration.RPCModuleAdapterFactory" />
</services:module-loader>
1.5、編寫一個HelloRPCService類:
在module目錄下新增新的package:rpc,編寫對應的服務類。對映的實現可以參看上面配置檔案的 rpcUrlComponentMapping部分.
例如對於:HelloRPCService.java 類
@WebResource("hello")
public class HelloRPCService {
// some fields
// getter & setter
@ResourceMapping("/loadUser")
public String loadUser() {
return user;
}
訪問的URL為:
http://localhost:8081/hello/loadUser.json (輸出json格式)
http://localhost:8081/hello/loadUser.xml (輸出xml格式)
引數傳遞:
public Object groupQuery(@RequestParam(name=”id”) Integer id, HttpSession session) {
}
RPC返回的引數型別,一般採用JSON的方式傳回,如何返回複雜的JSON資料結構,例如:
{“data”:[
{},
{},
{}
],
“totalCount”:50,
“pageSize”:10,
“currentPage”:1
}
針對這樣的資料結構,產生結果時,採用Map
1.6、高階應用
1.6.1、定義自己的result generator
result generator程式碼示例:
public class ErrorMessageResultGenerator implements RPCResultGenerator {
private static final Logger logger = LoggerFactory.getLogger( ErrorMessageResultGenerator.class );
/**
* code
* 500: RPC服務異常
* 404: 沒有匹配的RPC服務
* rpc_system_exception: RPC框架異常
* rpc_invalid_arg: 資料繫結異常
* null: 資料驗證異常
*/
private static final Map
1.6.2、RPC Wraper對所有的RPC請求進行統一的包裝,RPC Wraper
web-app.xml //針對應用的xml配置
示例程式的RPC Wraper:
package com.tmall.mastermind.web.rpcwraper;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import phoenix.exception.DSLServiceException;
import com.alibaba.common.lang.StringUtil;
import com.tmall.mastermind.app.auth.service.api.AccessControlSwitcherService;
import com.tmall.mastermind.exception.MastermindException;
import com.tmall.mastermind.exception.MastermindExceptionType;
import com.tmall.mastermind.web.helper.BUCUserInfoHelper;
@Slf4j
public class RpcResultWraper {
@Resource
AccessControlSwitcherService accessControlSwitcherService;
public Object doWrap(ProceedingJoinPoint pjp) throws MastermindException {
Map<String, Object> result = new HashMap<String, Object>();
try {
rpcSwitcher(pjp);
return pjp.proceed();
} catch (MastermindException me) {
result.put("result", "false");
result.put("errorMsg", me.getErrorMsg());
return result;
} catch (DSLServiceException e) {
result.put("result", "false");
result.put("errorMsg", "系統繁忙~" + MastermindExceptionType.TIME_OUT.getMsg());
log.error("erro on :" + pjp.getClass(), e);
result.put("debugMsg", e.getMessage());
return result;
} catch (Throwable e) {
result.put("result", "false");
result.put("errorMsg", "系統開小差了~" + MastermindExceptionType.EXECUTION_FAILED);
log.error("erro on :" + pjp.getClass(), e);
result.put("debugMsg", e.getMessage());
return result;
}
}
/**
* rpc訪問控制開關
*
* @param pjp
* @throws MastermindException
*/
private void rpcSwitcher(ProceedingJoinPoint pjp) throws MastermindException {
if (!accessControlSwitcherService.isSwitcherEnabled()) return;
String url = getRequestUrl(pjp.getTarget());
if (StringUtil.isEmpty(url)) {
return;
}
log.info("rpcSwitcher: get request url:" + url);
String empId = BUCUserInfoHelper.getEmpId(getRequest(pjp.getTarget()));
if (StringUtil.isEmpty(empId)) {
log.error("rpcSwitcher error!! get empty empId from request");
throw new MastermindException(MastermindExceptionType.EXECUTION_FAILED, "無法獲取使用者資訊");
}
accessControlSwitcherService.checkWhiteList(url, empId);
}
private String getRequestUrl(Object target) {
HttpServletRequest request = getRequest(target);
if (null == request) {
return "";
}
return new String(((HttpServletRequest) request).getRequestURL());
}
private HttpServletRequest getRequest(Object t) {
Field field = null;
try {
field = t.getClass().getDeclaredField("request");
} catch (Exception e) {
log.error("rpcSwitcher error!! RPC-Object does not have request object", e);
return null;
}
if (null == field) {
return null;
}
HttpServletRequest request = null;
boolean save = field.isAccessible();
field.setAccessible(true);
try {
request = (HttpServletRequest) field.get(t);
} catch (Exception e) {
log.error("rpcSwitcher error!! could not get request from field", e);
}
field.setAccessible(save);
return request;
}
}
1.6.3、RPC timeout
1.7、WebX RPC原理
Pipeline任務的分發處理,RPC Service Handler, 處理的關鍵點,結果集合的重新生成,包括JSON、XML格式的結果集合。同時可以自己定義結果的生成集合。
RPC和Web服務區分 WebX的不同於Rest服務是一種RPC實現這種區分在於分佈系統中的兩種實現,一種是Web Service,一種是RPC實現。Web服務遵循SOAP協議。
RPC客戶機呼叫程式傳送一個有程式引數的呼叫資訊到服務程式,然後等待應答資訊。在伺服器端,程式保持睡眠狀態直到呼叫資訊的到達為止。當一個呼叫資訊到達,伺服器獲得程式引數,計算結果,傳送答覆資訊,然後等待下一個呼叫資訊,最後,客戶端呼叫程式接收答覆資訊,獲得程式結果,然後呼叫執行繼續進行。
Web Service本身其實是在實現應用程式間的通訊。我們有兩種應用程式通訊的方法:RPC遠端過程呼叫和訊息傳遞。使用RPC的時候,客戶端的概念是呼叫伺服器上的遠端過程,通常方式為例項化一個遠端物件並呼叫其方法和屬性。RPC系統試圖達到一種位置上的透明性:伺服器暴露出遠端物件的介面,而客戶端就好像在本地使用的這些物件的介面一樣,這樣就隱藏了底層的資訊,客戶端也就根本不需要知道物件是在哪臺機器上。
Web Service是構造分散式、模組化應用程式和麵向服務應用整合的最新技術和發展趨勢。Web服務是基於Web容器的,使用Servlet來實現。
RPC OVER HTTP Microsoft RPC-over-HTTP 部署(RPC over HTTP)允許RPC客戶端安全和有效地通過Internet 連線到RPC 伺服器程式並執行遠端過程呼叫。這是在一個名稱為RPC-over-HTTP 代理,或簡稱為RPC 代理的中介軟體的幫助下完成的。
RPC代理執行在IIS計算機上。它接受來自Internet 的RPC 請求,在這些請求上執行認證,檢驗和訪問檢查,如果請求通過所有的測試,RPC 代理將請求轉發給執行真正處理的RPC 伺服器。通過RPC over HTTP,RPC客戶端不和伺服器直接通訊,它們使用RPC 代理作為中介軟體。
WebX的實現也是類似的,是一種RPC over HTTP的實現。
相關文章
- webx啟動流程Web
- 機器學習實踐指南機器學習
- Mahout實踐指南
- DevOps 實踐指南dev
- 實驗四 CTF實踐
- pm2實踐指南
- Windows DHCP最佳實踐(四)Windows
- BouncyCastle JCE實踐(四) (轉)AST
- Docker入門實踐(四)Docker
- JMeter元件作用域實踐指南JMeter元件
- 實踐指南-網頁生成PDF網頁
- 實踐指南-前端效能提升 270%前端
- JavaScript 專案最佳實踐指南JavaScript
- AngularJS 指令實踐指南(二)AngularJS
- AngularJS 指令實踐指南(一)AngularJS
- [摘要]Python 最佳實踐指南Python
- Kubernetes 最佳安全實踐指南
- PM2入門實踐指南
- RESTful API 設計指南——最佳實踐RESTAPI
- AngularJS最佳編碼實踐指南AngularJS
- iPhone遊戲開發實踐指南iPhone遊戲開發
- 阿里智慧運維實踐|阿里巴巴DevOps實踐指南阿里運維dev
- CoreData實踐(四)——查詢資料
- DevOps 從理論到實踐指南dev
- Webpack自動化構建實踐指南Web
- Vue 專案效能優化 — 實踐指南Vue優化
- 前端優秀實踐不完全指南前端
- 資料庫安全最佳實踐:基本指南資料庫
- Django RESTful API設計與實踐指南DjangoRESTAPI
- 【機器學習PAI實踐四】如何實現金融風控機器學習AI
- Kernel Module實戰指南(四):系統呼叫劫持
- Kurento實戰之四:應用開發指南
- 大型網站的 HTTPS 實踐(四):協議層以外的實踐網站HTTP協議
- 大型網站的 HTTPS 實踐(四)——協議層以外的實踐網站HTTP協議
- MongoDB 最佳實踐和場景避坑指南MongoDB
- CSS變數(自定義屬性)實踐指南CSS變數
- 教程:Apache Spark SQL入門及實踐指南!ApacheSparkSQL
- 優酷 IPv6 演進和實踐指南