Web Services中RPC/Encoded 、RPC/Literal 等样式的区别

转自 :http://hi.baidu.com/java6666/blog/item/96752ceb53285cc9d439c9a7.html

 

概要

Web服务是作为一种沟通技术而被很好地制订出来,它为Internet提供最佳的互通能力。它们的标准化进程正高速地进行着,这必将引起它们会被更广泛的接受。尽管如此,从许多邮件列表、用户组和各种讨论来判断,在不同Web服务设计(Web Service Design)方法中仍然存在相当多的混乱情形。“Document/Literal” 意味着什么,而“RPC-style”又是什么,怎样使SOAP“message-style” 适合这呢?

这篇文章将会阐明和详细解释那些由Web服务标准化组定义的不同的Web服务设计方法学,阐明各种术语,着重解释它们的不同之处。在这里,我们将把精力放在如下的几个Web服务设计方法学,评估它们的优点和缺点,并在设计一种互通性Web服务中探究每一种类型得到多大程度的支持。


RPC/Encoded 样式 
RPC/Literal 样式 
Document/Literal 样式 
Document /Literal 外覆样式

介绍

在市场上Web服务在相对存在较短的时间内,得到了巨大的认同和广泛的应用。其中一个主要原因当然是它们的那些非常早期的开放式标准,而这些标准就是市场上所有主要的Web服务推崇者所推动的;另一方面,在Web服务看起来应该像什么和他们应该如何通信这些方面,这些推崇者各有自己的偏爱。这已经导致今天的标准支持各种不同的关于web服务消息能怎样格式化和它们如何通信的方法,事实上,那些不同的通信类型是需要的。

这些描述和使用Web服务的相关标准是WSDL(Web服务描述语言),一种标准的类似XML Schema的语言,用它详细说明Web服务和简单对象访问协议(SOAP),Web服务使用的实际的沟通协议就是简单对象访问协议(SOAP)。在了解真正的设计方法学之前,让我们先阐述下在web服务领域中频繁使用到的各种术语。

沟通模式

让我们从沟通模式开始,在使用Web服务时我们应能本质地区别三种沟通方法:


远程进程调用:客户端给服务提供者发送一个SOAP请求并等待一个SOAP响应(同步沟通)。 
发送消息: 客户端发送一个SOAP请求但不期望有SOAP响应返回(单向沟通)。 
异步回调: 一个客户端用上述方法中的一种调用服务。然后,双方为回叫调用交换角色。这种模式能建立在前面两种模式之上。

SOAP 协议格式化规则

现在我们转到一个Web服务的SOAP的消息(本质上是消息的<soap:body> 元素)能如何格式化,WSDL1.1 区分两种不同绑定形式(参考soap的绑定形式):RPC和Document(文档)。(译者注:RPC(消息包含参数并返回值)Document(消息包含文档))


RPC 样式

RPC样式指定<soap:body> 元素包含一个将被调用的web方法的名称的元素(wrapper element(封装元素))。这个元素依次为该方法的每个参数还有返回值作了记录。


Document 样式

如果是document 样式,就没有像在RPC样式中的wrapper元素。转而代之的是消息片断直接出现在<soap:body> 元素之下。没有任何SOAP格式化规则规定<soap:body>元素下能包含什么;它包含的是一个发送者和接收者都达成一致的XML文档。

第二种格式规则就是‘Use’ 属性。这与各种类型如何在XML中显示有关,它指定使用某种编码规则对消息片段进行编码,还是使用消息的具体架构来定义片段。如下就是提供的两种选择:


编码 

如果use的值是”encoded”, 则每个消息片段将使用类型属性来引用抽象类型。通过应用由 encodingStyle 属性所指定的编码样式,可使用这些抽象类型生成具体的消息。最常用到的SOAP编码样式是在SOAP1.1中定义的一组序列化规则,它说明了对象、结构、数组和图形对象应该如何序列化。通常,在应用程序中使用SOAP编码着重于远程进程调用和以后适合使用RPC消息样式。 
Literal 

如果use 的值是”Literal”, 则每个片段使用 element 属性(对于简单片段)或 type 属性(对于复合片段)来引用具体架构,例如,数据根据指定的架构来序列化,这架构通常使用W3C XML架构来表述。

表1总结了各种不同的web服务参数的可选项。一个重要的事实就是,每个web服务开发人员要做三个独立的决定,使用什么“沟通模式”?什么SOAP格式化“样式”?最后用到什么SOAP消息编码类型?

 

WSDL 参数

可用选项

Communication Patterns

远程进程调用或单方消息发送

Style

Document 或 RPC

Use

Encoded 或 Literal

表1.Web服务参数。

虽然,理论上说,这些选项的任何一种组合都是可以的,但在实践中会明确偏爱某种组合而不是其它的,同时,各种标准和Web服务互用性组织(WS-I)也有某种明确的偏爱。

因此在实践中,仅Document/Literal 和 RPC/Encoded 得到了广泛的应用,同时也被大部分平台直接支持,这些平台显示在表2中。这个表也显示了对不同的style/use组合的WS-I 一致性测试结果。

Style/Use 组合

支持的 Soap 工具

WS-I 一致性

RPC/Encoded

Microsoft, Axis 1.1

Failed

RPC/Literal

Axis 1.1

Failed

Document/Literal

Microsoft , Axis1.1

Passed

表2. Web服务格式支持

由于Document/Encoded这种组合不支持现有使用的平台,所以没有测试。事实上Document/Encoded组合还没有真实的应用环境。

一个简单Web服务例子

现在我们来更详细的了解被使用和支持最多的RPC/Encoded与Document/Literal的style/use组合。我们将利用一个叫做 “SendTemperature” 的web方法举例来说明每一种的style/use组合,那个web方法使用的参数是一个用户自定义的复杂对象,返回一个void类型,这些在清单1中有描述。

我们选择了这么一个使用复杂数据类型例子,就是为了让各种样式之间的不同更加明显。

 


public void SendTemperature (Temperature[] TempCollection){}
public class Temperature 
{
   /// <remarks/>
   public int Id;
  /// <remarks/>
  public string Name;
  /// <remarks/>
  public System.Double Temperature;
}

清单

1. 使用C#实现的web方法SendTemperature

 

针对这个web方法,我们将展示各种web服务样式就它们各自的SOAP请求形式怎样在WSDL中中实现,重点讲述它们的不同之处。我们利用Microsoft VS.NET和Axis SOAP 工具箱来实现。

注意,为了简单,在这篇文章中我们忽略了WSDL文件的名称空间、前缀和服务部分。清单2列出了常用的名称空间和前缀。

 

 

 


xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" 
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
xmlns:s="http://www.w3.org/2001/XMLSchema" 
xmlns:s0="http://interop.webservices.fhso.ch/{service name}" 
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" 
xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" 
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" 
xmlns="http://schemas.xmlsoap.org/wsdl/" 
targetNamespace="http://interop.webservices.fhso.ch/{service name}/ ”

清单

 

2. 名称空间和使用到的前缀 
RPC/Encoded 样式

实质上RPC/Encoded 是一种典型的遵循“远程进程调用”模式的样式,在这种模式中客户端发送一个同步请求给服务器来执行一次操作。SOAP请求包含了要执行的方法的名称和它携带的参数。运行web服务的的服务器把该请求转化成适当的对象,然后执行操作并向客户端做出响应反馈一个SOAP消息。在客户端,该响应被用来合成一个适当的对象并返回给客户端所需要的的信息。在RPC样式的web服务中,整个方法在WSDL文件和SOAP体中被指定,包含方法的发送参数和返回值。因此我们用这种样式会有相当紧密的耦合关系。

清单3显示在RPC/Encoded样式中SendTemperature 的WSDL定义。

 


<types>
<s:schema targetNamespace="http://interop.webservices.fhso.ch/rpcencoded">
<s:complexType name="ArrayOfTemperature">
<s:complexContent mixed="false">
<s:restriction base="soapenc:Array">
<s:attribute d7p1:arrayType="s0:Temperature[]" ref="soapenc:arrayType" 
xmlns:d7p1="http://schemas.xmlsoap.org/wsdl/"/>
</s:restriction>
</s:complexContent>
</s:complexType>
<s:complexType name="Temperature">
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="Id" type="s:int"/>
<s:element minOccurs="1" maxOccurs="1" name="Name" type="s:string"/>
<s:element minOccurs="1" maxOccurs="1" name="value" type="s:double"/>
</s:sequence>
</s:complexType>
</s:schema>
</types>
<message name="SendTemperatureSoapIn">
<part name="Collection" type="s0:ArrayOfTemperature"/>
</message>
<message name="SendTemperatureSoapOut"/>
<portType name="TemperatureRpcEncodedSoap">
<operation name="SendTemperature">
<input message="s0:SendTemperatureSoapIn"/>
<output message="s0:SendTemperatureSoapOut"/>
</operation>
</portType>
<binding name="TemperatureRpcEncodedSoap" type="s0:TemperatureRpcEncodedSoap">
<soap:binding  transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="SendTemperature">
<soap:operation soapAction="http://interop.fhso.ch/soapformat/SendTemperature"/>
<input>
<soap:body use="encoded" 
      encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</input>
<output>
<soap:body use="encoded" 
      encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</output>
</operation>
</binding>

清单

3. SendTemperature在RPC/Encoded 样式中的SOAP定义

 

注意绑定的style的值被设为‘rpc’ 而use的值是‘encoded’. 在 <message> 这节中,可以有任意数目的<part> 元素,该元素包含一个type 属性,对‘rpc’ 样式来说,该属性的值是惟一的。现在我们看看调用这个SendTemperature web方法会发生什么,传送的参数是包含两个元素的数组。清单4显示了SOAP消息形式的结果。

 

 


<soap:Envelopexmlns:
     soap="http://schemas.xmlsoap.org/soap/envelope/" 
     xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" 
     xmlns:tns="http://interop.webservices.fhso.ch/rpcencoded" 
     xmlns:types="http://interop.webservices.fhso.ch/rpcencoded/encodedTypes" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SendTemperature>
<Collection href="#id1"/>
</SendTemperature>
<soapenc:Array id="id1" soapenc:arrayType="tns:Temperature[2]">
<Item href="#id2"/>
<Item href="#id3"/>
</soapenc:Array>
<tns:Temperature id="id2" xsi:type="tns:Temperature">
<Id xsi:type="xsd:int">3</Id>
<Name xsi:type="xsd:string">Station1</Name>
<value xsi:type="xsd:double">34.3</value>
</tns:Temperature>
<tns:Temperature id="id3" xsi:type="tns:Temperature">
<Id xsi:type="xsd:int">56</Id>
<Name xsi:type="xsd:string">Station3</Name>
<value xsi:type="xsd:double">23.6</value>
</tns:Temperature>
</soap:Body>
</soap:Envelope>

清单4

. SendTemperature在RPC/Encoded 样式中的SOAP消息

 

在SOAP消息中每个参数都会被类型编码(译者注:例如xsi:type="xsd:int"),注意,在SOAP消息中的‘href’ tags 标签,实质上也是RPC/Encoded样式的一部分,它被用来查询数组中的元素。在任何literal 样式中,这个‘href’ 标签是不可用的。让我们来分析下WSDL定义和它的SOAP消息形式。

优点:


WSDL文件的定义遵循直观和众所周知的远程进程调用的沟通模式。 
操作名显示在消息中,因此接收者很容易就把消息分派给它的实现。 
如果你正在你的服务中使用数据图形或者多态,在本文描述的样式中这是惟一能使用的样式。 

缺点:


SOAP消息包含的类型编码信息就如xsi:type="xsd:int", xsi:type="xsd:string", xsi:type="xsd:double" ,这些就是一种开销。 
通常验证SOAP消息是很困难的。 
RPC样式引起了一种在服务提供者和客户之间的紧密耦合,任何对接口的更改都会导致服务和客户间联系的中断。 
依赖那也许也许要同步处理的信息,内存约束也许使得RPC消息传输不能实现,因为在内存中发生消息聚集。 
不被WSI一致性标准所支持。

现在我们来看同样的web方法用RPC/Literal样式实现并看看它是否能消除RPC/Encode样式中的一些缺陷。


RPC/Literal 样式

这里的WSDL定义看起来和先前的非常相似,惟一可预见的改变就是<soap:body> 元素中‘use’ 的值由‘encoded’ 变为 ‘literal’,这显示在清单5中。就如上面所描述的,这就意味着数据类型定义并是由引用的XML Schema所提供,而不是RPC编码。

 


<types>
<s:schema elementFormDefault="qualified" 
targetNamespace="http://interop.webservices.fhso.ch/rpcliteral">
<!-- there are no global element declarations. There's nothing in the 
schema that completely describes the content of soap:Body -->
<s:complexType name="ArrayOfTemperature">
<s:sequence>
<s:element minOccurs="0" maxOccurs="unbounded" name="Temperature" 
     nillable="true" 
     type="s0:Temperature"/>
</s:sequence>
</s:complexType>
<s:complexType name="Temperature">
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="Id" type="s:int"/>
<s:element minOccurs="0" maxOccurs="1" name="Name" type="s:string"/>
<s:element minOccurs="0" maxOccurs="1" name="value" type="s:double"/>
</s:sequence>
</s:complexType>
</s:schema>
</types>
<message name="SendTemperatureSoapIn">
<part name="Collection" type="s0:ArrayOfTemperature"/>
</message>
<message name="SendTemperatureSoapOut"/>
<portType name="TemperatureRpcLiteralSoap">
<operation name="SendTemperature">
<input message="s0:SendTemperatureSoapIn"/>
<output message="s0:SendTemperatureSoapOut"/>
</operation>
</portType>
<binding name="TemperatureRpcLiteralSoap" 
            type="s0:TemperatureRpcLiteralSoap">
<soap:binding  
            transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="SendTemperature">
<soap:operation 
            soapAction="http://interop.fhso.ch/soapformat/SendTemperature"/>
<input>
<soap:body use="literal" 
            namespace="http://interop.fhso.ch/soapformat/SendTemperature"/>
</input>
<output>
<soap:body use="literal" />
</output>
</operation>
</binding>

清单

5. SendTemperature在RPC/Literal 样式中的SOAP定义

 

然而,使用这种样式仍然存在一个主要的缺陷。独立的XML Schema 不会告诉你消息体中的信息集合包含了些什么,你也必需知道RPC规则。因此,该schema描述的一种RPC/Literal消息但并不足以验证那种消息。

在清单6中让我们看看针对RPC/Literal样式的SOAP消息形式。注意,类型编码被完全移除掉了。

 


<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
< ! – SendTemperature is the name of the procedure being invoked. 
Collection is a parameter of that procedure.
Note that Collection is not namespace qualified. The two Temperature 
elements are contents of the Collection parameter. This Collection can 
be thought of as an array of Temperature items. Note that the Temperature 
is namespace qualified but is in a different namespace than SendTemperature. 
These namespace rules are unique to RPC-style messages -- > 
<SendTemperature xmlns="http://interop.fhso.ch/soapformat/SendTemperature">
<Collection xmlns="">
<ns1:Temperature xmlns:ns1="http://interop.webservices.fhso.ch/rpcliteral">
<ns1:Id>2</ns1:Id>
<ns1:Name> Station1</ns1:Name>
<ns1:value>34.2</ns1:value>
</ns1:Temperature>
<ns2:Temperature xmlns:ns2="http://interop.webservices.fhso.ch/rpcliteral">
<ns2:Id>56</ns2:Id>
<ns2:Name> Station 3</ns2:Name>
<ns2:value>23.6</ns2:value>
</ns2:Temperature>
</Collection>
</SendTemperature>
</soapenv:Body>
</soapenv:Envelope>

清单

6. SendTemperature在RPC/Literal 样式中的SOAP消息

 

优点:


WSDL定义仍然像RPC/Encoded样式一样简单直接。 
操作名仍然出现在SOAP消息中。 
把类型编码从消息中排除了,因此提升了吞吐性能。 

缺点:


服务和客户之间仍然有紧密耦合。 
仍然难以用SOAP消息来验证传输的数据。 
它也不被WSI一致性标准所支持。

现在,我们来看看Document/Literal样式,来看一下该样式是否能减少现有的缺陷。

posted @ 2011-11-06 18:03  kaqike  阅读(2542)  评论(0编辑  收藏  举报