SOAP技术与B2B应用集成——SOAP的消息结构与数据的组织方法![]() | ![]() |
![]() |
级别: 初级 柴晓路, Chief System Architect 2001 年 4 月 01 日 本文延续前文 SOAP技术和应用概览, 结合应用实例,对SOAP消息的结构做了详细而精确地阐述,通过对SOAPEnvelope、SOAP Header、SOAPBody的详细介绍使用户对如何使用SOAP消息来描述RPC调用和响应有了一个完整而深入地了解,并为本系列后面的介绍SOAP 消息中数据的编码规则的文章奠定了结构基础。 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消息必须不包含DTD,同时SOAP消息也必须不包含PI(Processing Instructions)。 除SOAP mustUnderstand attribute和SOAP actor attribute外,一般允许属性及属性值自由地选择是在XML实例中描述还是在XML Schema中描述,当然前提是他们具有相同的效果。也就是说,在模式(schema)中使用默认值或固定值定义在语义上等价于在实例中的值定义。 例如:在Schema中定义
然后在XML实例中定义
与直接在XML实例中定义
本文所引用的资源主要包括两类,一类用于解决B2B电子商务应用交互和集成的系列技术标准规范,他们与SOAP是一个不可分割的技术体系,包括UDDI、 SOAP、WSDL、XML等,另一类是SOAP的开发软件包,包括Microsoft的SOAP软件包SOAPToolkit和Apache Project的SOAP Package。本文的最后给出了这些资源的链接,有兴趣的读者可以通过这些 资源链接找到所需的内容 SOAP消息是由一个强制的SOAP Envelope、一个可选的SOAP Header和一个强制的SOAP Body组成的XML文档。作为SOAP消息的该XML文档将在本规范的其余部分被引用。而本节的元素和属性的命名空间标识是http://schemas.xmlsoap.org/soap/envelope/。SOAP消息应当包含如下部分:
这些XML元素的语法规则如下:
下面是一个SOAP消息的例子,其中Envelope包含一个Header元素和一个Body元素。Header元素有两个Header条目,他们的命名 空间修饰都是uniB2B,两个Header条目各有一个子元素。而Body元素有一个Body条目,该条目包含两个子元素。
SOAP的全局encodingStyle属性被用于指明在SOAP消息中使用哪种编序规则。该属性可以在任意元素中出现,并且其作用范围包括该元素的内 容和所有其子元素中未使用该属性的所有子元素,这就象XML命名空间定义的作用范围一样,是向下传递的。对于一个SOAP消息来说,没有默认的编码定义。 SOAP encodingStyle属性的值是一个或多个用于标识编序规则(对数据类型和数据类型实例的描述规则)和用于标识解序SOAP消息的规则的有序列表,其排序是按照详尽程度从大到小排列。下面是一些值的例子:
而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/标识的编码规则是一个编码的基类) 一个空值的URI(“”)明确地指明并未为其所包含的元素声明任何编码风格。这可以为包含的元素关闭任何前面预先的声明。
SOAP提供了一个可扩展的机制用于在分散的网络环境下,模块化地扩展SOAP消息的描述能力,而通讯双方并不需要有完整的预先的约定。典型的扩展例子可 以是实现一些诸如认证、事务管理以及支付的Header条目,当然对于更复杂的多步骤的B2B协同,通过扩展相对复杂的Header条目也可以实现,在前 面的文章SOAP技术及应用概览中就有一个完整的例子。 按照SOAP的语法,Header元素应当被编码为SOAP Envelope XML文档的第一直接子元素。Header的所有直接子元素都被称为Header条目。 Header条目的编码规则包括:
在SOAP Header中,SOAP Header属性的设置是为了让SOAP消息的接收者了解应该如何处理该消息。一个生成SOAP消息的SOAP应用程序应该仅使用SOAP Header元素的直接子元素的SOAP Header属性。而对于那些并非作为SOAP Header元素的直接子元素出现的SOAP Header属性,SOAP消息的接受者必须忽略。 以下是一个Header的例子,其中包含了一个元素标识Priority和一个mustUnderstand属性及其值1,以及Priority的值7,该元素表明该消息的处理优先权为7。
SOAP消息从生成者到达最终接受者,将潜在地沿着消息路径(message path)经过一系列的SOAP中间介。SOAP中间介是一个能够接受和转发SOAP消息的应用程序。所有的中间介都如同最终接受者一样由一个URI来标识。 并非一个SOAP消息的所有部分都是最终接收者需要了解的调用信息,其中部分是路径中的一个或多个中间介所需要处理的。Header元素中接收者角色类似 合约的接受者,他并不能将其交给其它方。也就是说,一个接收者接到其需要接收的Header元素必须不转发该Header给SOAP消息路径中的下一个应 用程序。该接收者可以插入一个类似的Header元素,但在这个情况下,合约关系存在于该应用程序及下一个Header元素的接收者之间了。 SOAP actor全局属性可以被用于指明Header元素的接收者。而SOAP actor属性的值是一个URI。URI: http://schemas.xmlsoap.org/soap/actor/next指明该Header元素是直接的下一个进行消息处理的SOAP应用程序需要处理的。这与HTTP的连接头字段的hop-by-hop scope model的表示是一致的。 若省略SOAP actor属性,则表明该消息的接收者是SOAP消息的最终接收者。 对于一个SOAP消息的实例(在实际传输中的SOAP消息),这个属性必须出现以指明该消息的接收方的URI。
SOAP mustUnderstand全局属性用于指明一个Header条目是强制必须处理的还是可选的要求接收者处理的。Header条目的接收者由SOAP actor属性来定义。mustUnderstand属性的值可取为“0”或“1”。若没有使用SOAP mustUnderstand属性,则在语义上等价于mustUderstand属性出现同时取值为“0”。 若Header 元素带有值为“1”的SOAP mustUnderstand属性,则该Header条目的接收者要么必须遵循语义(由具备完整修饰的元素名来传达)并正确地处理这些语义,要么必须宣称 处理消息失败。也就是说如果该应用程序发现自己无法识别某一个Header条目(应为在自己的处理逻辑里面没有该条目),那么必须申明错误,并响应该错误 信息。 SOAP mustUnderstand属性是为了考虑健壮地升级而设置的。所有用值为“1”的SOAP mustUnderstand属性来标记的元素必须被认为是可以影响该元素的上级元素或同级元素的语义。而这种风格标记的元素应保证对语义的修改并不能被那些不能完全理解该修改后的语义的那些元素静默地或假设地、不正确地忽略。 该属性若要生效必须在实例中出现,也就是说不能依靠XML Schema的缺省值或固定值的设置来使该属性生效。
SOAP Body元素提供一个简单的用于与消息的最终接收者交换信息(这些信息都是必须处理的)的机制。而Body元素的典型应用包含序列的RPC调用和错误报告。 Body元素在编码上应当作为SOAP Envelope元素的一个直接子元素。如果包含Header元素,则Body元素必须直接跟随Header元素,为Header元素的直接下一个兄弟元素,否则Body元素必须是Envelope元素的第一直接子元素。 所有Body元素的直接子元素被称为Body条目,同时每一个Body条目都应当编码为SOAP Body元素里的一个独立元素。 Body条目的编码规则包括:
SOAP只预定义了一个Body条目:用于向调用方报告错误的Body条目:Fault。
下面是一对SOAP调用/响应的例子,在调用消息中Body包含了一个描述调用方法的Body条目RequestPurchaseOrder,它包含两个 参数ProductID和ProductPrice。而在响应消息中,Body中包含了一个Body条目ResponsePurchaseOrder用于 描述响应调用的返回信息,其中包含OrderID、AuthenticatedID、ProductID、ProductNumber、 IssueDate。 RPC调用的SOAP消息表示
RPC响应的SOAP消息表示
Header和Body在定义上是独立的,但在事实上是相联系的。一个Body条目和一个Header条目的关系是:一个Body条目在语义上与这样一个Header条目等价:该Header条目将由默认参与者(最终接受者)解释同时由值为“1”的SOAP mustUnderstand属性标记。默认参与者可以不使用actor属性的方式来指明。
SOAP Fault元素是用于在SOAP消息中传输错误及状态信息。如果SOAP消息需要包含SOAP Fault元素的话,它必须作为一个Body条目出现,同时在Body元素内它必须不出现多于一次(至多出现一次)。 SOAP Fault元素定义了如下子元素:
Detail条目的编码规则如下:
当描述由本规范定义的错误的时候,faultcode元素必须使用在本节中定义的faultode的值。这些faultcode值的命名空间标识为http://schemas.xmlsoap.org/soap/envelope/。 默认的SOAP faultcode值是按照一种可扩展的风格来定义的,它允许在维持以有的faultcode值的向后兼容的基础定义新的SOAP faultcode值。这一机制在使用上非常类似与HTTP中基本状态类的定义1xx, 2xx, 3xx等。不过,他们是用XML修饰名来定义,而不是用整数。“.”符号是faultcode值的分隔符,用于指明“.”左边的是一个比右边更泛化的错误代码。例如:
在本文档中定义的faultcode值集合是:
本文介绍了SOAP消息的消息结构及SOAP消息各个元素的XML语法和具体应用方法,我将在下一篇文章中详细描述在SOAP元素中如何描述具体数据(数据结构/数据实例),并详细介绍用于描述数据的SOAP编码规则的语法。 |