閱讀918 返回首頁    go 技術社區[雲棲]


SOAP-Simple Object Access Protocol(簡單對象訪問協議)

SOAP是Simple Object Access Protocol(簡單對象傳輸協議)的縮寫。SOAP消息是基於XML格式進行傳輸的,流行的web service就是使用SOAP進行客戶端和服務器之間的通信的。在這篇文章中我將介紹基礎的SOAP格式(1.2版),包括:

  • SOAP XML格式
  • SOAP 消息樣式
  • SOAP MEP(Message Exchange Patterns 消息交換模式 )
  • SOAP 消息路由選擇
  • SOAP 通過HTTP傳輸

SOAP 消息格式

下麵是一個簡單的SOAP消息:

<?xml version="1.0"?>
<soap:Envelope xmlns:soap="https://www.w3.org/2001/12/soap-envelope" >

<soap:Header>
</soap:Header>

<soap:Body>

  <-- Fault element is optional,
      used only if a fault occurs in web service.
  -->
  <soap:Fault>
  </soap:Fault>

</soap:Body>

</soap:Envelope>

正如你看到的,一條SOAP消息包括一個envelope元素,在envelope元素中可以嵌套了一個Header元素和一個Body元素。如果在這個web service 處理消息過程中產生了一個錯誤,在Body元素中可以嵌套一個Fault元素。在接下來的SOAP的文章中將會依次介紹SOAP消息中的這些元素。

SOAP請求和響應都使用Envelope命名空間

在早期的SOAP規範中從客戶端發送請求到服務器和從服務器發送響應到客戶端都使用相同的SOAP數據格式,因此SOAP請求和響應消息格式是一致的。這不同於HTTP協議中請求和響應報文采用了不同的數據格式。

SOAP Envelope元素

SOAP的Envelope元素是SOAP消息的根元素,在Envelope元素內可以嵌套到一個Header元素(可選的)和一個Body元素。
下邊是一個關於SOAP Envelope元素的例子(內容中粗體內容為Envelope元素)

<?xml version="1.0"?>
<env:Envelope  xmlns:env="https://www.w3.org/2002/06/soap-envelope" >

<env:Header>
</env:Header>

<env:Body>
</env:Body>

</env:Envelope>

注意到命名空間envEnvelope元素中有如下定義

xmlns:env="https://www.w3.org/2002/06/soap-envelope"

命名空間的定義必須總是出現在SOAP Envelope元素內,前綴(env)可以視自己的喜好定義。

SOAP的Header元素

內容列表

  • Header 子元素屬性
  • mustUnderstand
  • encodingStyle
  • role
  • relay

SOAP Header元素是Envelope元素的一個可選的子元素,在Header元素內你可以放置SOAP信息中Body部分一外的內容,其中的內容可以完全由你來指定,例如,它可以是關於這條SOAP請求處理的最大時間,或者是其它沒有在SOAP消息中直接被指明的內容。

下邊是一個關於SOAP Header元素的例子(內容中粗體內容為Header元素)

<?xml version="1.0"?>
<env:Envelope  xmlns:env="https://www.w3.org/2001/12/soap-envelope" >

  <env:Header>
    <jj:maxTime value="10000" xmlns:jj="https://jenkov.com"/>
  </env:Header>

  <env:Body>
  </env:Body>

</env:Envelope>

上邊的例子展示了僅有一個“SOAP 頭信息塊”的Header元素。
更多的關於Header元素的使用類似於Envelope元素的XML命名空間的內容請參考SOAP規範。

Header子元素屬性

Header元素的子元素有以下幾個標準屬性:

  • mustUndersstand
  • encodingStyle
  • role
  • relay

接下來的部分將詳細介紹這幾個元素屬性。

mustUnderstand
mustUnderstand屬性意味著每個處理SOAP的節點必須能夠理解(處理)所給出的Header區域。這裏所說的“節點”不一定是最終接收SOAP消息的節點,這條SOAP消息在到達最終接收/處理消息的節點(web service)之前可能經過了中間某些節點。
假如中間的一個節點不能理解含有mustUnderstand屬性的header區域中的內容,那麼必須返回SOAP錯誤信息。

錯誤信息例子如下:

<env:Header>
  <jj:maxTime value="10000" xmlns:jj="https://jenkov.com"
               mustUnderstand="true"
    />
</env:Header>

encodingStyle
encodingStyle屬性內容省略。

role

某個節點在處理/轉發SOAP消息過程中都扮演者一個或多個SOAP角色,Header區域(元素)能夠將信息發送給消息路徑中的特定的角色,換句話說,如果Header區域中指定了”ultimateReceiver”角色,那麼消息路徑中“ultimateReceiver”角色必須處理Header區域,消息路徑中的其它節點將不對Header區域中的內容進行處理。
SOAP角色詳細解釋見“SOAP 角色”
下邊是一個使用role屬性的例子:

<env:Header>
  <jj:maxTime value="10000" xmlns:jj="https://jenkov.com"
    role="https://www.w3.org/2003/05/soap-envelope/role/ultimateReceiver"
    />
</env:Header>

在這個例子中header元素<maxTime …>僅指定為該SOAP消息的最終接收者處理,消息路徑的中間節點將忽略header元素中的內容。

relay

relay屬性決定了如果header區域沒有被處理是否可以被轉發,換句話說,如果消息路徑中的中間節點沒有處理Header元素中的內容,在轉發SOAP消息的過程中需要根據relay屬性來判斷header元素是否可以被轉發?
relay屬性隻有兩個合法的值:

  1. true
  2. false

如果relay屬性設置為’true’那麼沒有處理的Header元素可以被轉發。
如果relay屬性設置為’false’那麼沒有處理的Header元素不可以被轉發。

缺省relay條件情況下等同於relay屬性設置為’false’。
下邊是一個使用relay屬性的例子:

<env:Header>
  <jj:maxRelayTime value="10000" xmlns:jj="https://jenkov.com"
       role="https://www.w3.org/2003/05/soap-envelope/role/next"
       relay="true"
    />
</env:Header>

在這個例子中Header元素<maxRelayTime …>必須在節點間進行轉發,就算已經被處理過了,換句話說,SOAP消息在消息路徑中轉發過程中Header元素不應該被省去。正如你所看到的role屬性被設置為”next”,這意味著所有消息路徑中的節點都需要處理Header元素。

SOAP Body元素

SOAP Body元素是客戶端和web serveice服務器端處理的SOAP消息中的最主要的部分,SOAP消息中Header元素是可選的但是Body元素是必須要有的元素,SOAP消息中必須包含Body元素。

下邊是一個關於SOAP Header元素的例子(內容中粗體內容為Header元素)

<?xml version="1.0"?>
<env:Envelope  xmlns:env="https://www.w3.org/2001/12/soap-envelope" >

  <env:Header>
    <jj:maxTime value="10000" xmlns:jj="https://jenkov.com"/>
  </env:**Header**>

  <env:Body>
  </env:Body>

</env:Envelope>

上邊的例子展示了僅有一個“SOAP 頭信息塊”的Header元素。
更多的關於Header元素的使用類似於Envelope元素的XML命名空間的內容請參考SOAP規範。

Header元素的子元素的屬性

Header元素的子元素有以下幾個標準屬性:

  • mustUndersstand
  • encodingStyle
  • role
  • relay

每一個元素將會在接下來進行詳細的介紹。

mustUnderstand
mustUnderstand屬性意味著每個處理SOAP的節點必須能夠理解(處理)所給出的Header區域。這裏所說的“節點”不一定是最終接收SOAP消息的節點,這條SOAP消息在到達最終接收/處理消息的節點(web service)之前可能已經經過了消息路徑中的某些節點。
假如中間的一個節點不能理解含有mustUnderstand屬性的header區域中的內容,那麼必須返回SOAP錯誤信息。
錯誤信息例子如下:

<env:Header>
  <jj:maxTime value="10000" xmlns:jj="https://jenkov.com"
               mustUnderstand="true"
    />
</env:Header>

encodingStyle
encodingStyle屬性內容省略

role

某個節點在處理/轉發SOAP消息過程中都扮演者一個或多個SOAP角色,Header區域(元素)能夠將信息發送給消息路徑中的特定的角色,換句話說,如果Header區域中指定了”ultimateReceiver”角色,Name隻有消息路徑中“ultimateReceiver”角色必須處理Header區域,消息路徑中的其它節點將不對Header區域中的內容進行處理。
SOAP角色詳細解釋見“SOAP 角色”
下邊是一個使用role屬性的例子:

<env:Header>
  <jj:maxTime value="10000" xmlns:jj="https://jenkov.com"
    role="https://www.w3.org/2003/05/soap-envelope/role/ultimateReceiver"
    />
</env:Header>

在這個例子中header元素<maxTime …>僅指定為該SOAP消息的最終接收者處理,消息路徑的中間節點將忽略header元素中的內容。

relay

relay屬性決定了如果header區域沒有被處理是否可以被轉發,換句話說,如果消息路徑中的中間節點沒有處理Header元素中的內容在轉發SOAP消息的過程中需要根據relay屬性來判斷header元素是可以被轉發?
relay屬性隻有兩個合法的值:

  1. true
  2. false

如果relay屬性設置為’true’那麼沒有處理的Header元素可以被轉發。
如果relay屬性設置為’false’那麼沒有處理的Header元素不可以被轉發。

缺省relay條件情況下等同於relay屬性設置為’false’。
下邊是一個使用relay屬性的例子:

<env:Header>
  <jj:maxRelayTime value="10000" xmlns:jj="https://jenkov.com"
       role="https://www.w3.org/2003/05/soap-envelope/role/next"
       relay="true"
    />
</env:Header>

在這個例子中Header元素<maxRelayTime …>必須在節點間進行轉發,就算已經被處理過了,換句話說,Header元素不應該被省去。正如你所看到的role屬性被設置為”next”,這意味著所有消息路徑中的節點都需要處理Header元素。

SOAP Body元素

SOAP Body元素是客戶端和web serveice服務器端處理的SOAP消息中的最主要的部分,Header元素是可選的但是Body元素是強製的,SOAP消息中必須包含Body元素。

下邊是一個關於SOAP Body元素的例子(內容中粗體內容為Body元素)

<?xml version="1.0"?>
<env:Envelope  xmlns:env="https://www.w3.org/2001/12/soap-envelope" >

<env:Header>
</env:Header>

<env:Body>
</env:Body>

</env:Envelope>

SOAP消息的Body部分可以包含幾乎所有的你想放置的格式正確的XML數據,然而你不能在Body元素內直接放置文本內容,文本內容應該放置在Body元素的子元素內。

推薦Body元素的子元素使用符合規範的命名空間。

這裏有兩個關於Body元素的例子。第一個例子中Body元素中包含了4個元素,第二個例子這4個元素嵌套在了<service>元素內。

    <?xml version="1.0"?>
    <env:Envelope  xmlns:env="https://www.w3.org/2001/12/soap-envelope" >

      <env:Body>

        <jj:operation name="setName"
            xmlns:jj="https://jenkov.com/operation" />

        <jj:param name="userId" value="123456"
            xmlns:jj="https://jenkov.com/params" />

        <jj:param name="firstName" value="Jakob"
            xmlns:jj="https://jenkov.com/params" />

        <jj:param name="lastName"  value="Jenkov"
            xmlns:jj="https://jenkov.com/params" />

      </env:Body>

    </env:Envelope>

<?xml version="1.0"?>
<env:Envelope  xmlns:env="https://www.w3.org/2001/12/soap-envelope" >

    <env:Body>

      <jj:service name="userService"
          xmlns:jj="https://jenkov.com/service" >

          <jj:operation name="setName" />

          <jj:param name="userId" value="123456" />

          <jj:param name="firstName" value="Jakob" />

          <jj:param name="lastName"  value="Jenkov" />

      </jj:service name="userService"

    </env:Body>

</env:Envelope>

SOAP Fault元素

內容列表

  • SOAP Fault元素結構
    • code
  • Reason
  • Node
  • Role
  • Detail

如果消息路徑中的節點在處理SOAP消息的過程中產生了錯誤,Fault元素出現在從web service(或中間節點)返回的SOAP消息中的Body元素中。

下邊是一個關於SOAP Fault元素的例子(內容中粗體內容為Fault元素)

<?xml version="1.0"?>
<env:Envelope  xmlns:env="https://www.w3.org/2001/12/soap-envelope" >
    <env:Body>
        <env:Fault>

          <env:Code>
            <env:Value>env:Sender</env:Value>
          </env:Code>

          <env:Reason>
            <env:Text xml:lang="en-US">Processing error</env:Text>
            <env:Text xml:lang="da">Processerings-fejl</env:Text>
          </env:Reason>

        </env:Fault>
    </env:Body>
</env:Envelope>

SOAP Fault元素結構

SOAP Fault元素有如下的結構:

<env:Fault>

  <env:Code>
    <env:Value>env:Sender</env:Value>
    <env:Subcode>
        <env:Value>env:Sender</env:Value>
        <env:Subcode> <-- recursive Subcode's possible -->
        </env:Subcode>
    </env:Subcode>
  </env:Code>

  <env:Reason>
   <env:Text xml:lang="en-US">Error in Input Data</env:Text>
   <env:Text xml:lang="da">Fejl i input data</env:Text>
  </env:Reason>

  <env:Node>https://jenkov.com/theNodeThatFailed</env:Node>

  <env:Role>
    https://www.w3.org/2003/05/soap-envelope/role/ultimateReceiver
  </env:Role>

  <env:Detail
    <jj:maxRelayTime
        xmlns:jj="https://jenkov.com" >10000</jj:MaxRelayTime>
  </env:Detail>

</env:Fault>

Code元素和Reasong元素是必須要有的,NodeRoleDetail元素是可選的

Code

Code元素是必須要有的,在Code元素內可以嵌套Value元素,如果你需要分解錯誤碼還可以添加可選的SubCode子元素。

Value子元素隻能包含以下列表中的值,這些值必須添加命名空間信息,這就意味著如果你在SOAP消息中添加了Envelope元素的命名空間信息映射前綴為”env”,你也需要為下邊列表中的值添加前綴”env”,例如:”env:Sender”。

Value Describe
VersionMismath 消息路徑中的節點發現在SOAP消息中的根節點不是有效是Envelope元素將會報告這個錯誤

MustUnderstand 消息路徑中的節點不能理解Header元素的某一個含有mustUnderstand屬性的子元素,這樣的一個目標節點將會報
告這個錯誤,換句話說消息路徑中的此節點不能理解此Header元素假設他能理解的元素的意思。

DataEncodingUnknow 消息路徑中的節點不能理解假定被理解的元素的編碼(由encodingStyle屬性被指定)

Sender SOAP消息格式錯誤、不包含有效的數據或者缺少數據等,換句話說,消息的發送方發送了錯誤的SOAP消息。

Receiver SOAP消息的接收者不能處理此消息。責任完全在消息的接收方,例如:web service需要數據庫支持但是數據庫
宕機了。

更多信息關於 SOAP Fault在SOAP spec – fault codes section.https://www.w3.org/TR/2007/REC-soap12-part1-20070427/

你可以自己定義Subcode元素包含任何值到Value子元素中,Subcode元素可以循環嵌套Subcode元素

下麵是Code元素的例子

<env:Code>

  <env:Value>env:Sender</env:Value>

  <env:Subcode>
    <env:Value>env:Sender</env:Value>
    <env:Subcode> <-- recursive Subcode's possible -->
    </env:Subcode>
  </env:Subcode>

</env:Code>

Reason

Reason元素是強製要有的,Reason元素可以包含一個或者多個Text元素作為子元素,Text元素包含任何語言格式的錯誤的原因,Text元素的lang屬性可以是ISO規定的語言代碼值。

下麵是包含相同錯誤信息的英語和丹麥語的例子

<env:Reason xmlns:xml="https://www.w3.org/XML/1998/namespace" >
 <env:Text >Error in Input Data</env:Text>
 <env:Text xml:lang="da">Fejl i input data</env:Text>
</env:Reason>

Node

Node元素是可選的,他應該包含當前發生錯誤的URI標識符,URI標識符可以自定義。

下麵是例子:

<env:Node>https://jenkov.com/theNodeThatFailed</env:Node>

Role

Role元素是可選的,他應該包含消息路徑中產生錯誤的節點的角色,“角色”詳細信息見“SOAP 角色”相關內容。

下麵是例子

<env:Role>
    https://www.w3.org/2003/05/soap-envelope/role/ultimateReceiver
</env:Role>

Detail

Detail元素是可選的,他應該包含描述錯誤產生詳細信息的子元素,不能直接將文本信息放置在Detail元素內,所有的文本信息需要放置在Detail元素的子元素內。
所有的Detail元素的子元素應該使用合法的命名空間,表明這些子元素屬於自己的命名空間。

下麵是例子:

<env:Detail
    <jj:maxRelayTime
        xmlns:jj="https://jenkov.com" >10000</jj:MaxRelayTime>
  </env:Detail>

SOAP Roles元素

內容

  • 預定義SOAP Roles
  • 用戶SOAP Roles
  • Header元素中的SOAP Roles
  • Fault元素中的SOAP Roles

消息路徑中處理/轉發SOAP消息的節點被認為是扮演著一個或多個SOAP角色,這裏有一個示意圖展示了包含3個節點的SOAP消息處理過程:

Alt text
處理過程中節點角色.

第一個節點是消息的發送者,這個節點的角色在SOAP規範中沒有被提及。

第二個節點是進行SOAP消息轉發的中間節點,中間的節點也可以改變SOAP消息的內容,例如:它們可以添加、修改或者是刪除Header元素或者改變Body元素中的內容,中間節點被定義為扮演者”next”角色。

圖中SOAP消息中的最後一個節點是”ultimateReceiver”,最終的接收節點是最終的SOAP消息的處理者,是”web service”的另一個說法,可以理解為”web service”實際上包含了整個處理SOAP消息的所有節點不僅僅是最終的接收者。

預定義的SOAP角色

SOAP規範預定義的三個角色:

SOAP Roles
角色名稱 角色URI
next https://www.w3.org/2003/05/soap-envelope/role/next
none https://www.w3.org/2003/05/soap-envelope/role/none
ultimateReceiver https://www.w3.org/2003/05/soap-envelope/role/ultimateReceiver

所有的中間節點和最終接收節點被假定為next角色

none角色比較特殊,不包含任何節點,到達該角色的SOAP消息Header區域在該節點的左側沒有被處理過或者是在處理其它Header區域時已經被使用過。

ultimateReceiver角色為SOAP消息的最總接收者保留,沒有該角色屬性的Header區域不能處理此區域。

用戶自定義SOAP Roles

SOAP角色並不僅限於上一節中預定義的三種角色,SOAP角色可以是任何自定義的角色,如果你定義了你自己的角色,你也必須同時定義角色的語義,換句話說你必須決定這些自定義角色所執行操作的意義。

Header元素中SOAP角色

SOAP Header元素可以使用SOAP角色

下麵是Header元素使用role屬性:

<env:Header>
  <jj:maxTime value="10000" xmlns:jj="https://jenkov.com"
    role="https://www.w3.org/2003/05/soap-envelope/role/ultimateReceiver"
    />
</env:Header>

當Header元素的子元素包含role屬性,隻有作為這個角色的節點才可以處理此元素,所有其它節點都不做處理。

Fault元素中的SOAP角色

SOAP 角色也可以用在Fault元素,Fault元素中的角色信息用來說明產生錯誤的節點的角色。
下麵是Fault元素嵌套Role元素的例子:

<env:Fault>

  <env:Code>
    <env:Value>env:Sender</env:Value>
  </env:Code>

  <env:Reason>
   <env:Text xml:lang="en-US">Error in Input Data</env:Text>
  </env:Reason>

  <env:Node>https://jenkov.com/theNodeThatFailed</env:Node>

  <env:Role>
    https://www.w3.org/2003/05/soap-envelope/role/ultimateReceiver
  </env:Role>

</env:Fault>

SOAP消息交換模式

內容

  • 請求-響應模式
  • 響應模式

SOAP規範提到了一個概念”message exchange patterns” (MEP) 。在SOAP規範中有兩種消息交換模式:

  1. 請求-響應
  2. 響應

本小節將對這兩種消息交換模式進行描述。

請求-響應模式

請求-響應消息交換模式是SOAP客戶端發送一個SOAP請求消息到服務器端,服務器端以SOAP格式的消息返回客戶端。

當SOAP服務需要SOAP客戶端發送的數據才能執行任務時,請求-響應消息交換模式是必要的,例如:如果客戶端需要將數據存儲在服務器端,那麼客戶端必須把需要被存儲的數據發送到服務器端。

下邊圖例描述了請求-響應消息交換:

Alt text
SOAP請求-響應消息交換

響應模式

響應消息交換模式是SOAP客戶端連接到服務器端,但是不向服務器發送SOAP消息內容,而是發送一個簡單的HTTP請求,然後服務器返回響應的SOAP消息。

這種消息交換模式和瀏覽器與web服務器進行通訊的方式相似,瀏覽器發送一個HTTP請求去請求相應的頁麵,但是這個HTTP請求沒有攜帶任何額外的數據,然後web服務器返回請求的頁麵。

響應消息交換模式的圖例:

Alt text

SOAP響應消息交換

最後更新:2017-05-23 15:37:01

  上一篇:go  Java變量類型
  下一篇:go  如何編寫屬於自己的Java / Scala的調試器