文档章节

WebX RPC说明

pake35110
 pake35110
发布于 2016/03/16 21:56
字数 1860
阅读 55
收藏 0

http://blog.csdn.net/fiboliu/article/details/50340011

WebX RPC顾名思义,是基于webx框架之上支持异步请求的一种扩展,是轻量级的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的实现。








本文转载自:http://blog.csdn.net/fiboliu/article/details/50340011

pake35110
粉丝 4
博文 213
码字总数 160988
作品 0
杭州
程序员
私信 提问
org.springframework.web.context.ContextLoaderListener

常用Web框架SpringMVC及WebX级联容器原理探究 一、前言 使用一个东西最好研究下他的原理,因为如果知其然那么在排查问题时候会很方便,本文则针对常用web框架SpringMVC和集团的WebX框架的容器...

aoper
2017/11/14
0
0
使用SpringExt扩展Webx的示例

Webx和SpringExt分别是什么 Webx是一套基于Java Servlet API的通用Web框架。它在Alibaba集团内部被广泛使用。从2010年底,向社会开放源码。SpringExt则是Spring的一个扩展,在Spring的基础上...

joshuazhan
2012/10/05
0
20
子线程使用父线程RequestScope作用域Bean问题的探究

一、前言 最近我们组在做项目分层模块化项目调研,同组通元童鞋在调研ajdk8的多租户方案需要对每一个请求开启一个线程进行处理,然后就产生一个问题如何在开启的线程中不破坏使用习惯情况下使...

加多
2018/06/04
0
0
WebX框架解析及使用教程

原文链接:http://blog.sina.com.cn/s/blog628cc2b70102v115.html 一、Webx的层次结构(从里到外) (1)SpringExt:基于Spring,提供扩展组件的能力 (2)Webx Framework:基于Servlet API...

卢瑶
2016/10/12
159
0
webx3请求过程

webx初始化 可以使用命令: 这样在容器启动的过程中将会自动搜索以及webx-开头的XML配置文件,并创建一组级联的Spring容器结构。Webx所创建的Spring容器完全兼容于Spring MVC所创建的容器,可...

jiejie2050
2016/11/04
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Spring Boot 常用注解说明

实体类 @Entity (实体类注解) @Table(可指定表名) @Data(可缺省get/set) @Id (指定属性主键) @GeneratedValue(指定主键生成规则)

兜兜毛毛
今天
3
0
局域网能互相ping通,ubuntu虚拟机不能上外网

【问题】 桥接模式老是无法上网,查看本机IP发现被分配了一个私网地址,猜测应该是虚拟DHCP服务器没有打开,于是查看Ubuntu的网络配置: /etc/network/interfaces 发现没有dhcp配置的信息,只...

tahiti_aa
今天
2
0
以太坊助记词PHP开发包简介

以太坊助记词PHP开发包用来为PHP以太坊应用增加助记词和层级确定密钥支持能力。下载地址:以太坊助记词php开发包 。 1、开发包概述 以太坊助记词PHP开发包主要包括以下特性: 生成符合BIP39...

汇智网教程
昨天
2
0
系统监控-分布式调用链Skywalking

1. 为什么要使用分布式调用链技术? 随着公司业务的高速发展,公司服务之间的调用关系愈加复杂,如何理清并跟踪它们之间的调用关系就显的比较关键。线上每一个请求会经过多个业务系统,并产生...

秋日芒草
昨天
6
0
告诉自己的一些建议

摆脱学生心态 尽快发挥自己价值,让公司感知自己的存在,才是王道 选择比努力重要 自己附着的平台的经济体要是一个快速崛起的行业 转行趁早,年龄越大选择成本越高 趁早大量试错,学习新领域...

林怡丰
昨天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部