在Dubbo中开发REST风格的远程调用(RESTful Remoting)

PDF版:
 

原文:http://dangdangdotcom.github.io/dubbox/rest.html

 
IBM的JAX-RS:http://www.ibm.com/developerworks/cn/java/j-lo-jaxrs/

概述:

dubbo支持多种远程调用方式,例如dubbo RPC(二进制序列化 + tcp协议)、http invoker(二进制序列化 + http协议,至少在开源版本没发现对文本序列化的支持)、hessian(二进制序列化 + http协议)、WebServices (文本序列化 + http协议)等等,但缺乏对当今特别流行的REST风格远程调用(文本序列化 + http协议)的支持。

有鉴于此,我们基于标准的Java REST API——JAX-RS 2.0(Java API for RESTful Web Services的简写),为dubbo提供了接近透明的REST调用支持。由于完全兼容Java标准API,所以为dubbo开发的所有REST服务,未来脱离dubbo或者任何特定的REST底层实现一般也可以正常运行。

特别值得指出的是,我们并不需要完全严格遵守REST的原始定义和架构风格。即使著名的Twitter REST API也会根据情况做适度调整,而不是机械的遵守原始的REST风格。

附注:我们将这个功能称之为REST风格的远程调用,即RESTful Remoting(抽象的远程处理或者调用),而不是叫RESTful RPC(具体的远程“过程”调用),是因为REST和RPC本身可以被认为是两种不同的风格。在dubbo的REST实现中,可以说有两个面向,其一是提供或消费正常的REST服务,其二是将REST作为dubbo RPC体系中一种协议实现,而RESTful Remoting同时涵盖了这个面向。

no image found

 

标准的Restful框架JAX-RS(JAVATM API FOR RESTFUL WEB SEVICES),具体实现有:

    ①.Apache CXF——XFire和Celtix的合并(一个由IONA赞助的开源ESB,最初寄存在ObjectWeb上),开源的Web服务框架。

    ②.Jersey——Sun公司提供的JAX-RS的参考实现。

    ③.RESTEasy——Jboss公司的实现。

    ④.Restlet——JAX-RS之前就存在的最早的REST框架。

    ⑤.Apache Wink,一个Apache软件基金会孵化器中的项目,其服务模块实现JAX-RS规范

 

常用注解:

@PATH,接口请求的路径

@GET、@PUT、@DELETE、@POST,分别对应着查、改、删、增四种Http请求类型

@Produces,标记返回的MIME媒体类型。理解:可以接受的出参类型,一般为json、xml

@Consumes,标记可接受的MIME媒体类型。理解:可以接受的入参类型。

@PathParam、@QueryParam、@FormParam、@HeaderParam、@CookieParam、@MatrixParam,请求参数的类型

 

 

Annotation放在接口类还是实现类

一般放在实现类中,防止接口污染,保证接口的可维护性、可扩展性。

接口和实现类同时配置注解,则实现类生效,接口的注解会被直接忽略。

 

 

JSON、XML等多数据格式的支持

支持同时返回多种数据格式,比如同时返回json和xml,根据JAX-RS的标准,根据http中的MIME header决定使用哪种类型的数据。
 

中文字符支持

编码也可以直接配置到注解中。
 

XML数据格式的额外要求

需要在返回对象的类上标注如下注解:@XmlRootElement
返回基本数据类型则无法被解析为json或xml,可以使用wrapper对象等方式来封装返回。

 

定制序列化

dubbo中使用JAXB做XML的序列化,使永jackson做json的序列化。可以在对象上添加JAXB、jackson的相关注解实现定制序列化,如添加@JsonIgnore
 

配置REST Server的实现

单独启动进程,可以使用嵌入式容器:
<dubbo:protocol name="rest" server="jetty"/>

非单独启动进程,可以使用外部容器:

 

<dubbo:protocol name="rest" server="servlet"/>

web.xml:

 

<web-app>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/classes/META-INF/spring/dubbo-demo-provider.xml</param-value>
    </context-param>

    <listener>
        <listener-class>com.alibaba.dubbo.remoting.http.servlet.BootstrapListener</listener-class>
    </listener>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>com.alibaba.dubbo.remoting.http.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>

 

即必须将dubbo的BootstrapListener和DispatherServlet添加到web.xml,以完成dubbo的REST功能与外部servlet容器的集成。

注意:如果你是用spring的ContextLoaderListener来加载spring,则必须保证BootstrapListener配置在ContextLoaderListener之前,否则dubbo初始化会出错。

其实,这种场景下你依然可以坚持用嵌入式server,但外部应用服务器的servlet容器往往比嵌入式server更加强大(特别是如果你是部署到更健壮更可伸缩的WebLogic,WebSphere等),另外有时也便于在应用服务器做统一管理、监控等等。

 

 

获取上下文(Context)信息

第一种方式,用JAX-RS标准的@Context annotation:

public User getUser(@PathParam("id") Long id, @Context HttpServletRequest request) {
    System.out.println("Client address is " + request.getRemoteAddr());
} 

 

第二种方式,用dubbo中常用的RpcContext:(代码具有入侵式,未来可能重构,server=jetty、tomcat、servlet、tjws才能用)

public User getUser(@PathParam("id") Long id) {
    System.out.println("Client address is " + RpcContext.getContext().getRemoteAddressString());
} 

 

 

配置端口号和Context Path

端口默认80
<dubbo:protocol name="rest" port="8888"/>

web上下午contextPath配置:

 

<dubbo:protocol name="rest" port="8888" contextpath="services" server="servlet"/>

 

 

配置线程数和IO线程数

配置长连接

配置最大的HTTP连接数

配置每个消费端的超时时间和HTTP连接数

...

详见PDF

 

GZIP数据压缩(不推荐)

Dubbo的REST支持用GZIP压缩请求和响应的数据,以减少网络传输时间和带宽占用,但这种方式会也增加CPU开销。

 

 

用Annotation取代部分Spring XML配置

 

添加自定义的Filter、Interceptor等

...

 

 

 

 

 

 

 





附件列表

原文地址:https://www.cnblogs.com/douJiangYouTiao888/p/6473982.html