日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

SOAP凈化有線協(xié)議(一):SOAP基礎(chǔ)知識

 figol 2006-04-22
 

  一、SOAP簡介

  SOAP用XML作為數(shù)據(jù)編碼格式。用XML作為數(shù)據(jù)編碼格式并非SOAP的原創(chuàng),實際上這是一種相當(dāng)自然的選擇。XML-RPC和ebXML也同樣使用XML。

  請考慮下面的Java接口:

Listing 1

public interface Hello
{
public String sayHelloTo(String
name);
}

  客戶程序在調(diào)用sayHelloTo()方法時提供了一個名字,它希望從服務(wù)器接收到一則個性化的“Hello”信息?,F(xiàn)在,假定RMI、CORBA和DCOM都不存在,開發(fā)者必須負(fù)責(zé)串行化方法調(diào)用,并把消息發(fā)送給遠(yuǎn)程機器。幾乎所有的人都會說“這該使用XML”,我同意。因此,讓我們先從對服務(wù)器的請求格式開始。假設(shè)要模擬sayHelloTo("John")調(diào)用,我打算發(fā)送的請求是:

  Listing 2

<?xml version="1.0"?>
<Hello>
<sayHelloTo>
<name>John</name>
</sayHelloTo>
</Hello>

  在這里,我把接口的名字作為根結(jié)點。另外,我還把方法名字和參數(shù)名字都當(dāng)作節(jié)點。接下來,我們要把這個請求發(fā)送給服務(wù)器。我們不創(chuàng)建自己的TCP/IP消息,而是使用HTTP。因此,下面的步驟應(yīng)該是把請求封裝成HTTP POST請求格式,然后把它發(fā)送給服務(wù)器。實際創(chuàng)建該HTTP POST請求的詳細(xì)過程在本文后面介紹,現(xiàn)在,我們先假定它已經(jīng)創(chuàng)建完畢。服務(wù)器接收到了這個請求,解碼XML,然后再以XML格式向客戶程序發(fā)送應(yīng)答。假設(shè)應(yīng)答內(nèi)容如下:

  Listing 3

<?xml version="1.0"?>
<Hello>
<sayHelloToResponse>
<message>Hello John, How are you?</message>
</sayHelloToResponse>
</Hello>

  根節(jié)點仍然是接口的名字Hello。但這一次,原來對應(yīng)著方法的節(jié)點名字不再是sayHelloTo,而是方法的名字加上“Response”字符串??蛻舫绦蛑雷约赫{(diào)用了哪一個方法,要找出被調(diào)用方法的返回值,它只需查看名字為方法名字加上“Response”字符串的元素。

  以上就是SOAP的根本思路。Listing 4顯示了同一請求用SOAP XML編碼之后的結(jié)果:

  Listing 4

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas./soap/envelope/" xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" xmlns:xsd="http://www./1999/XMLSchema">
<SOAP-ENV:Header>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ns1:sayHelloTo
xmlns:ns1="Hello"
SOAP-ENV:encodingStyle="
http://schemas./soap/encoding/">
<name xsi:type="xsd:string">John</name>
</ns1:sayHelloTo>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
 
 看起來稍微復(fù)雜了一點,對吧?實際上,它和我們前面編寫的請求類似,只是略微擴展了一些東西。首先,注意SOAP文檔通過一個Envelope(根節(jié)點)、一個Header區(qū)、一個Body區(qū),整潔地組織到一起。Header區(qū)用來封裝那些與方法本身無直接關(guān)系的數(shù)據(jù),提供環(huán)境方面的信息,比如事務(wù)ID和安全信息。Body區(qū)包含面向方法本身的信息。在Listing 2中,我們自己編寫的XML只包含一個Body區(qū)。

  第二,注意Listing 4大量地應(yīng)用了XML名稱空間。SOAP-ENV映射到名稱空間http://schemas./soap/envelope/,xsi映射到http://www./1999/XMLSchema-instance,而xsd映射到http://www./1999/XMLSchema。這三者是所有SOAP文檔都擁有的標(biāo)準(zhǔn)名稱空間。

  最后,在Listing 4中,接口名稱(即Hello)不再象在Listing 2中那樣成為節(jié)點的名字;相反,它引用了一個名稱空間nsl。另外,參數(shù)的類型信息也隨同參數(shù)的值一起發(fā)送給了服務(wù)器。注意信封(Envelope)encodingStyle屬性的值。這個屬性值設(shè)置成了http://schemas./soap/encoding/。這個值告訴服務(wù)器用來編碼(即串行化)方法的編碼方式;服務(wù)器需要這個信息,以便正確地解除方法的串行化。對于服務(wù)器來說,SOAP文檔的自我描述能力是相當(dāng)完善的。

  對于上面的SOAP請求,服務(wù)器的應(yīng)答如下:

  Listing 5

<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas./soap/envelope/"
xmlns:xsi="http://www./1999/XMLSchema-nstance"
xmlns:xsd="http://www./1999/XMLSchema">
<SOAP-ENV:Body>
<ns1:sayHelloToResponse
xmlns:ns1="Hello"
SOAP-ENV:encodingStyle="http://schemas./soap/encoding/">
<return xsi:type="xsd:string">Hello John, How are you doing?</return>
</ns1:sayHelloToResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

  Listing 5與Listing 4的請求消息類似。在上面的代碼中,返回值(即個性化的“Hello”消息)包含在Body區(qū)。SOAP消息文檔的格式非常靈活。例如,編碼方式不固定,而是由客戶程序指定。只要是客戶程序和服務(wù)器都認(rèn)可的編碼方式,可以是任何合法的XML文檔。

  另外,分離調(diào)用環(huán)境信息意味著方法本身并不關(guān)心這類信息。在當(dāng)前的市場上,主流應(yīng)用服務(wù)器都遵從這一理念。早先,我曾經(jīng)指出環(huán)境信息可以包含事務(wù)和安全方面的信息。事實上,環(huán)境可以涵蓋幾乎所有的東西。下面是一個SOAP消息頭的例子,它帶有一些事務(wù)方面的信息:

  Listing 6

<SOAP-ENV:Header>
<t:Transaction xmlns:t="some-URI" SOAP-ENV:mustUnderstand="1">
5
</t:Transaction>
</SOAP-ENV:Header>

  名稱空間t映射到了與特定應(yīng)用有關(guān)的URI。這里的5表示的是該方法從屬于其中的事務(wù)ID。注意SOAP信封mustUnderstand屬性的應(yīng)用。這個屬性被設(shè)置成了1,它表示服務(wù)器要么理解并按照要求處理該事務(wù)請求,要么表示無法處理該請求;這是SOAP規(guī)范所要求的。

  二、錯誤處理

  使用SOAP并不意味著任何時候所有的請求都會獲得成功。許多地方可能會出現(xiàn)差錯。例如,服務(wù)器可能無法訪問某個關(guān)鍵性的資源(比如數(shù)據(jù)庫),因而無法順利地處理請求。
 
 讓我們返回“Hello”實例,為它加上一個假想的約束,即“在星期二向別人說Hello不合法。”因此,星期二的時候,即使發(fā)送給服務(wù)器的請求是合法的,服務(wù)器也會把一個錯誤信息返回給客戶端。應(yīng)答內(nèi)容將如下所示:

  Listing 7

<SOAP-ENV:Envelope xmlns:SOAP-ENV="
http://schemas./soap/envelope/">
<SOAP-ENV:Body>
<SOAP-ENV:Fault>
<faultcode>SOAP-ENV:Server</faultcode>
<faultstring>Server Error</faultstring>
<detail>
<e:myfaultdetails xmlns:e="Hello">
<message>
Sorry, my silly constraint says that I cannot say hello on Tuesday.
</message>
<errorcode>
1001
</errorcode>
</e:myfaultdetails>
</detail>
</SOAP-ENV:Fault>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

  我們來分析一下http://schemas./soap/envelope/名稱空間定義的Fault元素。Fault元素總是Body元素的直接子元素,所有的SOAP服務(wù)器必須始終通過該元素報告所有錯誤情況。Fault元素必須包含faultcode和faultstring元素,不能有例外。faultcode是一個能夠標(biāo)識問題的代碼;客戶程序按照SOAP規(guī)范的要求利用faultcode進行算法處理。SOAP規(guī)范定義了一小組錯誤代碼供用戶使用。另一方面,faultstring是供人類閱讀的錯誤信息。

  Listing 7的代碼還包含了一個detail元素。由于錯誤在處理SOAP消息的Body區(qū)時出現(xiàn),detail元素必須出現(xiàn)。正如你將在本文后面看到的,如果錯誤在處理Header區(qū)時出現(xiàn),detail元素不應(yīng)出現(xiàn)。在Listing 7中,應(yīng)用利用detail元素提供當(dāng)前錯誤更詳細(xì)、更自然的解釋,即星期二不允許說Hello。SOAP還提供另外一個面向具體應(yīng)用的錯誤代碼,即半可選的faultfactor元素,但上面的錯誤信息中沒有顯示這個元素。之所以稱這個元素是半可選的,是因為如果錯誤消息不是由請求最終處理點的服務(wù)器發(fā)送,即由一個中間服務(wù)器發(fā)送,則錯誤消息必須包含該元素。SOAP對faultcode元素不應(yīng)出現(xiàn)的情形沒有作任何規(guī)定。

  在Listing 7中,錯誤起源于方法調(diào)用本身,處理該方法的應(yīng)用導(dǎo)致了這個錯誤?,F(xiàn)在,我們來看一下另一種類型的錯誤,這種錯誤由于服務(wù)器不能處理請求頭信息而導(dǎo)致。舉例來說,假設(shè)所有的Hello消息必須在一個事務(wù)環(huán)境之內(nèi)生成,則請求類似于:

  Listing 8

<SOAP-ENV:Envelope
xmlns:SOAP-ENV="
http://schemas./soap/envelope/"
xmlns:xsi="
http://www./1999/XMLSchema-instance"
xmlns:xsd="http://www./1999/XMLSchema">
<SOAP-ENV:Header>
<t:Transaction xmlns:t="some-URI"
SOAP-ENV:mustUnderstand="1">
5
</t:Transaction>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ns1:sayHelloTo
xmlns:ns1="Hello"
SOAP-ENV:encodingStyle="
http://schemas./soap/encoding/">
<name xsi:type="xsd:string">Tarak</name>
</ns1:sayHelloTo>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
 
 上面消息的Header區(qū)包含一個transaction元素,它指定了方法調(diào)用必須從屬于其中的事務(wù)編號。這里我說“必須”是因為transaction元素使用了mustUnderstand屬性。如前所述,SOAP服務(wù)器要么遵照屬性的指示處理請求,要么聲明不能處理請求。假定SOAP服務(wù)器不能處理,它必須返回一個錯誤信息。這時的應(yīng)答應(yīng)該類似于:

  Listing 9

<SOAP-ENV:Envelope xmlns:SOAP-ENV="
http://schemas./soap/envelope/">
<SOAP-ENV:Body>
<SOAP-ENV:Fault>
<faultcode>SOAP-ENV:MustUnderstand</faultcode>
<faultstring>SOAP Must Understand
Error</faultstring>
</SOAP-ENV:Fault>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

  上面的代碼類似Listing 7顯示的錯誤信息。但應(yīng)該注意的是,detail元素不再出現(xiàn)。正如我在前面指出的:SOAP規(guī)范規(guī)定,如果錯誤在處理Header區(qū)的時候出現(xiàn),則錯誤消息中不應(yīng)包含detail元素。事實上,我們可以根據(jù)detail元素是否出現(xiàn),迅速判定錯誤是在處理Body區(qū)還是在處理Header區(qū)時出現(xiàn)。

  三、SOAP與HTTP

  在第一個例子中,我通過HTTP把定制的XML請求發(fā)送給服務(wù)器,但沒有詳細(xì)介紹這么做涉及到了哪些操作?,F(xiàn)在我們回過頭來看那個問題。怎樣才能把一個SOAP請求(而不是定制的XML)通過HTTP發(fā)送給服務(wù)器?SOAP很自然地遵循了HTTP的請求/應(yīng)答消息模型。這個模型在HTTP請求中提供SOAP請求參數(shù),在HTTP應(yīng)答中提供SOAP應(yīng)答參數(shù)。實際上,SOAP 1.0特別指明HTTP作為它的傳輸協(xié)議。SOAP 1.1略有放松。雖然SOAP 1.1仍舊可以使用HTTP,但它也可以使用其他協(xié)議,比如SMTP。在這個系列的文章中,我只討論通過HTTP使用SOAP的情形。

  讓我們返回Hello示例。如果我們通過HTTP把SOAP請求發(fā)送給服務(wù)器,則代碼應(yīng)該類似于:

  Listing 10

POST http://www.SmartHello.com/HelloApplication HTTP/1.0
Content-Type: text/xml; charset="utf-8"
Content-Length: 587
SOAPAction: "http://www.SmartHello.com/HelloApplication#sayHelloTo"
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="
http://schemas./soap/envelope/"
xmlns:xsi="
http://www./1999/XMLSchema-instance"
xmlns:xsd="http://www./1999/XMLSchema">
<SOAP-ENV:Header>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ns1:sayHelloTo
xmlns:ns1="Hello"
SOAP-ENV:encodingStyle="
http://schemas./soap/encoding/">
<name xsi:type="xsd:string">Tarak</name>
</ns1:sayHelloTo>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
 
Listing 10代表的SOAP請求與Listing 4的請求基本相同,但Listing 10的開頭加入了一些HTTP特有的代碼。第一行代碼表明這是一個遵循HTTP 1.1規(guī)范的POST請求,POST的目標(biāo)是http://www.SmartHello.com/HelloApplication。下一行指示內(nèi)容的類型,在HTTP消息中包含SOAP實體時,內(nèi)容類型必須是text/xml。Content-Length指明了POST請求有效載荷的長度。

  第四行是SOAP特有的,而且它是必不可少的。SOAPAction HTTP請求頭指明了SOAP HTTP請求的目標(biāo),它的值是一個標(biāo)識目標(biāo)的URI。SOAP不對該URI的格式作任何限制,實際上,這個URI甚至不必對應(yīng)某個實際的位置。

  SOAPAction的一個可能的應(yīng)用是,防火墻檢查該請求頭的值,決定是否允許請求通過防火墻。

  一旦服務(wù)器處理完請求,它將向客戶返回一個應(yīng)答。應(yīng)答的內(nèi)容如Listing 11所示(假設(shè)沒有出現(xiàn)錯誤):

  Listing 11

HTTP/1.0 200 OK
Content-Type: text/xml; charset="utf-8"
Content-Length: 615
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="
http://schemas./soap/envelope/"
xmlns:xsi="
http://www./1999/XMLSchema-instance"
xmlns:xsd="http://www./1999/XMLSchema">
<SOAP-ENV:Body>
<ns1:sayHelloToResponse
xmlns:ns1="Hello"
SOAP-ENV:encodingStyle="
http://schemas./soap/encoding/">
<return xsi:type="xsd:string">Hello John, How are
you doing?</return>
</ns1:sayHelloToResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

  這個SOAP應(yīng)答與Listing 5所顯示的一樣,但前面加上了一些HTTP特有的代碼。由于沒有出現(xiàn)錯誤,第一行代碼顯示應(yīng)答狀態(tài)是200。在HTTP協(xié)議中,200應(yīng)答狀態(tài)代碼表示“一切正常”。如果在處理SOAP消息(Header區(qū)或者Body區(qū))的時候出現(xiàn)了任何錯誤,則返回的狀態(tài)代碼將是500。在HTTP中,500狀態(tài)代碼表示“internal server error”。此時,上述SOAP應(yīng)答的第一行代碼將是:

HTTP 500 Internal Server Error

  四、HTTP擴充框架

  許多應(yīng)用對服務(wù)的需求超過了傳統(tǒng)HTTP提供的服務(wù)。其結(jié)果就是,這類應(yīng)用擴充了傳統(tǒng)的HTTP協(xié)議。然而,這種擴充是應(yīng)用本身私有的。HTTP擴充框架試圖確立一個通用的HTTP擴充機制,從而解決這個問題。HTTP擴充框架的擴充之一是增加了一個M-POST方法,其中的M表示Mandatory(必須遵循的,強制的)。如果一個HTTP請求包含至少一個強制的擴充聲明,那么這個請求就稱為強制的請求。引入強制的擴充聲明通過Man或者C-Man頭進行。強制請求的請求方法名字必須帶有“M-”前綴,例如,強制的POST方法稱為M-POST。

  SOAP 1.0要求客戶程序首先發(fā)送一個HTTP POST請求,只有當(dāng)服務(wù)器返回錯誤510時才發(fā)送M-POST請求。SOAP 1.1不再對客戶作這種限制,也就是說,SOAP 1.1允許客戶從發(fā)送任何一種類型的請求開始。下面的請求就是迄今為止我們一直在討論的那個請求,但它現(xiàn)在是M-POST格式:

  Listing 12

M-POST http://www.SmartHello.com/HelloApplication HTTP/1.1
Content-Type: text/xml; charset="utf-8"
Content-Length: 587
Man: "http://schemas./soap/envelope/"; ns=01
01-SOAPAction: "http://www.SmartHello.com/HelloApplication#sayHelloTo"
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="
http://schemas./soap/envelope/"
xmlns:xsi="
http://www./1999/XMLSchema-instance"
xmlns:xsd="http://www./1999/XMLSchema">
<SOAP-ENV:Header>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ns1:sayHelloTo
xmlns:ns1="Hello"
SOAP-ENV:encodingStyle="
http://schemas./soap/encoding/">
<name xsi:type="xsd:string">Tarak</name>
</ns1:sayHelloTo>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
 
對于實際的SOAP消息來說,Listing 12和Listing 10沒有什么不同。但請求頭中有一些不同的地方,例如,現(xiàn)在我們發(fā)出的不是POST請求,而是一個M-POST請求。正如前面所介紹的,象M-POST這樣的強制請求至少有一個強制擴充聲明。這里我們就有一個:Man域描述了一個強制性的端到端擴充聲明,把頭前綴01映射到了名稱空間http://schemas./soap/envelope/。請注意這個前綴關(guān)聯(lián)到SOAPAction域的方式。

  一旦服務(wù)器處理完該請求,它將返回一個應(yīng)答給客戶。應(yīng)答內(nèi)容類如(假設(shè)沒有出現(xiàn)錯誤):

  Listing 13

HTTP/1.0 200 OK
Ext:
Content-Type: text/xml; charset="utf-8"
Content-Length: 615
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="
http://schemas./soap/envelope/"
xmlns:xsi="
http://www./1999/XMLSchema-instance"
xmlns:xsd="http://www./1999/XMLSchema">
<SOAP-ENV:Body>
<ns1:sayHelloToResponse
xmlns:ns1="Hello"
SOAP-ENV:encodingStyle="
http://schemas./soap/encoding/">
<return xsi:type="xsd:string">Hello John, How are
you doing?</return>
</ns1:sayHelloToResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

  同樣地,Listing 13顯示的應(yīng)答類似于對普通POST請求的應(yīng)答(如Listing 11所示),兩者的不同之處在于Ext域。

  在通過HTTP使用SOAP的過程中,我們欣喜地看到,實際的SOAP消息(SOAP信封和它里面的所有內(nèi)容)總是保持不變,就如消息尚未加載HTTP協(xié)議時一樣。根據(jù)這一事實可以推斷出,HTTP不是能夠與SOAP協(xié)作的唯一協(xié)議。例如,SOAP可以方便地和SMTP協(xié)議或者其他定制的私有協(xié)議一起運行。唯一的要求是兩者——客戶端和服務(wù)器端——都理解該協(xié)議。

  五、SOAP的特點:簡單

  至此為止,我們討論了SOAP定義的方方面面,但有許多領(lǐng)域的問題SOAP沒有定義。SOAP規(guī)范的創(chuàng)立者明確地排除了一些關(guān)系密切的領(lǐng)域,比如構(gòu)造對象模型,還有其他許多已經(jīng)確立的標(biāo)準(zhǔn)。

  造成這種現(xiàn)象的原因可以從分析SOAP的目標(biāo)理解。SOAP的目標(biāo)除了擴展性之外,另一個主要的設(shè)計目標(biāo)是簡單。為了保持SOAP簡單,SOAP規(guī)范的創(chuàng)立者決定,只定義那些對于創(chuàng)建一個輕型協(xié)議來說絕對必須的東西。例如,SOAP沒有定義/指定任何有關(guān)分布式垃圾收集、類型安全或版本控制、雙向HTTP通信、消息盒(Message-box)運輸或管道處理、對象激活等方面的內(nèi)容。SOAP的目標(biāo)就是成為一種簡單的協(xié)議——一種在任何操作系統(tǒng)上,單個開發(fā)者能夠用任何語言化數(shù)天時間實現(xiàn)的協(xié)議??紤]到這一點,SOAP在許多方面沒有作出明確定義實際上是一件好事,因為在構(gòu)造分布式系統(tǒng)時,所有現(xiàn)有的技術(shù)都可以方便地采用SOAP,即使不同技術(shù)之間的差異象CORBA和DCOM的差異那樣明顯。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多