网学网为广大网友收集整理了,简单对象协议(SOAP)简介(2),希望对大家有所帮助!
<br>
存取元素被用作表达类型的域、属性或数据成员。一个给定类型的域在它的SOAP表达将只有一个存取元素。存取元素的标记名对应于类型的域名。考虑下列Java 类定义:<br>
<br>
package com.bofsoap.IBank; <br>
public class adjustment { <br>
public int account ;<br>
public float amount ;<br>
}<br>
在一个SOAP消息中被序列化的实例如下所示:<br>
<br>
<t:adjustment xmlns:t=urn:develop-com:java:com.bofsoap.IBank><br>
<account>3514</account><br>
<amount>100.0</amount><br>
</t:adjustment><br>
在这个例子中,存取元素account和amount被称着简单存取元素。对引用简单类型的存取元素,元素值被简单地编码为直接在存取元素下的字符数据,如上所示。对引用组合类型的存取元素(就是那些自身用子存取元素来构造的存取元素),有两个技术来对存取元素进行编码。最简单的方法是把被结构化的值直接嵌入在存取元素下。考虑下面的Java类定义:<br>
<br>
package com.bofsoap.IBank;<br>
public class transfer {<br>
public adjustment from;<br>
public adjustment to; <br>
}<br>
如果用嵌入值编码存取元素,在SOAP中一个序列化的transfer对象如下所示:<br>
<br>
<t:transfer xmlns:t=urn:develop-com:java:com.bofsoap.IBank><br>
<from><br>
<account>3514</account><br>
<amount>-100.0</amount><br>
</from><br>
<to><br>
<account>3518</account><br>
<amount>100.0</amount><br>
</to><br>
</t:transfer><br>
在这种情况下,adjustment对象的值被直接编码在它们的存取元素下。在考虑组合存取元素时,需要说明几个问题。先考虑上面的transfer类。类的from和to的域是对象引用,它可能为空。SOAP用XML Schemas的null属性来表示空值或引用。下面例子表示一个序列化的transfer对象,它的from域是空的:<br>
<br>
<t:transfer xmlns:t=urn:develop-com:java:com.bofsoap.IBank <br>
xmlns:xsd=http://www.w3.org/1999/XMLSchema/instance><br>
<from xsd:null=true /><br>
<to><br>
<account>3518</account><br>
<amount>100.0</amount> <br>
</to> <br>
</t:transfer><br>
在不存在的情况下, xsd:null属性的隐含值是false。给定元素的能否为空的属性是由XML Schema定义来控制的。例如下列XML Schema将只允许from存取元素为空:<br>
<br>
<type name=transfer ><br>
<element name=from type=adjustment nullable=true /><br>
<element name=to type=adjustment nullable=false/><br>
</type><br>
在一个元素的Schema声明中如果没有nullable属性,就意味着在一个XML文档中的元素是不能为空的。Null存取元素的精确格式当前还在修订中�要了解用更多信息参考最新版本的SOAP规范。<br>
<br>
与存取元素相关的另一个问题是由于类型关系引起的可代换性。由于前面的adjustment类不是一个final类型的类,transfer对象的from和to域实际引用继承类型的实例是可能的。为了支持这种类型兼容的替换,SOAP使用一个名域限定的类型属性的XML Schema约定。这种类型属性的值是一个对元素具体的类型的限制的名字。考虑下面的adjustment扩展类:<br>
<br>
package com.bofsoap.IBank;<br>
public class auditedadjustment extends adjustment {<br>
public int auditlevel;<br>
}<br>
给出下面Java语言:<br>
<br>
transfer xfer = new transfer();<br>
xfer.from = new auditedadjustment();<br>
xfer.from.account = 3514; <br>
xfer.from.amount = -100;<br>
xfer.from.auditlevel = 3;<br>
xfer.to = new adjustment();<br>
xfer.to.account = 3518; <br>
xfer.from.amount = 100;<br>
<br>
在SOAP中transfer对象的序列化形式如下所示:<br>
<br>
<t:transfer xmlns:xsd=http://www.w3.org/1999/XMLSchema<br>
xmlns:t=urn:develop-com:java:com.bofsoap.IBank><br>
<from xsd:type=t:auditedadjustment ><br>
<account>3514</account><br>
<amount>-100.0</amount><br>
<auditlevel>3</auditlevel ><br>
</from><br>
<to><br>
<account>3518</account><br>
<amount>100.0</amount><br>
</to><br>
</t:transfer><br>
<br>
在这里xsd:type属性引用一个名域限定的类型名,它能被反序列化程序用于实例化对象的正确类型。因为to存取元素引用到一个被预料的类型的实例(而不是一个可代替的继承类型),xsd:type属性是不需要的。<br>
<br>
刚才的transfer类设法回避了一个关键问题。如果正被序列化的transfer对象用下面这种方式初始化将会发生什么情况:<br>
<br>
transfer xfer = new transfer();<br>
xfer.from = new adjustment();<br>
xfer.from.account = 3514; xfer.from.amount = -100;<br>
xfer.to = xfer.from;<br>
基于以前的议论,在SOAP 中transfer对象的序列化形式如下所示:<br>
<br>
<t:transfer xmlns:t=urn:develop-com:java:com.bofsoap.IBank><br>
<from><br>
<account>3514</account><br>
<amount>-100.0</amount><br>
</from><br>
<to><br>
<account>3514</account><br>
<amount>-100.0</amount><br>
</to><br>
</t:transfer><br>
这个表达有两个问题。首先最容易理解的问题是同样的信息被发送了两次,这导致了一个比实际所需要消息的更大的消息。一个更微妙的但是更重要的问题是由于反序列化程序不能分辨两个带有同样值的adjustment对象与在两个地方被引用的一个单一的adjustment对象的区别,两个存取元素间的身份关系就被丢失。如果这个消息接收者已经在结果对象上执行了下面的测试,(xfer.to == xfer.from)将不会返回true。<br>
<br>
void processTransfer(transfer xfer) {<br>
if (xfer.to == xfer.from)<br>
handleDoubleAdjustment(xfer.to);<br>
else <br>
handleAdjustments(xfer.to, xfer.from);<br>
}<br>
为了支持必须保持身份关系的类型的序列化,SOAP支持多引用存取元素。目前我们接触到的存取元素是单引用存取元素,也就是说,元素值是嵌入在存取元素下面的,而且其它存取元素被允许引用那个值(这很类似于在NDR中的[unique]的概念)。多引用存取元素总是被编码为只包含已知的soap:href属性的空元素。soap:href属性总是包含一个代码片段标识符,它对应于存取元素引用到的实例。如果to和from存取元素已经被编码为多引用存取元素,序列化的transfer对象如下所示:<br>
<br>
<t:transfer xmlns:t=urn:develop-com:java:com.bofsoap.IBank> <br>
<from soap:href=#id1 /> <br>
<to soap:href=#id1 /> <br>
</t:transfer><br>
这个编码假设与adjustment类兼容的一个类型的实例已经在envelope中的其它地方被序列化,而且这个实例已经被用soap:id属性标记,如下所示:<br>
<br>
<t:adjustment soap:id=id1xmlns:t=urn:develop-com:java:com.bofsoap.IBank><br>
<account>3514</account><br>
<amount>-100.0</amount><br>
</t:adjustment><br>
<br>
<br>
第四节 结语<br>
<br>
一个遗留的HTTP问题还需要进一步阐明。SOAP支持(但不需要)HTTP扩展框架约定来指定必须的HTTP头扩展。这些约定主要有两个目的。首先,它们允许任意的URI被用于限定给定的HTTP头的范围(类似XML名域)。第二,这些约定允许把必须的头与可选的头区分开来(象soap:mustUnderstand)。下面是一个使用HTTP扩展框架来把SOAPMethodName头定义成为一个必须的头扩展:<br>
<br>
M-POST /foobar HTTP/1.1 <br>
Host: 209.110.197.2 <br>
Man: "urn:schemas-xmlsoap-org:soap.v1; ns=42" <br>
42-SOAPMethodName: urn:bobnsid:IFoo#DoIt <br>
Man头映射SOAP URI到前缀为42的头,并表示没有认出SOAP的服务器必须返回一个HTTP错误,状态代码为501 (没有被实现) 或 510 (没有被扩展)。HTTP方法必须是M-POST,表明目前是必须的头扩展。SOAP是一个被类型化的序列化格式,它恰巧用HTTP 作为请求/响应消息传输协议。SOAP被设计为与正将出现的XML Schema规范密切配合,并支持在Internet的任何地方运行的COM、CORBA、Perl、Tcl、和Java、C、Python或 PHP等程序间的互操作性。<br>