SOAP規範(1)

SOAP規範(1)

實話實說

Java (2001-07-27 17:32:52)


 

SOAP:簡單對象訪問協議
(2001-1-1)
摘要
SOAP是用在分散或分佈的環境中交換信息的簡單的協議,它是一個基於XML的協議,包括三個部分:封裝定義了一個描述消息中包含什麼內容以及如何處理它們的框架,編碼規則用於表示應用程序定義的數據類型的實例,另外還有一個表示遠程過程調用和應答的協定。SOAP被設計爲可以與各種其它協議結合使用;但這篇文章僅描述如何將SOAP和HTTP及HTTP擴展框架相結合。

目錄
1. 簡介
1.1 設計目標
1.2 符號協定
1.3 SOAP消息舉例
2. SOAP消息交換模型
3. 與XML的關係
4. SOAP封裝
4.1.1 SOAP encodingStyle屬性
4.1.2 封裝版本模型
4.2 SOAP頭
4.2.1 使用SOAP頭屬性
4.2.2 SOAP actor屬性
4.2.3 SOAP mustUnderstand屬性
4.3 SOAP體
4.3.1 SOAP頭和體的關係
4.4 SOAP 錯誤
4.4.1 SOAP錯誤代碼
5. SOAP編碼
5.1 XML編碼類型規則
5.2 簡單類型
5.2.1 字符串
5.2.2 枚舉
5.2.3 字符數組
5.3 多態 Accessor
5.4 複合類型
5.4.1 複合值和對值的引用
5.4.2 數組
5.4.2.1 PartiallyTransmitted Arrays
5.4.2.2 稀疏數組
5.4.3 一般複合類型
5.5 缺省值
5.6 SOAP root屬性
6. 在HTTP中使用SOAP
6.1 SOAP HTTP請求
6.1.1 HTTP頭中的SOAPAction域
6.2 SOAP HTTP應答
6.3 HTTP擴展框架
6.4 SOAP HTTP舉例
7. 用SOAP表示RPC
7.1 RPC和SOAP體
7.2 RPC和SOAP頭
8. 安全考慮
9. 參考文獻
A. SOAP封裝舉例
A.1 請求編碼舉例
A.2 應答編碼舉例
1. 簡介
SOAP以XML形式提供了一個簡單、輕量的用於在分散或分佈環境中交換結構化和類型化信息的機制。SOAP本身並沒有定義任何應用程序語義,如編程模型或特定語義的實現;實際上它通過提供一個有標準組件的包模型和在模塊中編碼數據的機制,定義了一個簡單的表示應用程序語義的機制。這使SOAP能夠被用於從消息傳遞到RPC的各種系統。

SOAP包括三個部分

SOAP封裝(見第4節)結構定義了一個整體框架用來表示消息中包含什麼內容,誰來處理這些內容以及這些內容是可選的或是必需的。
SOAP編碼規則(見第5節)定義了用以交換應用程序定義的數據類型的實例的一系列機制。
SOAP RPC表示(見第7節)定義了一個用來表示遠程過程調用和應答的協定。
雖然這三個部分都作爲SOAP的一部分一起描述,但它們在功能上是相交的。特別的,封裝和編碼規則是在不同的名域中定義的,這種模塊性的定義方法增加了簡單性。

在SOAP封裝,SOAP編碼規則和SOAP RPC協定之外,這個規範還定義了兩個協議的綁定,描述了在有或沒有HTTP擴展框架[6]的情況下,SOAP消息如何包含在HTTP消息[5]中被傳送。

1.1 設計目標
SOAP的主要設計目標是簡單性和可擴展性,這意味着傳統的消息系統和分佈對象系統的某些性質不是SOAP規範的一部分。這些性質包括:

分佈式碎片收集
成批傳送消息
對象引用(要求分佈式碎片收集)
激活機制(要求對象引用)
1.2 符號約定
這篇文章中的關鍵字 "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", 和"OPTIONAL"的解釋在RFC-2119 [2]中。

這篇文章中用到的名域前綴 "SOAP-ENV" 和 "SOAP-ENC"分別與"http://schemas.xmlsoap.org/soap/envelope/" 和"http://schemas.xmlsoap.org/soap/encoding/"關聯。

整篇文檔中,名域前綴“xsi”被假定爲與URI "http://www.w3.org/1999/XMLSchema-instance“(在XML Schema規範[11]定義)相連。類似的,名域前綴”xsd“被假定爲與URI "http://www.w3.org/1999/XMLSchema"(在 [10]中定義)相連。名域前綴”tns“用來表示任意名域。所有其它的名域前綴都只是例子。

名域URI的基本形式”some-URI“表示某些依賴於應用程序或上下文的URI[4]。

這個規範用擴展BNF(在RFC-2616[5] 描述)描述某些結構。

1.3 SOAP消息舉例
在這個例子中,GetLastTradePrice SOAP 請求被髮往 StockQuote服務。這個請求攜帶一個字符串參數和ticker符號,在SOAP應答中返回一個浮點數。XML名域用來區分SOAP標誌符和應用程序特定的標誌符。這個例子說明了在第6節中定義的HTTP綁定。如果SOAP中管理XML負載的規則完全獨立於HTTP是沒有意義的,因爲事實上該負載是由HTTP攜帶的。

在Appendix A中有更多的例子。

例1 在HTTP請求中嵌入SOAP消息

POST /StockQuote HTTP/1.1
Host:
www.stockquoteserver.com
Content-Type: text/xml;
charset="utf-8"
Content-Length: nnnn
SOAPAction:
"Some-URI"

<SOAP-ENV:Envelope
  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
  SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
   <SOAP-ENV:Body>
       <m:GetLastTradePrice xmlns:m="Some-URI">
           <symbol>DIS</symbol>
       </m:GetLastTradePrice>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

下面是一條應答消息,包括HTTP消息,SOAP消息是其具體內容:

例2 在HTTP應答中嵌入SOAP消息

HTTP/1.1 200 OK
Content-Type: text/xml;
charset="utf-8"
Content-Length:
nnnn

<SOAP-ENV:Envelope
  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
  SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
   <SOAP-ENV:Body>
       <m:GetLastTradePriceResponse xmlns:m="Some-URI">
           <Price>34.5</Price>
       </m:GetLastTradePriceResponse>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

2. SOAP消息交換模型
SOAP消息從發送方到接收方是單向傳送,但正如上面顯示的,SOAP消息經常以請求/應答的方式實現。

SOAP實現可以通過開發特定網絡系統的特性來優化。例如,HTTP綁定(見第6節)使SOAP應答消息以HTTP應答的方式傳輸,並使用同一個連接返回請求。

不管SOAP被綁定到哪個協議,SOAP消息採用所謂的”消息路徑“發送,這使在終節點之外的中間節點可以處理消息。

一個接收SOAP消息的SOAP應用程序必須按順序執行以下的動作來處理消息:

識別應用程序想要的SOAP消息的所有部分 (見4.2.2節)
檢驗應用程序是否支持第一步中識別的消息中所有必需部分並處理它。如果不支持,則丟棄消息(見4.4節)。在不影響處理結果的情況下,處理器可能忽略第一步中識別出的可選部分。
如果這個SOAP應用程序不是這個消息的最終目的地,則在轉發消息之前刪除第一步中識別出來的所有部分。
爲了正確處理一條消息或者消息的一部分,SOAP處理器需要理解:所用的交換方式(單向,請求/應答,多路發送等等),這種方式下接收者的任務,RPC機制(如果有的話)的使用(如第7節中所述),數據的表現方法或編碼,還有其它必需的語義。

儘管屬性比如SOAP encodingstyle(見4.1.1節)可以用於描述一個消息的某些方面,但這個規範並不強制所有的接收方也必須有同樣的屬性並取同樣的屬性值。舉個例子,某一特定的應用可能知道一個元素表示一條遵循第7節約定的RPC請求,但是另外一些應用可能認爲指向該元素的所有消息都用單向傳輸,而不是類似第7節的請求應答模式。
(譯者注:交互雙方的SOAP消息並不一定要遵循同樣的格式設定,而只需要以一種雙方可理解的格式交換信息就可以了)

3. 與XML的關係
所有的SOAP消息都使用XML形式編碼(更多有關XML的信息請見[7])

一個SOAP應用程序產生的消息中,所有由SOAP定義的元素和屬性中必須包括正確的名域。SOAP應用程序必須能夠處理它接收到的消息中的SOAP名域(見4.4節),並且它可以處理沒有SOAP名域的SOAP消息,就象它們有正確的名域一樣。

SOAP定義了兩個名域(更多有關XML名域的信息請見[8])

SOAP封裝的名域標誌符是"http://schemas.xmlsoap.org/soap/envelope/"
SOAP的編碼規則的名域標誌符是"http://schemas.xmlsoap.org/soap/encoding/"
SOAP消息中不能包含文檔類型聲明,也不能包括消息處理指令。[7]

SOAP使用"ID"類型"id"屬性來指定一個元素的唯一的標誌符,同時該屬性是局部的和無需校驗的。SOAP使用"uri-reference"類型的"href"屬性指定對這個值的引用,同時該屬性是局部的和無需校驗的。這樣就遵從了XML規範[7],XML Schema規範[11]和XML連接語言規範[9]的風格。

除了SOAP mustUnderstand 屬性(見4.2.3節)和SOAP actor屬性(見4.2.2節)之外,一般允許屬性和它們的值出現在XML文檔實例或Schema中(兩者效果相同)。也就是說,在DTD或Schema中聲明一個缺省值或固定值和在XML文檔實例中設置它的值在語義上相同。

4. SOAP封裝
SOAP消息是一個XML文檔,包括一個必需的SOAP封裝,一個可選的SOAP頭和一個必需的SOAP體。在這篇規範剩餘部分中,提到SOAP消息時就是指這個XML文檔。這一節中定義的元素和屬性的名域標誌符爲:"http://schemas.xmlsoap.org/soap/envelope/" 。一個SOAP消息包括以下部分:

在表示這個消息的XML文檔中,封裝是頂層元素。
應用SOAP交換信息的各方是分散的且沒有預先協定,SOAP頭提供了向SOAP消息中添加關於這條SOAP消息的某些要素(feature)的機制。SOAP定義了少量的屬性用來表明這項要素(feature)是否可選以及由誰來處理。(見4.2節)
SOAP體是包含消息的最終接收者想要的信息的容器(見4.3節)。SOAP爲SOAP體定義了一個Fault元素用來報告錯誤信息。
語法規則如下所示:

封裝
元素名是 "Envelope"
在SOAP消息中必須出現。
可以包含名域聲明和附加屬性。如果包含附加屬性,這些屬性必須限定名域。類似的,"Envelope"可以包含附加子元素,這些也必須限定名域且跟在SOAP體元素之後。
SOAP頭 (見4.2節)
元素名是"Header"
在SOAP消息中可能出現。如果出現的話,必須是SOAP 封裝元素的第一個直接子元素。
SOAP頭可以包含多個條目,每個都是SOAP頭元素的直接子元素。所有SOAP頭的直接子元素都必須限定名域。
SOAP體 (見4.3節)
元素名是"Body"
在SOAP消息中必須出現且必須是SOAP封裝元素的直接子元素。它必須直接跟在SOAP頭元素(如果有的話)之後。否則它必須是SOAP封裝元素的第一個直接子元素。
SOAP體可以包括多個條目,每個條目必須是SOAP體元素的直接子元素。SOAP體元素的直接子元素可以限定名域。SOAP定義了SOAP Fault元素來表示錯誤信息。(見4.4節).
4.1.1 SOAP encodingStyle 屬性
EncodingStyle全局屬性用來表示SOAP消息的序列化規則。這個屬性可以在任何元素中出現,作用範圍與名域聲明的作用範圍很相似,爲這個元素的內容和它的所有沒有重載此屬性的子元素。SOAP消息沒有定義缺省編碼。

屬性值是一個或多個URI的順序列表,每個URI確定了一種或多種序列化規則,用來不同程度反序列化SOAP消息,舉例如下:

"http://schemas.xmlsoap.org/soap/encoding/"
"http://my.host/encoding/restricted http://my.host/encoding/"
""

第5節中定義的序列化規則由URI"http://schemas.xmlsoap.org/soap/encoding/" 確定。使用這個特定序列化規則的消息應該用encodingStyle屬性說明這一點。另外,所有以"http://schemas.xmlsoap.org/soap/encoding/"開頭的URI中的序列化規則與第5節中定義的SOAP編碼規則相一致。

一個零長度的URI("")明確顯示所含元素沒有任何編碼形式。這可以用來取消上一級元素的所有編碼聲明。

4.1.2 封裝版本模型
SOAP沒有定義常規的基於主版本號和輔版本號的版本形式。SOAP消息必須有一個封裝元素與名域"http://schemas.xmlsoap.org/soap/envelope/"關聯。如果SOAP應用程序接收到的SOAP消息中的SOAP封裝元素與其他的名域關聯,則視爲版本錯誤,應用程序必須丟棄這個消息。如果消息是通過HTTP之類的請求/應答協議收到的,應用程序必須回答一個SOAP VersionMismatch 錯誤信息(見4.4節)。

4.2 SOAP頭
SOAP爲相互通信的團體之間提供了一種很靈活的機制:在無須預先協定的情況下,以分散但標準的方式擴展消息。可以在SOAP頭中添加條目實現這種擴展,典型的例子有認證,事務管理,支付等等。

頭元素編碼爲SOAP封裝元素的第一個直接子元素。頭元素的所有直接子元素稱作條目。

條目的編碼規則如下:

一個條目有它的完整的元素名(包括名域URI和局部名)確定。SOAP頭的直接子元素必須有名域限制。
SOAP encodingStyle屬性可以用來指示條目所用的編碼形式(見4.1.1節)
SOAP mustUnderstand屬性(見4.2.3節)和SOAP actor屬性(見4.2.2節)可以用來指示如何處理這個條目以及由誰來處理。(見4.2.1節)
4.2.1 使用頭屬性
這一節中定義的SOAP頭屬性確定了SOAP消息的接收者應該怎樣按第2節中所述的方式處理消息。產生SOAP消息的SOAP應用程序,應該僅僅在SOAP頭元素的直接子元素中使用這些SOAP頭屬性。SOAP消息的接收者必須忽略所有不在SOAP頭元素的直接子元素中SOAP頭屬性。

下面的例子是一個SOAP頭,包括一個元素標誌符"Transaction","mustUnderstand"取值爲"1"和數值5。這應該以如下方式編碼:

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

4.2.2 SOAP actor屬性
一個SOAP消息從始節點到終節點的過程中,可能沿着消息路徑經過一系列SOAP中間節點。一個SOAP中間節點是一個可以接收轉發SOAP消息的應用程序。中間節點和終節點由URI區分。

可能SOAP消息的終節點並不需要所有部分,而在消息路徑上的一個和幾個中間節點可能需要這些內容。頭元素的接收者扮演的角色類似於一個過濾器,防止這些只發給本接受者的消息部分擴散到其它節點。即一個頭元素的接收者必須不轉發這些頭元素到SOAP消息路徑上的下一個應用程序。同樣的,接收者可能插入一個相似的頭元素。

SOAP actor全局屬性可以用於指示頭元素的接收者。SOAP actor屬性的值是一個URI。URI "http://schemas.xmlsoap.org/soap/actor/next"指出了第一個處理這個消息的SOAP應用程序需要這個頭元素。這類似於HTTP頭中用Connection域表示hop-by-hop範圍模型。

省略SOAP actor屬性表示接收者是SOAP消息的終節點。

如果這個屬性要生效,它必須出現在SOAP消息實例中。(見第3節和4.2.1節)

4.2.3 SOAP mustUnderstand屬性
SOAP mustUnderstand全局屬性用來指示接受者在處理消息時這個條目是否必須處理。條目的接收者由SOAP actor屬性定義(見4.2.2節)。MustUnderstand屬性的值是"1" 或 "0"。缺少SOAP mustUnderstand屬性在語義上等同於它的值爲"0"。

如果一個頭元素的SOAP mustUnderstand屬性的值是"1",那麼條目的接受者必須或者遵守語義(如以元素的全名傳送)並按照語義正確的處理,或者放棄處理消息(見4.4節)。

SOAP mustUnderstand 屬性考慮了消息演變的準確性(robust evolution)。必須假定包含SOAP mustUnderstand屬性且值爲"1"的元素以某種方式修改了它們的父元素或同層元素的語義。以這種方式連接元素確保了語義上的變化不會被那些不能完全理解它的接收者忽略。

如果這個屬性要生效,它必須出現在SOAP消息實例中。(見第3節和4.2.1節)

4.3 SOAP體
SOAP體元素提供了一個簡單的機制,使消息的最終接收者能交換必要的信息。使用體元素的典型情況包括配置RPC請求和錯誤報告。

體元素編碼爲SOAP封裝元素的直接子元素。如果已經有一個頭元素,那麼體元素必須緊跟在頭元素之後,否則它必須是SOAP封裝元素的第一個直接子元素。

體元素的所有直接子元素稱作體條目,每個體條目在SOAP體元素中編碼爲一個獨立的元素。

條目的編碼規則如下:

一個條目由它的元素全名(包括名域URI和局部名)確定。SOAP體元素的直接子元素可能是名域限制的。
SOAP encodingStyle屬性可能用來指示條目(見4.1.1節)的編碼方式。
SOAP定義了一個Fault條目用來報告錯誤信息。(見4.4節)

4.3.1 SOAP頭和體的關係
雖然頭和體定義爲獨立的元素,它們實際上是有關係的。體條目和頭條目的關係如下:體條目在語義上等同於actor屬性爲缺省值且mustUnderstand屬性值爲"1"的頭條目。不使用actor屬性則表示缺省的actor。(見4.2.2節)

4.4 SOAP錯誤
SOAP錯誤元素用於在SOAP消息中攜帶錯誤和(或)狀態信息。如果有SOAP錯誤元素,它必須以以體條目的方式出現,並且在一個體元素中最多出現一次。

SOAP錯誤元素定義了以下四個子元素:

faultcode
faultcode元素給軟件提供了一個識別此錯誤的算法機制。SOAP錯誤元素必須有faultcode子元素,並且它的值必須是一個合法的名(在[8]節定義)。SOAP定義一些SOAP faultcode描述基本的SOAP錯誤(見4.4.1節)。
faultstring
faultstring元素提供了一個錯誤解釋,而不是爲了軟件處理。faultstring元素類似於HTTP中定義(見[5],第6.1節)的'Reason-Phrase'。SOAP錯誤元素必須有faultstring子元素,並且它應該提供一些錯誤本質的解釋信息。
faultactor
faultactor元素提供了在消息路徑上是誰導致了錯誤發生的信息(見第2節)。它類似於SOAP actor屬性(見4.2.2節),只是SOAP actor指的是頭條目的目的地,faultactor指的是錯誤的來源。faultactor屬性的值是用來區分錯誤來源的URI。不是SOAP消息的最終目的地的應用程序必須在SOAP Fault元素中包含faultactor元素。消息的最終目的地可以使用faultactor元素明確的指示是它產生了這個錯誤(參見下面的detail元素)
detail
detail元素用來攜帶與Body元素有關的應用程序所要的錯誤信息。如果Body元素的內容不能被成功的處理,則必須包含detail子元素。它不能用來攜帶屬於頭條目的錯誤信息。頭條目的詳細出錯信息必須由頭條目攜帶。
Fault元素中沒有detail元素表示這個錯誤與Body元素的處理無關。在有錯誤的時候,這可以用來區分Body元素有沒有被正確的處理。

detail元素的所有直接子元素稱作detail條目,並且每個detail條目在detail元素中編碼爲獨立的元素。

detail條目的編碼規則如下(參見例10):
一個detail條目由它的元素全名(包括名域URI和局部名)確定。SOAP體元素的直接子元素可能是名域限制的。
SOAP encodingStyle屬性可能用來指示detail條目(見4.1.1節)的編碼方式。
也可以有其它的Fault子元素,只要它們是名域限制的。

 


i社區原文:SOAP規範(1)
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章