SOAP技术与B2B应用集成(2)

SOAP 技术与 B2B 应用集成( 2 )

SOAP 的消息结构与数据的组织方法

本文最初由 IBM developerWorks 中国网站 发表,其网址是
http://www.ibm.com/developerWorks/cn/

SOAP 为在一个松散的、分布的环境中使用 XML 对等地交换结构化的和类型化的信息提供了一个简单的轻量级机制。而传送信息的基本单元承载体就是 SOAP 消息。从根本上来看, SOAP 消息是从发送方到接受方的一种传输方法,但就象前面 ** SOAP ** ** 技术及应用概览 ** 一文中阐述的那样, SOAP 消息一般会和实现模式结合,例如请求 / 响应。 SOAP 的实现可以为特殊网络系统的特有特征来优化。例如,通过 HTTP binding 将 SOAP 响应消息通过 HTTP 响应来传输,请求和响应使用同一连接。

当然,无论 SOAP 是与哪种协议绑定,它都使用同一种消息的描述框架格式,这种框架格式就是以 SOAP Envelope(SOAP 信封 ) 为根元素,内含 SOAP Header 和 SOAP Body 子元素的这样一个 XML 文档。 SOAP 消息描述文本是一种 XML Application 。之所以称之为描述框架,而不称为描述,是因为 SOAP 规范为 SOAP Header 和 SOAP Body 定义了强大的扩展机制,使用户可以按需要在其中增加与应用相关的自定义描述格式, SOAP 规范只是定义了消息描述的一个骨架。

所有的 SOAP 消息都是使用 XML 格式来编码的。 SOAP 应用程序在生成由 SOAP 定义的所有元素和属性的时候,应该包含恰当的 SOAP 的命名空间。 SOAP 应用程序必须能处理其收到的消息中的 SOAP 命名空间。它必须丢弃那些包含不正确命名空间的消息,并且可以处理那些不包含 SOAP 命名空间的 SOAP 消息,就好象他们包含了正确的命名空间一样。

SOAP 定义了两个命名空间:

SOAP 信封的命名空间标识为 http://schemas.xmlsoap.org/soap/envelope/

SOAP 编序的命名空间标识为 http://schemas.xmlsoap.org/soap/encoding/

SOAP 消息必须不包含 DTD ,同时 SOAP 消息也必须不包含 PI(Processing Instructions) 。

除 SOAP mustUnderstand attribute 和 SOAP actor attribute 外,一般允许属性及属性值自由地选择是在 XML 实例中描述还是在 XML Schema 中描述,当然前提是他们具有相同的效果。也就是说,在模式 (schema) 中使用默认值或固定值定义在语义上等价于在实例中的值定义。

例如:在 Schema 中定义

  1<element fixed="”DealEasy”" name="”company”" type="”string”">
  2
  3然后在  XML  实例中定义 
  4
  5<company></company>
  6
  7与直接在  XML  实例中定义 
  8
  9<company>DealEasy</company>
 10
 11在语义上是等价的。 
 12
 13##  SOAP  的消息框架 
 14
 15SOAP  消息是由一个强制的  SOAP Envelope  、一个可选的  SOAP Header  和一个强制的  SOAP Body  组成的  XML  文档。作为  SOAP  消息的该  XML  文档将在本规范的其余部分被引用。而本节的元素和属性的命名空间标识是  http://schemas.xmlsoap.org/soap/envelope/  。  SOAP  消息应当包含如下部分: 
 16
 17§  Envelope  是表示该消息的  XML  文档的顶级元素 
 18
 19§  Header  则是为了支持在松散环境下在通讯方之间尚未预先达成一致的情况下为  SOAP  消息增加特性的通用机制。  SOAP  定义了很少的一些属性来用于指明谁可以处理该特性以及它是可选处理的还是强制处理的。 
 20
 21§  Body  为该消息的最终接收者所想要得到的那些必须处理的信息提供了一个容器。此外,  SOAP  定义了  Body  的一个子元素  Fault  用于报告错误。 
 22
 23这些  XML  元素的语法规则如下: 
 24
 251\.  Envelope 
 26
 27§  元素名为  Envelope 
 28
 29§  该元素必须在  SOAP  消息中出现,一般是根元素 
 30
 31§  该元素可以包含命名空间申明和额外的属性。如果出现额外属性  (  并非是  SOAP  规范预定义的属性  )  ,则必须使用命名空间修饰。类似的,该元素可以包含额外的子元素,这些子元素如果出现,必须有命名空间修饰并且必须跟在  SOAP Body  元素之后,也就是说  Envelope  的直接子元素  Header  和  Body  必须排列在最前面。 
 32
 332\.  Header 
 34
 35§  元素名为  Header 
 36
 37§  该元素可以在  SOAP  消息中出现,但并不是必须出现  (  也就是说可以仅使用  Body  元素完成一次  SOAP  消息的信息描述  )  。如果出现,该元素必须是  SOAP Envelope  元素的第一个直接子元素。 
 38
 39§  该元素可以包含一系列的  Header  条目,这些条目都应当是  Header  元素的直接子元素。  Header  的所有直接子元素必须有命名空间修饰。 
 40
 41§  Header  条目自身可以包含下级子元素,但这些元素不是  Header  条目,而是  Header  条目的内容。 
 42
 433\.  Body 
 44
 45§  元素名为  Body 
 46
 47§  该元素必须在  SOAP  消息中出现,同时必须是  SOAP Envelope  元素的一个直接子元素。若该消息中包含  Header  元素,则  Body  元素必须直接跟随  Header  ,为  Header  元素的相邻兄弟元素。若  Header  不出现,则其必须是  Envelope  的第一个直接子元素。 
 48
 49§  该元素可以包含一系列的  Body  条目,这些条目都应当是  Body  元素的直接子元素。  Body  的所有直接子元素必须有命名空间修饰。  SOAP  定义了  SOAP Fault  元素,它用来指示调用错误的信息。 
 50
 51§  Boidy  条目自身可以包含下级子元素,但这些元素不是  Body  条目,而是  Body  条目的内容。 
 52
 53下面是一个  SOAP  消息的例子,其中  Envelope  包含一个  Header  元素和一个  Body  元素。  Header  元素有两个  Header  条目,他们的命名空间修饰都是  uniB2B  ,两个  Header  条目各有一个子元素。而  Body  元素有一个  Body  条目,该条目包含两个子元素。 
 54
 55<soap-env:envelope envelope="" http:="" schemas.xmlsoap.org="" soap="" soap-env:encodingstyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soap-env="”" ”="">
 56<soap-env:header>
 57<unib2b:accessauthenticated xmlns:unib2b="”Some-URI”">
 58<sessionkey>76E4#12A@-98JA#V5GQ</sessionkey>
 59</unib2b:accessauthenticated>
 60<unib2b:getlastproductprice xmlns:unib2b="Some-URI">
 61<price>243900.00</price>
 62</unib2b:getlastproductprice>
 63</soap-env:header>
 64<soap-env:body>
 65<unib2b:requestpurchaseorder xmlns:unib2b="Some-URI">
 66<productid>Jaguar_X_Type</productid>
 67<productprice>243900.00</productprice>
 68</unib2b:requestpurchaseorder>
 69</soap-env:body>
 70</soap-env:envelope>
 71
 72##  SOAP encodingStyle  属性 
 73
 74SOAP  的全局  encodingStyle  属性被用于指明在  SOAP  消息中使用哪种编序规则。该属性可以在任意元素中出现,并且其作用范围包括该元素的内容和所有其子元素中未使用该属性的所有子元素,这就象  XML  命名空间定义的作用范围一样,是向下传递的。对于一个  SOAP  消息来说,没有默认的编码定义。 
 75
 76SOAP encodingStyle  属性的值是一个或多个用于标识编序规则  (  对数据类型和数据类型实例的描述规则  )  和用于标识解序  SOAP  消息的规则的有序列表,其排序是按照详尽程度从大到小排列。下面是一些值的例子: 
 77
 78"http://schemas.xmlsoap.org/soap/encoding/"   
 79"http://schema.dealeasy.com/soap/encoding/ http://schema.dealeasy.com/soap/encoding/additional/"   
 80"" 
 81
 82而  SOAP  规范中定义的编序规则的标识为  http://schemas.xmlsoap.org/soap/encoding/  。消息若要使用特别的编序应该使用  SOAP encodingStyle  属性来指明。另外,所有在句法上由  http://schemas.xmlsoap.org/soap/encoding/  开始的  URI  序列表明这其中包含的所有  URI  都与  SOAP  规范中定义的  SOAP  编码规则相一致。  (  虽然可能会添加潜在的更为严格的规则,也就是说  http://schemas.xmlsoap.org/soap/encoding/  标识的编码规则是一个编码的基类  ) 
 83
 84一个空值的  URI(  “”  )  明确地指明并未为其所包含的元素声明任何编码风格。这可以为包含的元素关闭任何前面预先的声明。 
 85
 86##  SOAP Header 
 87
 88SOAP  提供了一个可扩展的机制用于在分散的网络环境下,模块化地扩展  SOAP  消息的描述能力,而通讯双方并不需要有完整的预先的约定。典型的扩展例子可以是实现一些诸如认证、事务管理以及支付的  Header  条目,当然对于更复杂的多步骤的  B2B  协同,通过扩展相对复杂的  Header  条目也可以实现,在前面的文章  ** SOAP  ** ** 技术及应用概览  ** 中就有一个完整的例子。 
 89
 90按照  SOAP  的语法,  Header  元素应当被编码为  SOAP Envelope XML  文档的第一直接子元素。  Header  的所有直接子元素都被称为  Header  条目。 
 91
 92Header  条目的编码规则包括: 
 93
 941\.  一个  Header  条目由一个完整修饰的元素名来标识,所谓完整修饰的元素名是由一个命名空间  URI  和局部名来组成。  SOAP Header  元素的所有直接子元素都必须是完整修饰的。不允许任何不带命名空间修饰的  Header  条目存在。 
 95
 962\.  SOAP encodingStyle  属性可以用于指明  Header  条目的编码风格,而  encodingStyle  属性在前面已经详细介绍了。 
 97
 983\.  SOAP mustUnderstand  属性和  SOAP actor  属性可以用于指明如何处理条目和由谁来处理条目。 
 99
100在  SOAP Header  中,  SOAP Header  属性的设置是为了让  SOAP  消息的接收者了解应该如何处理该消息。一个生成  SOAP  消息的  SOAP  应用程序应该仅使用  SOAP Header  元素的直接子元素的  SOAP Header  属性。而对于那些并非作为  SOAP Header  元素的直接子元素出现的  SOAP Header  属性,  SOAP  消息的接受者必须忽略。 
101
102以下是一个  Header  的例子,其中包含了一个元素标识  Priority  和一个  mustUnderstand  属性及其值  1  ,以及  Priority  的值  7  ,该元素表明该消息的处理优先权为  7  。 
103
104<soap-env:header>
105<unib2b:priority soap-env:mustunderstand="1" xmlns:unib2b="some-URI">   
1067   
107</unib2b:priority>
108</soap-env:header>
109
110##  SOAP actor  属性 
111
112SOAP  消息从生成者到达最终接受者,将潜在地沿着消息路径  (message path)  经过一系列的  SOAP  中间介。  SOAP  中间介是一个能够接受和转发  SOAP  消息的应用程序。所有的中间介都如同最终接受者一样由一个  URI  来标识。 
113
114并非一个  SOAP  消息的所有部分都是最终接收者需要了解的调用信息,其中部分是路径中的一个或多个中间介所需要处理的。  Header  元素中接收者角色类似合约的接受者,他并不能将其交给其它方。也就是说,一个接收者接到其需要接收的  Header  元素必须不转发该  Header  给  SOAP  消息路径中的下一个应用程序。该接收者可以插入一个类似的  Header  元素,但在这个情况下,合约关系存在于该应用程序及下一个  Header  元素的接收者之间了。 
115
116SOAP actor  全局属性可以被用于指明  Header  元素的接收者。而  SOAP actor  属性的值是一个  URI  。  URI: http://schemas.xmlsoap.org/soap/actor/next  指明该  Header  元素是直接的下一个进行消息处理的  SOAP  应用程序需要处理的。这与  HTTP  的连接头字段的  hop-by-hop scope model  的表示是一致的。 
117
118若省略  SOAP actor  属性,则表明该消息的接收者是  SOAP  消息的最终接收者。 
119
120** 对于一个  SOAP  ** ** 消息的实例  (  ** ** 在实际传输中的  SOAP  ** ** 消息  )  ** ** ,这个属性必须出现以指明该消息的接收方的  URI  ** ** 。  **
121
122##  SOAP mustUnderstand  属性 
123
124SOAP mustUnderstand  全局属性用于指明一个  Header  条目是强制必须处理的还是可选的要求接收者处理的。  Header  条目的接收者由  SOAP actor  属性来定义。  mustUnderstand  属性的值可取为“  0  ”或“  1  ”。若没有使用  SOAP mustUnderstand  属性,则在语义上等价于  mustUderstand  属性出现同时取值为“  0  ”。 
125
126若  Header  元素带有值为“  1  ”的  SOAP mustUnderstand  属性,则该  Header  条目的接收者要么必须遵循语义  (  由具备完整修饰的元素名来传达  )  并正确地处理这些语义,要么必须宣称处理消息失败。也就是说如果该应用程序发现自己无法识别某一个  Header  条目  (  应为在自己的处理逻辑里面没有该条目  )  ,那么必须申明错误,并响应该错误信息。 
127
128SOAP mustUnderstand  属性是为了考虑健壮地升级而设置的。所有用值为“  1  ”的  SOAP mustUnderstand  属性来标记的元素必须被认为是可以影响该元素的上级元素或同级元素的语义。而这种风格标记的元素应保证对语义的修改并不能被那些不能完全理解该修改后的语义的那些元素静默地或假设地、不正确地忽略。 
129
130** 该属性若要生效必须在实例中出现,也就是说不能依靠  XML Schema  ** ** 的缺省值或固定值的设置来使该属性生效。。  **
131
132##  SOAP Body 
133
134SOAP Body  元素提供一个简单的用于与消息的最终接收者交换信息  (  这些信息都是必须处理的  )  的机制。而  Body  元素的典型应用包含序列的  RPC  调用和错误报告。 
135
136Body  元素在编码上应当作为  SOAP Envelope  元素的一个直接子元素。如果包含  Header  元素,则  Body  元素必须直接跟随  Header  元素,为  Header  元素的直接下一个兄弟元素,否则  Body  元素必须是  Envelope  元素的第一直接子元素。 
137
138所有  Body  元素的直接子元素被称为  Body  条目,同时每一个  Body  条目都应当编码为  SOAP Body  元素里的一个独立元素。 
139
140Body  条目的编码规则包括: 
141
1421\.  一个  Body  条目由一个完整修饰的元素名来标识,所谓完整修饰的元素名是由一个命名空间  URI  和局部名来组成。  SOAP Body  元素的直接子元素可以是命名空间修饰的。 
143
1442\.  SOAP encodingStyle  属性可以被用来表明  Body  条目中使用的编码规则。 
145
146SOAP  只预定义了一个  Body  条目:用于向调用方报告错误的  Body  条目  :Fault  。 
147
148##  SOAP Body  的应用 
149
150下面是一对  SOAP  调用  /  响应的例子,在调用消息中  Body  包含了一个描述调用方法的  Body  条目  RequestPurchaseOrder  ,它包含两个参数  ProductID  &lt;SPAN style="FONT-FAMILY: 宋体;</element>
Published At
Categories with Web编程
Tagged with
comments powered by Disqus