14.3 XML和SOAP协议

SOAP是Simple Object Access Protocol(即简单对象访问协议)的简称,SOAP协议以XML作为数据传输格式,底层可以采用HTTP、SMTP等协议作为传输协议。不管是XML文档,还是HTTP、SMTP等协议,它们都是平台无关的,因此SOAP可以非常方便地解决异构系统相互通信的问题。

2000年5月,IBM、Microsoft和HP等公司向W3C提交了SOAP,第一个SOAP的公共工作草案于2001年12月发布。2007年4月,W3C组织发布了最新的SOAP 1.2版本,这也是本书所介绍的SOAP的版本。

14.3.1 SOAP基本语法

SOAP消息基于XML文档构建,一条SOAP消息就是一份特定的XML文档,SOAP消息包含以下3个主要元素:

alt 必需的<Envelope…/>根元素,SOAP消息对应的XML文档以该元素作为根元素。

alt 可选的<Header../>元素,包含SOAP消息的头信息。

alt 必需的<Body../>元素,包含所有的调用和响应信息。

就目前的SOAP消息的结构来看,<Envelope…/>根元素通常只能包含两个子元素,第一个子元素是可选的<Header../>元素,第二个子元素是必需的<Body../>元素。

上面的所有元素都位于SOAP所定义的命名空间中,该命名空间如下:

alt

下面是一份来自www.w3.org的SOAP消息示例:

alt

<Header…/>元素以一种非集中的方式增加SOAP消息的功能,其每个子元素都称为一个Header block,如果该子元素指定的值是必需的,则应该为属性增加mustUnderstand="true",否则无须指定。SOAP本身并没有定义内置的Header block,它只定义了一个有效负载,就是用于报告错误的<Fault…/>元素。图14.3显示了SOAP消息的基本结构。

alt

图14.3 SOAP消息的基本结构

14.3.2 Header元素

<Header…/>元素是一个可选的元素,专门用于定义SOAP的头部信息。这些头部信息主要用于传递应用程序业务相关的信息(比如认证、支付等)。如果Header 元素被提供,则它必须是<Envelope…/>元素的第一个子元素。

例如,下面的SOAP消息片段:

alt

上面的SOAP例子包含了一个带有<price…/>子元素的头部,该子元素的值是99.00,其mustUnderstand属性的值是true,这表明该<price…/>子元素的值必须得到处理。

SOAP在默认的命名空间(http://www.w3.org/2003/05/soap-envelope)中定义了3个属性:role、mustUnderstand和encodingStyle。这些属性用于指定容器应该如何处理SOAP 消息。

role属性

SOAP消息将从发送者单向传递到接收者,多个单向消息的组合可以形成较为复杂的模式,可以发送和接收SOAP消息的软件代理都称为SOAP节点。启动消息传递的SOAP节点称为原始发送节点,使用和处理SOAP消息的最后一个节点称为最终接收节点。位于原始发送节点和最终接收节点之间的任一节点都称为中介节点。

中介节点既是SOAP消息的接收者,也是SOAP消息的发送者,它主要用于实现消息的分布式处理,消息经过的所有中介节点和最终接收节点统称为消息路径。图14.4显示了消息路径示例。

alt

图14.4 消息路径示例

SOAP消息沿着消息路径经过不同的节点,可以从某个发送者传播到某个接收者。并非SOAP消息的所有部分均打算传送到SOAP 消息的最终接收节点,另一方面,SOAP消息的某个部分也许希望传送给消息路径上的一个或多个中介节点。

在这样的情形下,可以通过SOAP消息的role属性来指定将<Header…/>元素寻址到一个或多个特定的节点。SOAP为role属性定义了几个标准属性值:"none"、"next"和"ultimateReceiver",这些标准属性值都位于命名空间http://www.w3.org/2003/05/soap-envelope/role/之下,关于这几个属性值的说明如表14-1所示。

表14.1 role属性的标准属性值

alt

如果没有指定role属性,则相当于将role属性值指定为"ultimateReceiver"。

例如,下面的SOAP消息片段:

alt

mustUnderstand属性

SOAP消息的mustUnderstand属性可以用于指示在该Header block未被认出的情况下,该节点是否可以忽略该Header block,带有mustUnderstand="true"的Header block称为必需Header block;带有mustUnderstand="false"或未指定mustUnderstand属性的Header block称为可选Header block。

14.3.3 Body元素

SOAP消息依靠必需的<Body…/>元素来包含实际的SOAP消息。

<Body…/>元素里可以包含任何合法的子元素,用于包含实际需要传递的SOAP消息。例如,下面的SOAP请求:

alt

上面的SOAP请求消息希望获取“疯狂Java讲义”的价格,在该SOAP消息的<Body…/>元素内的<getPrice…/>元素和<book…/>子元素都是应用程序专用的元素,它们并不是SOAP标准的一部分。Body元素里的内容只要满足WSDL文档所规范的约束即可。

对于上面的SOAP请求消息,对应的SOAP响应消息可能如下:

alt

14.3.4 Fault元素

<Fault…/>元素用于处理SOAP消息内部的错误和状态信息,来自SOAP消息的错误将被保存在<Fault…/>元素之内。<Fault…/>元素可以接受以下几个可选的子元素:

alt <Code…/>:保存识别错误的错误代码。

alt <Reason…/>:保存可供人阅读的引发错误的原因。

alt <Node…/>:保存消息路径上引发该错误的SOAP节点。

alt <Role…/>:保存引发该错误的SOAP节点在消息路径上所扮演的角色。

alt <Detail…/>:保存关于该错误的、应用程序特定的错误信息。

图14.5显示了<Fault…/>元素的内部结构。

alt

图14.5 Fault元素的内部结构

下面的SOAP消息片段包含了<Fault…/>元素来保存错误信息:

alt


alt注意

<Fault…/>元素内的5个子元素并不是必需的,不同的Web Service服务提供者响应生成的SOAP文档里的<Fault…/>元素内可以包含不同的子元素。有些Web Service服务提供者在<Fault…./>元素中并不放置上面介绍的这5个元素,而是放置一些其他功能相似的元素。