<account>3514</account>
<amount>-100.0</amount>
<auditlevel>3</auditlevel>
</from>
<to>
<account>3518</account>
<amount>100.0</amount>
</to>
</t:transfer> 在這里xsd:type屬性引用一個(gè)名域限定的類型名,它能被反序列化程序用于實(shí)例化對(duì)象的正確類型。因?yàn)閠o存取元素引用到一個(gè)被預(yù)料的類型的實(shí)例(而不是一個(gè)可代替的繼承類型),xsd:type屬性是不需要的。
剛才的transfer類設(shè)法回避了一個(gè)關(guān)鍵問題。如果正被序列化的transfer對(duì)象用下面這種方式初始化將會(huì)發(fā)生什么情況:
transferxfer=newtransfer();
xfer.from=newadjustment();
xfer.from.account=3514;xfer.from.amount=-100;
xfer.to=xfer.from;
基于以前的議論,在SOAP中transfer對(duì)象的序列化形式如下所示:
<t:transferxmlns:t=''urn:develop-com:java:com.bofsoap.IBank''>
<from>
<account>3514</account>
<amount>-100.0</amount>
</from>
<to>
<account>3514</account>
<amount>-100.0</amount>
</to>
</t:transfer>
這個(gè)表達(dá)有兩個(gè)問題。首先最容易理解的問題是同樣的信息被發(fā)送了兩次,這導(dǎo)致了一個(gè)比實(shí)際所需要消息的更大的消息。一個(gè)更微妙的但是更重要的問題是由于反序列化程序不能分辨兩個(gè)帶有同樣值的adjustment對(duì)象與在兩個(gè)地方被引用的一個(gè)單一的adjustment對(duì)象的區(qū)別,兩個(gè)存取元素間的身份關(guān)系就被丟失。如果這個(gè)消息接收者已經(jīng)在結(jié)果對(duì)象上執(zhí)行了下面的測(cè)試,(xfer.to==xfer.from)將不會(huì)返回true。
voidprocessTransfer(transferxfer){
if(xfer.to==xfer.from)
handleDoubleAdjustment(xfer.to);
else
handleAdjustments(xfer.to,xfer.from);
}
為了支持必須保持身份關(guān)系的類型的序列化,SOAP支持多引用存取元素。目前我們接觸到的存取元素是單引用存取元素,也就是說,元素值是嵌入在存取元素下面的,而且其它存取元素被允許引用那個(gè)值(這很類似于在NDR中的[unique]的概念)。多引用存取元素總是被編碼為只包含已知的soap:href屬性的空元素。soap:href屬性總是包含一個(gè)代碼片段標(biāo)識(shí)符,它對(duì)應(yīng)于存取元素引用到的實(shí)例。如果to和from存取元素已經(jīng)被編碼為多引用存取元素,序列化的transfer對(duì)象如下所示:
<t:transferxmlns:t=''urn:develop-com:java:com.bofsoap.IBank''>
<fromsoap:href=''#id1''/>
<tosoap:href=''#id1''/>
</t:transfer>
這個(gè)編碼假設(shè)與adjustment類兼容的一個(gè)類型的實(shí)例已經(jīng)在envelope中的其它地方被序列化,而且這個(gè)實(shí)例已經(jīng)被用soap:id屬性標(biāo)記,如下所示:
<t:adjustmentsoap:id=''id1''xmlns:t=''urn:develop-com:java:com.bofsoap.IBank''>
<account>3514</account>
<amount>-100.0</amount>
</t:adjustment>
第四節(jié)結(jié)語(yǔ)
一個(gè)遺留的HTTP問題還需要進(jìn)一步闡明。SOAP支持(但不需要)HTTP擴(kuò)展框架約定來指定必須的HTTP頭擴(kuò)展。這些約定主要有兩個(gè)目的。首先,它們?cè)试S任意的URI被用于限定給定的HTTP頭的范圍(類似XML名域)。第二,這些約定允許把必須的頭與可選的頭區(qū)分開來(象soap:mustUnderstand)。下面是一個(gè)使用HTTP擴(kuò)展框架來把SOAPMethodName頭定義成為一個(gè)必須的頭擴(kuò)展:
M-POST/foobarHTTP/1.1
Host:209.110.197.2
Man:"urn:schemas-xmlsoap-org:soap.v1;ns=42"
42-SOAPMethodName:urn:bobnsid:IFoo#DoIt
Man頭映射SOAPURI到前綴為42的頭,并表示沒有認(rèn)出SOAP的服務(wù)器必須返回一個(gè)HTTP錯(cuò)誤,狀態(tài)代碼為501(沒有被實(shí)現(xiàn))或510(沒有被擴(kuò)展)。HTTP方法必須是M-POST,表明目前是必須的頭擴(kuò)展。SOAP是一個(gè)被類型化的序列化格式,它恰巧用HTTP作為請(qǐng)求/響應(yīng)消息傳輸協(xié)議。SOAP被設(shè)計(jì)為與正將出現(xiàn)的XMLSchema規(guī)范密切配合,并支持在Internet的任何地方運(yùn)行的COM、CORBA、Perl、Tcl、和Java、C、Python或PHP等程序間的互操作性。