簡單對象協議(SOAP)簡介

來源:互聯網
上載者:User
對象 簡易物件存取通訊協定 (SOAP)-CNXML標準教程 <br>
    2000-9-25    作者:何杭軍<br>
<br>
"SOAP是在非集中、分布環境中交換資訊的輕量級協議。它是基於XML的協議,包括三個部分: 封套(envelope)定義了訊息內容和處理的架構、一套編碼規則用來表達應用定義資料類型的執行個體以及表達遠端程序呼叫和響應的協定。"<br>
——SOAP 1.1規範<br>
<br>
第一節 SOAP簡介<br>
<br>
SOAP(Simple Object Access Protocal,簡易物件存取通訊協定 (SOAP)) 技術有助於實現大量異構程式和平台之間的互通性,從而使存在的應用能夠被廣泛的使用者所訪問。SOAP是把成熟的基於HTTP的WEB技術與XML的靈活性和可擴充性組合在了一起。<br>
<br>
SOAP的一個主要目標是使存在的應用能被更廣泛的使用者所使用。為了實現這個目的,沒有任何SOAP API或SOAP 對象請求代理(SOAP ORB),SOAP是假設你將使用儘可能多的存在的技術。幾個主要的CORBA廠商已經承諾在他們的ORB產品中支援SOAP協議。微軟也承諾在將來的COM版本中支援SOAP。DevelopMentor已經開發了參考實現,它使得在任何平台上的任何Java或Perl程式員都可以使用SOAP。而且IBM和Sun也陸續支援了SOAP協議,和MS合作共同開發SOAP規範和應用。目前SOAP已經成為了W3C和IETF的參考標準之一。<br>
<br>
SOAP的指導理念是“它是第一個沒有發明任何新技術的技術”。它採用了已經廣泛使用的兩個協議:HTTP和XML。HTTP用於實現SOAP的RPC風格的傳輸,而XML是它的編碼模式。採用幾行代碼和一個XML解析器,HTTP伺服器(如MS的IIS或Apache)立刻成為了SOAP的ORBs。 因為目前超過一半的Web伺服器採用IIS或Apache, SOAP將會從這兩個產品的廣泛而可靠的使用中擷取利益。這並不意味著所有的SOAP請求必須通過Web伺服器來路由,傳統的Web 服務器只是指派SOAP請求的一種方式。因此Web服務如IIS或Apache對建立SOAP效能的應用是充分的,但決不是必要的。<br>
<br>
SOAP把XML的使用代碼化為請求和響應參數編碼模式,並用HTTP作傳輸。這似乎有點抽象。具體地講,一個SOAP方法可以簡單地看作遵循SOAP編碼規則的HTTP請求和響應。一個SOAP終端則可以看作一個基於HTTP的URL,它用來識別方法調用的目標。象CORBA/IIOP一樣,SOAP不需要具體的對象被綁定到一個給定的終端,而是由具體實現程式來決定怎樣把對象終端標識符映射到伺服器端的對象。<br>
<br>
SOAP請求是一個HTTP POST請求。SOAP請求的content-type必須用text/xml。而且它必須包含一個請求-URI。伺服器怎樣解釋這個請求-URI是與實現相關的,但是許多實現中可能用它來映射到一個類或者一個對象。一個SOAP請求也必須用SOAPMethodName HTTP頭來指明將被調用的方法。簡單地講,SOAPMethodName頭是被URI指定範圍的應用相關的方法名,它是用#符作為分隔字元將方法名與URI分割開:<br>
<br>
SOAPMethodName: urn:strings-com:IString#reverse <br>
<br>
這個頭表明方法名是reverse,範圍URI是urn:strings-com:Istring。 在SOAP中,規定方法名範圍的名域URI在功能上等同於在DCOM 或 IIOP中規定方法名範圍的介面ID。<br>
<br>
簡單的說,一個SOAP請求的HTTP體是一個XML文檔,它包含方法中[in]和[in,out]參數的值。這些值被編碼成為一個顯著的調用元素的子項目,這個調用元素具有SOAPMethodName HTTP頭的方法名和名域URI。調用元素必須出現在標準的SOAP <Envelope>和<Body>元素內(後面會更多討論這兩個元素)。下面是一個最簡單的SOAP方法請求:<br>
<br>
POST /string_server/Object17 HTTP/1.1<br>
Host: 209.110.197.2<br>
Content-Type: text/xml<br>
Content-Length: 152<br>
SOAPMethodName: urn:strings-com:IString#reverse        <br>
<Envelope><br>
<Body><br>
  <m:reverse xmlns:m=''urn:strings-com:IString''><br>
   <theString>Hello, World</theString><br>
  </m:reverse><br>
</Body><br>
</Envelope><br>
SOAPMethodName頭必須與<Body>下的第一個子項目相匹配,否則調用將被拒絕。這允許防火牆管理員在不解析XML的情況下有效地過濾對一個具體方法的調用。<br>
<br>
SOAP響應的格式類似於請求格式。響應體包含方法的[out]和 [in,out]參數,這個方法被編碼為一個顯著的響應元素的子項目。這個元素的名字與請求的調用元素的名字相同,但以Response尾碼來串連。下面是對前面的SOAP請求的SOAP響應:<br>
<br>
200 OK Content-Type: text/xml <br>
Content-Length: 162 <br>
<Envelope> <br>
<Body> <br>
  <m:reverseResponse xmlns:m=''urn:strings-com:IString''><br>
   <result>dlroW ,olleH</result><br>
  </m:reverseResponse><br>
</Body><br>
</Envelope> <br>
這裡響應元素被命名為reverseResponse,它是方法名緊跟Response尾碼。要注意的是這裡是沒有SOAPMethodName HTTP頭的。這個頭只在請求訊息中需要,在響應訊息中並不需要。<br>
<br>
第二節 SOAP體的核心<br>
<br>
SOAP的XML特性是為把資料類型的執行個體序列化成XML的編碼模式。為了達到這個目的,SOAP不要求使用傳統的RPC風格的代理。而是一個SOAP方法調用包含至少兩個資料類型:請求和響應。考慮這下面個COM IDL代碼:<br>
<br>
<br>
[ uuid(DEADF00D-BEAD-BEAD-BEAD-BAABAABAABAA) ]<br>
interface IBank : IUnknown {<br>
HRESULT withdraw([in] long account, <br>
[out] float *newBalance,<br>
[in, out] float *amount<br>
[out, retval] VARIANT_BOOL *overdrawn);<br>
}<br>
在任何RPC協議下,account和amount參數的值將出現在請求訊息中,newBalance、overdrawn參數的值,還有amount參數的更新值將出現在響應訊息中。<br>
<br>
SOAP把方法請求和方法響應提升到了一流狀態。在SOAP中,請求和響應實際上類型的執行個體。為了理解一個方法比如IBank::withdraw怎樣映射一個SOAP請求和響應類型,考慮下列的資料類型:<br>
<br>
struct withdraw {<br>
long account;<br>
float amount;<br>
};<br>
<br>
這時所有的請求參數被打包成為單一的結構類型。同樣下面的資料表示打包所有響應參數到單一的資料類型。 <br>
<br>
struct withdrawResponse {<br>
float newBalance;<br>
float amount;<br>
VARIANT_BOOL overdrawn;<br>
};<br>
再給出下面的簡單的Visual Basic程式,它使用了以前定義的Ibank介面:<br>
<br>
Dim bank as IBank<br>
Dim amount as Single<br>
Dim newBal as Single<br>
Dim overdrawn as Boolean<br>
amount = 100<br>
Set bank = GetObject("soap:http://bofsoap.com/am")<br>
overdrawn = bank.withdraw(3512, amount, newBal)<br>
           <br>
         <br>
這裡,在發送請求訊息之前,參數被序列化成為一個請求對象。同樣被響應訊息接收到的響應對象被還原序列化為參數。一個類似的轉變同樣發生在調用的伺服器端。<br>
<br>
當通過SOAP調用方法時,請求對象和響應對象被序列化成一種已知的格式。每個SOAP體是一個XML文檔,它具有一個顯著的稱為<Envelope>的根項目。標記名<Envelope>由SOAP URI (urn:schemas-xmlsoap-org:soap.v1)來劃定範圍,所有SOAP專用的元素和屬性都是由這個URI來劃定範圍的。SOAP Envelope包含一個可選的<Header>元素,緊跟一個必須的<Body>元素。<Body>元素也有一個顯著的根項目,它或者是一個請求對象或者是一個響應對象。下面是一個IBank::withdraw請求的編碼:<br>
<br>
<soap:Envelope xmlns:soap=''urn:schemas-xmlsoap-org:soap.v1''><br>
<soap:Body><br>
  <IBank:withdraw xmlns:IBank=''urn:uuid:DEADF00D-BEAD-BEAD-BEAD-BAABAABAABAA''><br>
   <account>3512</account><br>
   <amount>100</amount><br>
  </IBank:withdraw><br>
</soap:Body><br>
</soap:Envelope><br>
下列響應訊息被編碼為: <br>
<soap:Envelope xmlns:soap=''urn:schemas-xmlsoap-org:soap.v1''><br>
<soap:Body><br>
  <IBank:withdrawResponse xmlns:IBank=''urn:uuid:DEADF00D-BEAD-BEAD-BEAD-BAABAABAABAA''><br>
   <newBalance>0</newBalance><br>
   <amount>5</amount> <br>
   <overdrawn>true</overdrawn><br>
  </IBank:withdrawResponse><br>
</soap:Body><br>
</soap:Envelope><br>
注意[in, out]參數出現在兩個訊息中。在檢查了請求和響應對象的格式後,你可能已經注意到序列化格式通常是: <br>
<br>
<t:typename xmlns:t=''namespaceuri''><br>
<fieldname1>field1value</fieldname1><br>
<fieldname2>field2value</fieldname2><br>
  ......<br>
</t:typename> <br>
在請求的情況下,類型是隱式的C風格的結構,它由對應方法中的[in]和[in, out]參數組成。對響應來說,類型也是隱式的C風格的結構,它由對應方法中的[out]和[in, out]參數組成。這種每個域對應一個子項目的風格有時被稱為元素正規格式(ENF)。一般情況下,SOAP只用XML特性來傳達描述包含在元素內容中資訊的注釋。<br>
<br>
象DCOM和IIOP一樣,SOAP支援協議頭擴充。SOAP用可選的<Header>元素來傳載被協議擴充所使用的資訊。如果用戶端的SOAP軟體包含要發送頭資訊,原始的請求將可能如圖9所示。在這種情況下命名causality的頭將與請求一起序列化。收到請求後,伺服器端軟體能查看頭的名域URI,並處理它識別出的頭擴充。這個頭擴充被http://comstuff.com URI識別,並期待一個如下的對象:<br>
<br>
struct causality { <br>
UUID id; <br>
}; <br>
在這種情況下的請求,如果頭元素的URI不能被識別,頭元素可以被安全地忽略。<br>
<br>
但你不能安全的忽略所有的SOAP體中的頭元素。如果一個特定的SOAP頭對正確處理訊息是很關鍵的,這個頭元素能被用SOAP屬性mustUnderstand=’true’標記為必須的。這個屬性告訴接收者頭元素必須被識別並被處理以確保正確的使用。為了強迫前面causality頭成為一個必須的頭,訊息將被寫成如下形式:<br>
<br>
<soap:Envelope xmlns:soap=''urn:schemas-xmlsoap-org:soap.v1''><br>
<soap:Header><br>
  <causality soap:mustUnderstand=''true''xmlns="http://comstuff.com"><br>
   <id>362099cc-aa46-bae2-5110-99aac9823bff</id><br>
  </causality> <br>
</soap:Header><br>
</soap:Envelope><br>
SOAP軟體遇到不能識別必須的頭元素情況時,必須拒絕這個訊息並出示一個錯誤。如果伺服器在一個SOAP請求中發現一個不能識別的必須的頭元素,它必須返回一個錯誤響應並且不發送任何調用到目標對象。如果用戶端在一個SOAP請求中發現一個不能識別出的必須的頭元素,它必須向調用者返回一個執行階段錯誤。在COM情況下,這將映射為一個明顯的HRESULT。<br>
<br>
<br>
第三節 SOAP資料類型<br>
<br>
在SOAP訊息中,每個元素可能是一個SOAP結構元素、根項目、存取元素或一個獨立的元素。在SOAP中,soap:Envelope、soap:Body和soap:Header是唯一的組成元素。它們的基本關係由下列XML Schema所描述: <br>
<br>
<schema targetNamespace=''urn:schemas-xmlsoap-org:soap.v1''><br>
<element name=''Envelope''><br>
<type><br>
  <element name=''Header'' type=''Header'' minOccurs=''0'' /><br>
  <element name=''Body'' type=''Body''minOccurs=''1'' /><br>
</type><br>
</element><br>
</schema><br>
在SOAP元素的四種類型中,除了結構元素外都被用作表達類型的執行個體或對一個類型執行個體的引用。<br>
<br>
根項目是顯著的元素,它是soap:Body 或是 soap:Header的直接的子項目。其中soap: Body只有一個根項目,它表達調用、響應或錯誤對象。這個根項目必須是soap:Body的第一個子項目,它的標記名和網域名稱URI必須與HTTP SOAPMethodName頭或在錯誤訊息情況下的soap:Fault相對應。而soap:Header元素有多個根項目,與訊息相聯絡的每個頭擴充對應一個。這些根項目必須是soap:Header的直接子項目,它們的標記名和名域URI表示當前存在擴充資料的類型。<br>
<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存取元素的精確格式當前還在修訂中

相關文章

E-Commerce Solutions

Leverage the same tools powering the Alibaba Ecosystem

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。