SOAP传输协议

Posted 肖爱Kun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SOAP传输协议相关的知识,希望对你有一定的参考价值。

一.HTTP传输协议

超文本传输协议(HyperText Transfer Protocol,缩写:HTTP),它是基于请求-响应的模式协议,客户端发出请求,服务器端给出响应并返回请求内容。方法如下,HTTP传输协议常用的也就是GET和POST两种方法,下面的SOAP协议常使用到的也是GET和POST两种方式。

方法  含义
GET向指定的资源发出“显示”请求。使用GET方法应该只用在读取数据,而不应当被用于产生“副作用”的操作中,例如在Web Application中。其中一个原因是GET可能会被网络蜘蛛等随意访问
HEAD与GET方法一样,都是向服务器发出指定资源的请求。只不过服务器将不传回资源的本文部分。它的好处在于,使用这个方法可以在不必传输全部内容的情况下,就可以获取其中“关于该资源的信息”(元信息或称元数据)
POST  向指定资源提交数据,请求服务器进行处理(例如提交表单或者上传文件)。数据被包含在请求本文中。这个请求可能会创建新的资源或修改现有资源,或二者皆有
PUT  向指定资源位置上传其最新内容
DELETE 请求服务器删除Request-URI所标识的资源
TRACE  回显服务器收到的请求,主要用于测试或诊断
OPTIONS  这个方法可使服务器传回该资源所支持的所有HTTP请求方法。用’*'来代替资源名称,向Web服务器发送OPTIONS请求,可以测试服务器功能是否正常运作
CONNECT  HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。通常用于SSL加密服务器的链接(经由非加密的HTTP代理服务器)

======================================================================

二.SOAP传输协议

SOAP(Simple Object Accrss Protocol,简单对象访问协议)是一种简单的基于XML的协议,SOAP是Web Service的通信协议,是基于XML语言和XSD标准,其定义了一套编码规则,编码规则定义如何将数据表示为消息,以及怎样通过HTTP协议来传输SOAP消息,由四部分组成:

(1) SOAP信封(Envelope):定义了一个框架,框架描述了消息中的内容是什么,包括消息的内容、发送者、接收者、处理者以及如何处理消息。

(2)SOAP编码规则:定义了一种系列化机制,用于交换应用程序所定义的数据类型的实例。(3) SOAP RPC表示:定义了用于表示远程过程调用和应答协定。

(4)SOAP绑定:定义了一种使用底层传输协议来完成在节点间交换SOAP信封的约定。

soap将信息进行XML的序列化后,再用http协议的方式再打包进行传送,传送的方式还是tcp或者udp。做个比喻就好理解了。tcp 和 udp 都是公路,暂且把tcp认为是一般公路,udp高速公路,soap和http就都是汽车,那么soap和http都可以在tcp和udp上跑。说soap可以通过http来传送,实际就是说soap是小轿车,http是装轿车的卡车,把soap的信息装到http里面,然后再运输,当然走的道路还是tcp或udp。说soap可以通过http协议来传输,这句话不太准确,比较准确第说法是:soap信息可以通过http协议包装后通过tcp或udp传输。

//SOPA协议的基本结构
<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
 
<soap:Header>
  ...
  ...
</soap:Header>
 
<soap:Body>
  ...
  ...
  <soap:Fault>
    ...
    ...
  </soap:Fault>
</soap:Body>
 
</soap:Envelope>

========================================================================

三.SOAP传输协议
1.SOAP Envelope

SOAP Envelope是代表消息的XML文件的根元素。它为消息如何处理、由谁处理定义了框架。XML内容从SOAP Envelope开始。在SOAP中,使用XML命名空间将SOAP标示符与应用程序特定的标示符区分开,将SOAP消息的元素的作用域限制在一个特定的领域。如果使用了不同的命名空间,应用程序会发生错误,并抛弃此消息。SOAP消息中所有元素必须由第一个命名空间进行限定。

SOAP 1.1规范如下:

<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"

</soap-env:Envelope >

SOAP 1.2规范如下:

<soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope"

</soap:Envelope>

2.encodingStyle属性

 SOAP的encodingStyle属性用于定义在文档中使用的数据类型,encodingStyle属性可出现在任何SOAP元素中,并会被应用到元素的内容及元素的所有子元素上。SOAP消息没有默认的编码方式。

3.SOAP Header元素

 SOAP Header元素应当作为SOAP Envelope的第一个直接子元素,必须使用有效的命名空间。Header还可以包含0个或多个可选的子元素,子元素称为Header项,所有的Header项都必须是完整修饰的,即必须由一个命名空间URI和局部名组成,不允许没有命名空间修饰的Header项存在。

Header元素用于与消息一起传输附加消息,如身份验证或事务信息。Header元素也可以包含某些属性。SOAP在默认的命名空间中定义了三个属性:actor,mustUnderstand以及encodingStyle。这些被定义在SOAP头部的属性可通知容器如何对SOAP消息进行处理。

<soap:Envelope
xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
 
<soap:Header>
<m:Trans
xmlns:m="http://www.w3school.com.cn/transaction/"
soap:mustUnderstand="1">234</m:Trans>
</soap:Header>
 
...
</soap:Envelope>

3.1actor属性

通过沿着消息路径经过不同的端点,SOAP消息可从某个发送者传播到某个接收者。并非SOAP消息的所有部分均打算传送到SOAP 消息的最终端点,也可以传输到某一个特定的端点上。SOAP的actor属性可被用于将Header元素寻址到一个特定的端点。

//语法规则:soap:actor="URI"
//下面代码中有一个"Trans"元素的头部,值是234,此元素的"mustUnderstand"属性的值是"1"。
<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
 
<soap:Header>
<m:Trans
xmlns:m="http://www.w3school.com.cn/transaction/"
soap:actor="http://www.w3school.com.cn/appml/">
234
</m:Trans>
</soap:Header>
 
...
...
 
</soap:Envelope>

3.2mustUnderstand属性

SOAP的mustUnderstand属性可用于标识标题项对于要对其进行处理的接收者来说是强制的还是可选的。假如向Header元素的某个子元素添加了"mustUnderstand="1",则它可指示处理此头部的接收者必须认可此元素。假如此接收者无法认可此元素,则在处理此头部时必须失效。

//语法:soap:mustUnderstand="0|1"
<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
 
<soap:Header>
<m:Trans
xmlns:m="http://www.w3school.com.cn/transaction/"
soap:mustUnderstand="1">
234
</m:Trans>
</soap:Header>
 
...
...
 
</soap:Envelope>

3.3encodingStyle属性

SOAP的encodingStyle属性与Envelope元素中相同。

=========================================================================

4.SOAP Body元素

  SOAP消息的Body块可以包含以下任何元素:RPC方法及其参数;目标应用程序(消息接收者)专用数据;报告故障和状态消息的SOAP Fault。所有Body元素的直接子元素都称为Body项,Body项必须由命名空间修饰。必需的SOAP Body元素可包含打算传送到消息最终端点的实际 SOAP消息。

SOAP Body元素的直接子元素可以是合格的命名空间。SOAP在默认的命名空间中("http://www.w3.org/2001/12/soap-envelope")定义了Body元素内部的一个元素。即SOAP的Fault元素,用于指示错误消息。

<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
 
<soap:Body>
   <m:GetPriceResponse xmlns:m="http://www.w3school.com.cn/prices">
      <m:Price>1.90</m:Price>
   </m:GetPriceResponse>
</soap:Body>
 
</soap:Envelope>

=========================================================================

5.SOAP Fault元素

SOAP Fault元素用于在SOAP消息中传输错误及状态信息。如果SOAP消息需要包括SOAP Fault元素,SOAP Fault元素必须作为一个Body项出现,而且至多出现一次。SOAP Fault包括以下子元素:faultcode、faultstring、faultactor、detail。

子元素

描述

<faultcode>

供识别故障的代码

<faultstring>

可供人阅读的有关故障的说明

<faultactor>

有关是谁引发故障的信息

<detail>

存留涉及 Body 元素的应用程序专用错误信息

SOAP的Fault元素拥有下列子元素, 在下面定义的 faultcode 值必须用于描述错误时的 faultcode 元素中:

VersionMismatch

SOAP Envelope 元素的无效命名空间被发现

MustUnderstand

Header 元素的一个直接子元素(带有设置为 "1" 的 mustUnderstand 属性)无法被理解。

Client

消息被不正确地构成,或包含了不正确的信息。

Server

服务器有问题,因此无法处理进行下去。

=========================================================================

6.SOAP附件

按照SOAP1.1规范的规定,SOAP消息可以包含XML格式的主SOAP信封,以及包含ASCII或二进制等任何数据格式的SOAP附件。如果SOAP消息包含附件,那么SOAP消息将是一个MIME编码的消息,包含SOAP内容和一个或多个其他类型的附件。因此SOAP消息实际上分为以下两种类型:

    A、仅包含XML内容的消息

    B、MIME编码的消息,包含初始的XML有效内容以及任何数量的附件。附件可以是任何其他类型的数据。

=========================================================================

7.SOAP消息绑定

Web服务的有效负载通常包装在SOAP消息中,而SOAP消息结构由WSDL文档中的SOAP绑定定义确定。不同的调用方式和编码方式通过组合可以产生多种绑定样式,而每种样式的应用场景和对应的SOAP消息结构并不相同。如果没有正确的构造SOAP消息,则无法正确交换服务的有效负载。

 SOAP Body提供了一种消息交换的机制,是SOAP消息的实际负载,可包含任意内容。SOAP消息体(SOAP Body)通过绑定服务调用方式(RPC或者Document)封装操作,绑定编码方式(Encoded或者Literal)序列化参数。SOAP消息的绑定样式由style、use和encodingStyle三个属性共同设置。style属性指定服务的调用方式,是采用RPC方式还是Document方式;use属性指定消息的编码方式,是采用Encoded方式还是采用Literal方式;而encodingStyle属性指定具体编码规则,例如可以指定SOAP编码规则、XML Schema编码规则等等,通常情况下都是采用XML Schema。

7.1style属性

        style属性描述了服务的调用方式,取值为”rpc”或者”document”,默认值为”document”。适用于SOAP Body元素的子元素(也可能是孙级元素)。此选项指定为WSDL文档中的soap:binding元素(通常情况下)或者soap:operation 的style属性。

A.RPC: 采用客户端/服务器方式(请求/响应),发送请求到服务器端,服务端执行方法后返回结果。优点是跨语言跨平台,缺点是编译时无法排错,只能在运行时检查。

SOAP消息本质上是一种从发送方到接收方的单向传输,但是SOAP经常组合到实现请求/响应机制中。要让RPC使用SOAP,必须遵循几条规则。首先,请求和响应消息必须被编码成结构类型。其次,对一个操作的每一个输入参数,都必须有一个同名元素(或输入结构的成员)作为参数。最后,对每一个输出参数,都必须有一个名称匹配的元素(或输出结构的成员)。

style=”rpc”指明遵从SOAP标准,在SOAP Body中封装RPC调用的请求和返回操作。对该类消息的约束是必须把操作的名称作为封装了对操作的请求和响应消息负载的根元素名称。对于SOAP请求消息,请求操作的名称是根据WSDL文档中的wsdl:operation元素命名,后者对应Web服务方法。对于SOAP响应消息,响应操作的名称是请求操作的名称后面追加"Response"构成。操作元素中的每个子元素表示一个参数,根据WSDL文档中的wsdl:part元素命名。RPC请求/响应消息的格式(省略了名称空间限定)如下:

RPC请求消息格式:

<SOAP信封>

<SOAP头部>

     ……

</SOAP头部>

    <SOAP消息体>

<请求操作名称>

          <参数名1>值</参数名1>

          <参数名2>值</参数名2>

             ......

        </请求操作名称>

</SOAP消息体>

</SOAP信封>

RPC响应消息格式:

<SOAP信封>

<SOAP头部>

  ……

</SOAP头部>

    <SOAP消息体>

       <响应操作名称>

          <参数名1>值</参数名1>

          <参数名2>值</参数名2>

              ......

        </响应操作名称>

    </SOAP消息体>

</SOAP信封>

B、Document与RPC相比较Document方式在XML文件中不是做远程方法的映射,而是一份完整的自包含的业务文档。当服务器端收到这份文档后,先进行预处理(比如词汇的翻译和映射),然后再构造出返回消息。构造返回消息的过程中,往往不再是简简单单的一个方法调用,而是多个对象协同完成一个事务的处理,再将结果返回。

 采用Document方式构造消息,SOAP Body元素中的内容完全由WSDL 中的 XML Schema定义,于是可以使用XML Schema验证SOAP Body元素中的内容。SOAP Body的子元素指定为消息部分在WSDL文档中定义的 wsdl:part 元素,该元素指向 XML Schema元素声明。通常wsdl:message不会包含多个wsdl:part 元素,所以SOAP Body 内容是真正的 XML 文档,尽管 WSDL 本身不禁止包含多个wsdl:part元素。Document请求/响应消息的格式(省略了名称空间限定)如下:

Document请求消息格式:

<SOAP信封>

<SOAP头部>

     ……

</SOAP头部>

    <SOAP消息体>

        <输入消息>

   ….

 </输入消息>

….

</SOAP消息体>

</SOAP信封>

Document响应消息格式:

<SOAP信封>

<SOAP头部>

 ……

</SOAP头部>

    <SOAP消息体>

         <输出消息>

   ….

  </输出消息>

….

    </SOAP消息体>

</SOAP信封>

7.2 use属性

 use属性描述了消息序列化的方式,取值为”encoded”或者”literal”,默认值是”literal”。 如果use=”encoded”,设置encodingStyle属性的值指定编码规则。如果use=”literal”,可以不用设置encodingStyle属性的值,通常情况都是使用默认的XML Schema。适用于出现在下一个级别的 Web 服务方法参数(或返回值)。此选项指定为WSDL文档中的 soap:body、soap:header、soap:fault和soap:headerfault元素的 use 属性。

A、Encoded,SOAP编码使用XML Schema的一个子集在XML文档与其所表示的数据之间进行绑定。SOAP 编码还使用href属性对文档中多次出现的元素的引用。SOAP编码和XML Schema编码完全不同的地方是数组。SOAP规范的5.4.2节指定了一种特别的机制来表示 XML 中的编程语言数组,它使用一种特殊的SOAP-ENC:Array类型。而XML Schema是通过设置element的minOccurs和maxOccurs属性值表示数组。例如使用这两种编码方式对整形数组的定义如下:

<complexType name="ArrayOfInt"> 
  <complexContent> 
     <restriction base="SOAP-ENC:Array"> 
<sequence>
    <element name=”item” type=”xsd:int” minOccurs=”0” maxOccurs=”unbounded”/>
</sequence>
        <attribute ref=" SOAP-ENC:arrayType"  wsdl:arrayType="xsd:ArrayOfInt[]"/> 
      </restriction> 
  </complexContent> 
</complexType>  

=================================================

//XML Schema定义数组
<complexType name="ArrayOfInt">  
<sequence>
 <element name=”item” type=”xsd:int” minOccurs=”0” maxOccurs=”unbounded”/>
</sequence>
  </complexContent> 
</complexType>

B、Literal与Encoded相比,Literal采用XML Schema编码,而不是SOAP编码;Literal编码不需要数据类型属性。数据根据 WSDL 文档中指定的 XML Schema定义或导入 WSDL 文档的 XML Schema定义逐字进行格式设置。使用Literal方式编码add方法的消息格式如下:

<op:add xmlns:op=”http://act.buaa.edu.cn/add”>
<a>
<item>45</item>
<item>36</item>
</a>
 <b>
<item>235</item>
<item>67</item>
</b>
</op:bdd>

7.3encodingStyle属性

        WSDL规范中的encodingStyle属性和SOAP规范中的encodingStyle 属性定义是一样的。encodingStyle属性的值是一个URIs列表,由单个空格隔开,每个URI代表着一种消息的编码规则,它们按照编码的限制从强到弱排序。encodingStyle属性是用来指定SOAP消息的编码规则,也就是序列化的格式和类型系统。如果use=”encoded”,encodingStyle属性的值为”http://schemas.xmlsoap.org/soap/encoding/”,则表示使用SOAP规范的第5节的编码,这一节定义了将编程语言的类型映射到 XML 的基本机制。如果use=”literal”则使用外部提供的类型系统,也可以通过encodingStyle属性来指定Schema,但是通常情况下使用XML Schema来编码SOAP消息。

    这其中的缘故是因为SOAP规范是在采用XML Schema规范之前编写的。因此,原始的SOAP规范必须提供一种方法来指明编码类型信息。然而,自从采用XML Schema之后,大多数语言使用自己的从XML Schema到编程语言类型之间的映射(或序列化规则),这使得SOAP编码变得过时。因此,推荐不要采用SOAP编码,而是采用使用Literal编码,在Literal映射中由 XML Schema 文档(通常是WSDL文档的形式)从外部指定映射。

========================================================================

8.SOAP消息构造

style和use属性都有两个值,通过它们之间的不同组合,就可以产生四种绑定样式,分别是rpc-literal、rpc-encoded、document-literal和document-encoded。为了使Document绑定样式能够支持RPC绑定样式的调用,增加了一种包装(Wrapped)样式,它只不过是对Document样式的使用进行了约束。这样就又增加了两种绑定样式, document-literal-wrapped和document-encoded-wrapped,一共合起来就有6种绑定样式。下面通过一个加法服务为例来说明在不同绑定样式下的SOAP消息构造,服务的定义如下:

从服务的定义可以看出,输入操作的操作名为add,有a和b两个整数类型的输入参数。根据WSDL规范返回操作的操作名应该为addResponse,有一个整数类型的输出参数,假设命名为return。

操作的序列化是需要名称空间限定的。如果是RPC调用方式,则名称空间是soap :body的namespace属性值;如果是Document调用方式,名称空间则是输入消息引用的Schema的targetNamespace属性值。参数的序列化是否需要名称空间限定取决于Schema定义时elementFormDefault属性的值。如果值为”qualified”则表示需要限定,名称空间为Schema的targetNamespace属性值;如果值为”unqualified”表示不用限定,默认值为”unqualified”。操作序列化后的元素作为SOAP消息体的子元素,而每个参数序列化后的元素都是作为操作元素的子元素,排列的顺序和操作的参数定义顺序一样。   

    A、如果use= ”encoded”则encodingStyle的值为”http://schemas.xmlsoap.org/soap/encoding/”,如果use= ”literal”则使用” http://www.w3.org/2001/XMLSchema”编码。

    B、如果style=”rpc”则wsdl:part 部分的类型引用使用type属性,如果style=”document”则使用element属性。

8.1 rpc-literal绑定样式

<wsdl:definitions xmlns:wsdl= " http://schemas.xmlsoap.org/wsdl/"
   xmlns:ns="http://act.buaa.edu.cn/add" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://act.buaa.edu.cn/add">
<wsdl:message name=”addRequest”>
 <wsdl:part name=”a” type=”xsd:int”/>
    <wsdl:part name=”b” type=”xsd:int ”/>
</wsdl:message>
<wsdl:message name=”addReponse”>
    <wsdl:part name=”return” type=”xsd:int”/>
</wsdl:message>
<!--Just assume it's rpc-literal. -->
......

<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
   <env:Body>
     <op: add  xmlns:op=“http://act.buaa.edu.cn/add”>
       <a>12</a>
<b>45</b>
     </op: add >
   </env:Body>
</env:Envelope>]

 优点:WSDL 描述和SOAP消息基本达到了尽可能地简单易懂的要求;服务的操作名出现在SOAP消息的Body中,这样接收者就可以很轻松地把消息发送到方法的实现;没有类型编码,提高了吞吐量,减少了处理的性能开销。

    缺点:在RPC模型中XML仅仅被用于描述方法的信息,不能充分利用XML的功能去描述和验证一份业务文档 ;不能使用Schema简单地检验此消息的有效性,因为只有参数a和b是Schema 中定义的内容,其余的 env:body 内容(例如add元素)都来自 WSDL 定义;无法直接从消息中获得参数的类型信息;RPC样式对请求/响应消息的模式捆绑,使得服务与客户端之间耦合性增加,一旦方法发生变化,客户端就需要做相应的改动;相对异步调用方式而言,RPC样式下服务调用通常是同步的。

8.2 rpc-encoded 绑定样式

<env:Envelope  xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" 
       xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi=” http://www.w3.org/2001/XMLSchema-instance” >
  <env:Body>
     <op: add xmlns:op=“http://act.buaa.edu.cn/add”>
        < a  xsi:type=”xsd:int”>12</a>
<b  xsi:type=”xsd:int”>45</b>
     </op: add >
   </env:Body>
</env:Envelope>

 与rpc-literal绑定样式唯一的区别就是请求消息的参数部分编码方式不一样。消息中的每个参数都有类型编码(比如 <a xsi:type=”int”>12</a>),直接从消息就可以知道参数的数据类型。但是这些类型信息降低了吞吐量和消息处理的性能。尤其是在大数据的情况下,性能开销明显。

 rpc-encoded绑定样式主要在重载、数据图形和多态的情况下使用。WSDL 允许重载的操作,但是当参数个数相同的情况下,因为Literal编码方式没有类型信息,无法定位方法,所以rpc-literal就不支持这样的重载。数据图形的标准方式是使用href 标记,它是 rpc-encoded的样式。多态所生成的 SOAP 消息必须包含类型编码信息,这样接收终端才能知道它所接收的是父类的哪一个扩展。

8.3 document /literal绑定样式

<wsdl:definitions xmlns:wsdl= " http://schemas.xmlsoap.org/wsdl/"
xmlns:ns="http://act.buaa.edu.cn/add" targetNamespace=" http://act.buaa.edu.cn/add ">
<wsdl :types>
<xs:schema elementFormDefault="qualified" targetNamespace="http://act.buaa.edu.cn/add" xmlns:xs="http://www.w3.org/2001/XMLSchema" >  
       <xs:element name="a"  type="xs:int " />
       <xs:element name="b"  type="xs:int " />
       <xs:element name="return"  type="xs:int " />
</xs :schema>
</wsdl :types>
<wsdl:message name=”addRequest”>
     <wsdl:part  name=”parameter1” element=”ns:a”/>
<wsdl:part  name=”parameter2” element=”ns:b”/>
</wsdl:message>
<wsdl:message name=”addReponse”>
     <wsdl:part name=”parameter” element=”ns:return”/>
</wsdl:message>
<!--Just assume it's  document-literal. -->
……

================================================================
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:op=“http://act.buaa.edu.cn/add”>
<env:Body>
    <op:a>12</op:a>
<op:b>45</op:b>
</env:Body>
</env:Envelope>

请求消息的参数元素添加了名称空间限定,这是因为输入消息在WSDL文档的Schema中定义,而且Schema的elementFormDefault=”qualified”。也就是说参数元素必须使用Schema的名称空间"http://act.buaa.edu.cn/add"进行限定。

 优点:没有操作和类型编码信息,减少了消息的数据量,提高了消息处理性能;env:Body中每项内容都定义在Schema中,可以用任何XML检验器检验此消息的有效性。

 缺点:WSDL文档变得比较复杂,这不过是一个非常小的缺点,因为 WSDL 并没有打算由人来读取;SOAP消息中没有提供服务操作的名称,一些特定的程序代码在分发消息时可能会变得复杂,并且有时变得不可能。如果使用HTTP作为底层传输协议,可以使用SOAPAction属性绑定操作的名称来解决消息分发的问题。虽然大多数情况下都是使用HTTP协议来传输SOAP消息,但是这种方法绑定了底层传输协议,限制了其他传输协议的使用。

8.4 document /encoded绑定样式

<env:Envelope  xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi=” http://www.w3.org/2001/XMLSchema-instance”
       xmlns:op=“http://act.buaa.edu.cn/add”>
   <env:Body>
       <op:a  xsi:type=”xsd:int”>12</op:a>
<op:b  xsi:type=”xsd:int”>45</op:b>
   </env:Body>
</env:Envelope>

 与document-literal绑定样式唯一的区别就是请求消息的参数部分编码方式不一样。引入了类型编码,降低了吞吐量和消息处理的性能。这种绑定样式不被大多数Web服务实现平台支持。

8.5  document-literal-wrapped绑定样式

<wsdl:definitions  xmlns:wsdl= " http://schemas.xmlsoap.org/wsdl/"
xmlns:ns="http://act.buaa.edu.cn/add"  targetNamespace=" http://act.buaa.edu.cn/add ">
<wsdl :types>
<xs:schema elementFormDefault="qualified" targetNamespace="http://act.buaa.edu.cn/xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema" >  
       <xs:element name="add">
          <xs:complexType>
            <xs:sequence>
               <xs:element name="a"  type="xs:int " />
               <xs:element name="b"  type="xs:int " />
            </xs:sequence>
          </xs:complexType>
       </xs:element>
       <xs:element name="addResponse">
          <xs:complexType>
            <xs:sequence>
               <xs:element name="return"  type="xs:int " />
            </xs:sequence>
         </xs:complexType>
       </xs:element>
</xs :schema>
</wsdl :types>
<wsdl:message name=”addRequest”>
    <wsdl:part  name=”parameter” element=”ns:add”/>
</wsdl:message>
<wsdl:message name=”addReponse”>
    <wsdl:part name=”parameter” element=”ns:addResponse”/>
</wsdl:message>
<!--Just assume it's  document-literal-wrapped. -->
……
=====================================================================
<env:Envelope  xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
   <env:Body>
     <op: add  xmlns:op=“http://act.buaa.edu.cn/add”>
       <op:a>12</op:a>
<op:b>45</op:b>
     </op: add >
  </env:Body>
</env:Envelope>

此时SOAP Body中第一个元素的名称并不是操作的名称,而是Schema中的元素的名称。Schema中的元素的名称可以与操作名相同,也可以不同。如果取相同则是一种将操作名放入SOAP消息的巧妙方式。

  虽然此SOAP 消息看起来与 rpc-literal的 SOAP 消息是完全一样的(如果不考虑名称空间限定),但是这两种消息之间存在着微妙的区别。在 rpc-literal的 SOAP 消息中,<env:Body>下的<op:add>根元素是操作的名称。在document-literal-wrapped的SOAP 消息中,<op:add>元素是单个输入消息的组成部分引用的元素的名称。

 document-literal-wrapped样式规定Document绑定操作的输入消息和输出消息都只有一个wsdl:part部分;该部分使用element属性引用一个元素;该元素是复杂类型并且没有属性;该元素的名称和操作的名称必须一样。

 优点:包装行为吸取了RPC样式的一个重要优点,即RPC样式中SOAP消息体可以直接通过与之关联的服务操作名称来命名,同时又摒弃了RPC样式的不足之处;可以利用WSDL文档类型部分的Schema文档直接来验证SOAP消息体;只要在Schema中定义了明确的数据结构,如何构建SOAP消息体具有很大的灵活性;由于业务数据是自包含的,显然文档模型更利于采用异步处理。

 缺点:WSDL 较为复杂, 但是这仍然是一个非常小的缺点。使得服务调用的复杂度有所增加,尤其是在API级别。针对程序开发人员来说,基于包装的document绑定样式的服务编写客户端代码也许就变成了一项极具挑战性的工作。在SOAP消息体的XML包装元素中必须拥有一个服务操作的名称,因此包装版本不支持重载的服务操作。实际上,针对一个既定的元素名称也只能够有一个服务操作。

8.6 document-encoded-wrapped绑定样式

<env:Envelope  xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi=” http://www.w3.org/2001/XMLSchema-instance” >
  <env:Body>
     <op: add  xmlns:op=“http://act.buaa.edu.cn/add”>
        <op:a  xsi:type=”xsd:int”>12</op:a>
<op:b  xsi:type=”xsd:int”>45</op:b>
     </op: add >
   </env:Body>
</env:Envelope>

与document -literal-wrapped绑定样式唯一的区别就是请求消息的参数部分编码方式不一样。引入了类型编码,降低了吞吐量和消息处理的性能。

========================================================================

9.SOAP 附件

实际应用中需要和各种附件(如图像、图画、xml 文档等)一起发送SOAP消息。附件数据通常是特殊的二进制格式。 带附件的SOAP规范详细说明了使用“MIME multipart/related” 媒体类型和URI模式引用MIME部件。并不是所有的Web服务工具箱都提供SOAP附件支持。Microsoft提出了另一个基于DIME的附件解决方案

9.1 SOAP消息包

带附件的SOAP消息包如下 ,SOAP消息包包含XML格式的主SOAP消息以及SOAP信封中未定义但与消息有关的任意数据格式(例如 gif、jpg 和 xml 等)的其它实体。

SOAP消息包是用MIME的Multipart/related 媒体类型构建的,每个部件都嵌入MIME边界(在Context-Type报头中定义)。每个 MIME部件都有报头信息比如Context-Type 它指定嵌入这MIME部件的数据的类型)、Content Transfer-encoding(指定用于这个MIME部件的编码)、 Content-ID或Content-Location(作为从MIME包的任何地方引用这些内容的标识符)。MIME消息的根部件包含SOAP信封,Content-Type被设置为text/xml。

9.2 SOAP对附件的引用

SOAP报头和SOAP消息的主体都可以引用消息包中的其它实体。根据 SOAP 1.1 编码规则,SOAP的“href”属性可用于引用任何资源。任何资源都可以使用Content-ID或者Content-Location引用。如果使用Content-ID作为标识符,那么模式属性(例如href)必须使用URL模式CID。如果使用Content-Location作为标识符,那么必须根据 带附件的 SOAP规范中指定的规则进行解析,其中解析是基于下列要素之一:

绝对URI引用 ― 绝对URI是SOAP信封中的Content-Location和“href”属性中指定的。相对URI引用― MIME消息主报头的Content-Location中指定了一个基础(base)URI,对所有的相对URL都是使用这个基础URL进行引用.不带基础URI的相对URI ― 主报头的Content-Location中没指定基础URI,但使用消息的基础URL,并且对所有的相对URL都是使用这个基础URL进行引用。

通常由SOAP处理器决定是否需要解析URI。而且,消息包中可能有在SOAP信封中没有URI引用的附件。

9.3 HTTP绑定

如果HTTP绑定被SOAP用来发送附件,就需要修改HTTP报头使其包含来自SOAP MIME包报头的Content-Type信息。HTTP报头中不包含来自MIME包报头的其它报头信息。Apache忽略了报头信息比如Content-Transfer-Encoding和MIME Version 。所有的MIME部件都包含SOAP信封部件和其它附件,构成HTTP主体。另一方面,对于 SMTP绑定来说,所有的多部件MIME报头都会被作为SMTP报头的一部分存储。这样,SOAP处理器和应用程序就应该知道这些报头与不同种类的 SOAP 绑定的不兼容性。

9.4 WSDL支持

WSDL支持描述带附件的Web服务。

<binding name="DocManagementService_Binding"  ... />
  <operation  name="SubmitArrayOfDocuments">
    <soap:operation soapAction="http://www.DocManagementService.com/SubmitArrayOfData"/>
    <input>
      <mime:multipartRelated>
          <mime:part>
            <soap:body
    encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
    namespace="urn:DocManagement-service"
    parts="SubmitArrayOfDocuments_inType1 SubmitArrayOfDocuments_inType2"
    use="encoded"/>
          </mime:part>
          <mime:part>
            <mime:content part="SubmitArrayOfDocuments_inType3" type="*/*"/>
          </mime:part>
    </mime:multipartRelated>
    </input>
    <output>
      <soap:body
    encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
    namespace="urn:DocManagement-service" 
    use="encoded"/>
    </output>
  </operation>
</binding>

binding元素的input和output元素被扩展,并且包含了带有不同MIME部件的MIME:multipart-related,其中一个MIME部件用于 SOAP主体,其它的用于附件。每个带附件的MIME部件也都可以指定其内容类型。

========================================================================

SOAP协议示例

SOAP 1.2 请求和响应示例。所显示的占位符需替换为实际值。

//SOAP 1.2 请求
POST /WebServices/WeatherWS.asmx HTTP/1.1
Host: ws.webxml.com.cn
Content-Type: application/soap+xml; charset=utf-8
Content-Length: length

<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
  <soap12:Body>
    <getWeather xmlns="http://WebXml.com.cn/">
      <theCityCode>string</theCityCode>
      <theUserID>string</theUserID>
    </getWeather>
  </soap12:Body>
</soap12:Envelope>


//SOAP 1.2 响应
HTTP/1.1 200 OK
Content-Type: application/soap+xml; charset=utf-8
Content-Length: length

<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
  <soap12:Body>
    <getWeatherResponse xmlns="http://WebXml.com.cn/">
      <getWeatherResult>
        <string>string</string>
        <string>string</string>
      </getWeatherResult>
    </getWeatherResponse>
  </soap12:Body>
</soap12:Envelope>

 HTTP GET 请求和响应示例。所显示的占位符需替换为实际值。

GET /WebServices/WeatherWS.asmx/getWeather?theCityCode=string&theUserID=string HTTP/1.1
Host: ws.webxml.com.cn
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length

<?xml version="1.0" encoding="utf-8"?>
<ArrayOfString xmlns="http://WebXml.com.cn/">
  <string>string</string>
  <string>string</string>
</ArrayOfString>

 HTTP POST 请求和响应示例。所显示的占位符需替换为实际值。

POST /WebServices/WeatherWS.asmx/getWeather HTTP/1.1
Host: ws.webxml.com.cn
Content-Type: application/x-www-form-urlencoded
Content-Length: length

theCityCode=string&theUserID=string
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length

<?xml version="1.0" encoding="utf-8"?>
<ArrayOfString xmlns="http://WebXml.com.cn/">
  <string>string</string>
  <string>string</string>
</ArrayOfString>

 参考文章

​​​​​​SOAP协议解析_tuowsh的博客-CSDN博客​​​​​​

 WeatherWS Web 服务

以上是关于SOAP传输协议的主要内容,如果未能解决你的问题,请参考以下文章

onvif 开发中的一些重要函数介绍

基于ONVIF协议的摄像头开发总结

onvid提示账号密码错误

SOAP传输协议

ONVIF,GB28181是干啥用的

08_使用TCP/IP Monitor监视SOAP协议