原文:http://dangdangdotcom.github.io/dubbox/rest.html
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同时涵盖了这个面向。
标准的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等多数据格式的支持
中文字符支持
XML数据格式的额外要求
定制序列化
配置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
<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等
...