一般資訊
SOAP 是簡單物件訪問協議 ( Simple Object Access Protocol )的首字母縮寫,它定義了一種協議,用於通過遠端過程呼叫(RPC)與其他 SOAP 服務或客戶端交換資料。它有兩個版本:
SOAP 1.2 廢棄了 SOAP 1.1,因此建議儘可能使用 SOAP 1.2。
它通常建立在 HTTP / S 之上,很少在 SMTP 或 FTP 上構建,儘管它會根據協議支援它。儘管 HTTP 通常用作底層傳輸協議,但 SOAP 僅使用它的有限子集。對於傳送請求,它幾乎完全依賴於 HTTP 的 POST
操作。從 1.2 開始,GET
呼叫在理論上是可行的,儘管文件必須作為 URI 引數傳遞,因此可能超過大約 3000 個字元邊界,這被大多數框架拒絕。此外,安全相關的設定通常在特殊的 SOAP 標頭中定義。
雖然 SOAP 和 REST 被稱為 Web 服務,但它們本質上是非常不同的。一些框架區分 WS(用於基於 SOAP 的服務)和 RS(用於基於 REST 的服務)。
下表簡要概述了兩種 Web 服務型別之間的差異。
方面 | 肥皂 | 休息 |
---|---|---|
標準 | SOAP , WSDL | 沒有標準,只是一種建築風格 |
資源定址 | 間接通過 SOAP 操作 | 通過唯一資源識別符號(URI) |
錯誤處理 | SOAP 錯誤訊息 | HTTP 錯誤響應程式碼和可選的響應主體 |
資料表示 | XML | HTTP 中所有可用的編碼 |
HTTP 使用情況 | 作為傳輸協議 | 對映在 HTTP 方法上的資源操作(CRUD)(GET,POST,PUT,DELETE,…) |
交易支援 | 通過 SOAP 標頭 | 通過將事務建模為資源 |
狀態 | 有狀態(SOAP 操作是應用程式的一部分) | 無國籍(獨立請求) |
服務發現 | UDDI / WSDL | 實際上沒有; API 的 Start-URI 應返回子 API 列表 |
方法 | 在 SOAP 體內 | HTTP 方法 |
方法引數 | 由 WSDL 中的 XML 模式定義 | 通過 URI 中的 HTTP 標頭或路徑/查詢或 Matrix 引數 |
狀態轉換 | 很難確定不直接基於資料 | 下一個 URI 呼叫 |
快取支援 | 快取通常不需要, | HTTP 定義的簡單 |
肥皂
SOAP 請求由 SOAP 信封組成,該信封必須包含一個 body 元素,並且可以包含一個可選的 header 元素。header 元素用於將某些配置傳遞給服務,例如 WS-Security 可以定義訊息是加密的,或者 WS-Coordination / WS-Transaction 可以定義訊息必須在事務中執行。
一個簡單的 SOAP 1.2 請求通過 HTTP 新增兩個值可能如下所示:
POST /calculator HTTP/1.1
Host: http://example.org
Content-Type: application/soap+xml; charset=utf-8
Content-Length: 224
<?xml version="1.0"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
<env:Body>
<m:AddValues xmlns:m="http://example.org/calculator">
<m:FirstValue>1</m:FirstValue>
<m:SecondValue>2</m:SecondValue>
</m:AddValues>
</env:Body>
</env:Envelope>
對上述示例請求的響應可能如下所示
HTTP/1.1 200 OK
Content-Type: application/soap+xml; charset=utf-8
Content-Length: 329
<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
soap:encodingStyle="http://www.w3.org/2003/05/soap-encoding">
<soap:Body xmlns:m="http://www.example.org/calculator">
<m:AddValuesResponse>
<m:Result>3</m:Result>
</m:AddValuesResponse>
</soap:Body>
</soap:Envelope>
上面的例子定義了一個請求,它使用兩個引數呼叫 AddValues
方法,FirstValue
設定為 1
,SecondValue
設定為 2
。該請求導致在遠端 SOAP 伺服器上執行此方法,該伺服器計算了 3
的值作為結果,該值封裝在單獨的響應元素中,按照慣例,該元素通常是呼叫的方法名稱加上尾隨 Response
字串,因此任何人都是檢查響應可以得出結論,這是之前的 AddValue
方法呼叫的響應。
SOAP 1.1 和 1.2 之間的差異
只要協議支援繫結框架,SOAP 1.2 就允許其他傳輸協議,然後是 HTTP。
SOAP 1.1 基於 XML 1.0,而 1.2 基於 XML Infoset,它允許使用其他序列化程式將 SOAP 訊息序列化,然後使用 SOAP 1.1 使用的預設 XML 1.0 序列化程式。這允許 ie 將訊息序列化為二進位制訊息,從而防止訊息的 XML 性質的一些開銷。除此之外,可以通過資料繫結來確定所使用的底層協議的序列化機制。
通過定義比其前身更具體的處理模型,消除了許多解釋的可能性,SOAP 1.2 也促進了互操作性方面。SOAP with Attachment API(SAAJ)
允許對 SOAP 1.1 和 1.2 訊息進行操作,它幫助許多框架實現者處理和建立訊息。
W3C 釋出了 SOAP 1.1 和 1.2 之間主要變化的簡短概述
Web 服務互操作性
Web 服務互操作性(也稱為 WS-I) 是由一些知名企業(如 IBM,Microsoft,Oracle 和 HP )管理的互操作性指南,僅舉幾例。這些指南建議在 SOAP 主體中僅使用一個單獨的根元素,即使 SOAP 允許在主體內包含多個元素。
WS-I 由
- WS-I Basic Profile 又名 WSI-BP
- WS-I 基本安全配置檔案
- 簡單的肥皂結合配置檔案
WSI-BP 提供 4 個不同版本 v1.0(2004)
, v1.1(2006)
, v1.2(2010)
, v2.0(2010)
, 並定義了核心 Web 服務規範(如 SOAP,WSDL )的互操作性指南和 UDDI。通過使用 Web 服務描述語言(WSDL),SOAP 服務可以在與其他端點的內聚集中描述其支援的操作和方法。WSI-BP 利用 WSDL 定義一個較窄的集合,然後完整的 WSDL 或 SOAP 模式將定義,從而消除規範本身內部的一些歧義,從而提高階點之間的互操作性。
WSDL
為了宣傳可用的 SOAP 操作,它們的引數以及要呼叫給客戶端的相應端點,使用另一個基於 XML 的文件,簡稱為 Web Services Description Language
或 WSDL。
WSDL 描述了服務端點,SOAP 訊息與操作的繫結,操作的介面以及它們對客戶端的型別。與 SOAP 類似,WSDL 有 2 個版本可供選擇,它們的語法略有不同,儘管它們對客戶端表達的語義幾乎相同。
WSDL 1.1
WSDL 1.1 描述包含 service
,binding
,portType
和 message
部分。它可以進一步匯入或定義 WSDL 檔案中的模式,這可以從對應於上面顯示的計算器示例的示例 WSDL 檔案中看到:
<wsdl:definitions xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:calc="http://example.org/calculator"
xmlns:tns="http://example.org/calculatorService"
targetNamespace="http://example.org/calculatorService">
<!--
Abstract type definitions
-->
<wsdl:types>
<!--
<xs:schema>
<xs:import namespace="http://example.org/calculator" schemaLocation="calc/calculator.xsd" />
</xs:schema>
-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://example.org/calculator"
targetNamespace="http://example.org/calculator"
elementFormDefault="qualified"
attributeFormDefault="qualified">
<xs:element name="AddValuesRequest" type="tns:AddValuesType" />
<xs:element name="AddValuesResponse" type="tns:AddValuesResponseType" />
<xs:complexType name="AddValuesType">
<xs:sequence>
<xs:element name="FirstValue" type="xs:int" minOccurs="1" maxOccurs="1" />
<xs:element name="SecondValue" type="xs:int" minOccurs="1" maxOccurs="1" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="AddValuesResponseType">
<xs:sequence minOccurs="1" maxOccurs="1">
<xs:element name="Result" type="xs:int" />
</xs:sequence>
</xs:complexType>
<xs:attribute name="Timestamp" type="xs:dateTime" />
<xs:element name="CalculationFailure">
<xs:complexType>
<xs:sequence>
<xs:element name="ErrorCode" type="xs:int" />
<xs:element name="Reason" type="xs:string" />
</xs:sequence>
<xs:attribute ref="tns:Timestamp" use="required" />
</xs:complexType>
</xs:element>
</xs:schema>
</wsdl:types>
<!--
Abstract message definitions
-->
<wsdl:message name="AddValuesRequest">
<wsdl:part name="in" element="calc:AddValuesRequest" />
</wsdl:message>
<wsdl:message name="AddValuesResponse">
<wsdl:part name="out" element="calc:AddValuesResponse" />
</wsdl:message>
<wsdl:message name="CalculationFault">
<wsdl:part name="fault" element="calc:CalculationFailure" />
</wsdl:message>
<!--
Abstract portType / interface definition
-->
<wsdl:portType name="CalculatorEndpoint">
<wsdl:operation name="AddValues">
<wsdl:documentation>Adds up passed values and returns the result</wsdl:documentation>
<wsdl:input message="tns:AddValuesRequest" />
<wsdl:output message="tns:AddValuesResponse" />
<wsdl:fault name="CalculationFault" message="tns:CalculationFault" />
</wsdl:operation>
</wsdl:portType>
<!--
Concrete binding definition
-->
<wsdl:binding name="CalculatorBinding" type="tns:CalculatorEndpoint">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="AddValues">
<soap:operation soapAction="http://example.org/calculator/AddValuesMessage" />
<wsdl:input>
<soap:body parts="in" use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body parts="out" use="literal" />
</wsdl:output>
<wsdl:fault name="CalculationFault">
<soap:fault name="CalculationFault" use="literal" />
</wsdl:fault>
</wsdl:operation>
</wsdl:binding>
<!--
Concrete service definition
-->
<wsdl:service name="CalculatorService">
<wsdl:port name="CalculatorServicePort" binding="tns:CalculatorBinding">
<soap:address location="http://localhost:8080/services/calculator" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
service
部分定義服務將偵聽傳入請求的具體端點。binding
部分將操作繫結到具體樣式,並定義伺服器期望或客戶端可以期望的訊息格式。
抽象部分由 portType
塊組成,該塊定義了服務提供的操作以及交換的訊息。訊息在其 on 塊中指定,並連結到引數和返回值為例項的模式型別。訊息可以宣告引數或返回值為 in
,out
或 inout
。雖然前兩個很容易掌握,後者模仿參考傳遞的引數的行為。由於某些語言不支援 pass-by-ref,因此通常會通過某些處理程式模擬此效果。
WSDL 2.0
可以在 WSDL 2.0 中描述相同的計算器,如下所示:
<?xml version="1.0" encoding="utf-8" ?>
<wsdl:description xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:wsdl="http://www.w3.org/ns/wsdl"
xmlns:soap="http://www.w3.org/ns/wsdl/soap"
xmlns:calc="http://example.org/calculator"
xmlns:tns="http://example.org/calculatorService"
targetNamespace="http://example.org/calculatorService">
<!--
Abstract type definitions
-->
<wsdl:types>
<!--
<xs:schema>
<xs:import namespace="http://example.org/calculator" schemaLocation="calc/calculator.xsd" />
</xs:schema>
-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://example.org/calculator"
targetNamespace="http://example.org/calculator"
elementFormDefault="qualified"
attributeFormDefault="qualified">
<xs:element name="AddValuesRequest" type="tns:AddValuesType" />
<xs:element name="AddValuesResponse" type="tns:AddValuesResponseType" />
<xs:complexType name="AddValuesType">
<xs:sequence>
<xs:element name="FirstValue" type="xs:int" minOccurs="1" maxOccurs="1" />
<xs:element name="SecondValue" type="xs:int" minOccurs="1" maxOccurs="1" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="AddValuesResponseType">
<xs:sequence minOccurs="1" maxOccurs="1">
<xs:element name="Result" type="xs:int" />
</xs:sequence>
</xs:complexType>
<xs:attribute name="Timestamp" type="xs:dateTime" />
<xs:element name="CalculationFault">
<xs:complexType>
<xs:sequence>
<xs:element name="ErrorCode" type="xs:int" />
<xs:element name="Reason" type="xs:string" />
</xs:sequence>
<xs:attribute ref="tns:Timestamp" use="required" />
</xs:complexType>
</xs:element>
</xs:schema>
</wsdl:types>
<!--
Abstract interface
-->
<wsdl:interface name="CalculatorInterface">
<wsdl:fault name="fault" element="calc:CalculationFault" />
<wsdl:operation name="AddValues" pattern="http://www.w3.org/ns/wsdl/in-out" style="http://www.w3.org/ns/wsdl/style/iri" wsdl:safe="true">
<wsdl:documentation>Adds up passed values and returns the result</wsdl:documentation>
<wsdl:input messageLabel="in" element="calc:AddValuesRequest" />
<wsdl:output messageLabel="out" element="calc:AddValuesResponse" />
<wsdl:outfault messageLabel="fault" ref="tns:fault" />
</wsdl:operation>
</wsdl:interface>
<!--
Concrete binding definition
-->
<wsdl:binding name="CalculatorBinding" interface="tns:CalculatorInterface" type="http://www.w3.org/ns/wsdl/soap" soap:protocol="http://www.w3.org/2003/05/soap/bindings/HTTP/">
<wsdl:operation ref="tns:AddValues" soap:mep="http://www.w3.org/2003/05/soap/mep/soap-response" />
<wsdl:fault ref="tns:fault" soap:code="soap:Sender" />
</wsdl:binding>
<!--
Concrete service definition
-->
<wsdl:service name="CalculatorService" interface="tns:CalculatorInterface">
<wsdl:endpoint name="CalculatorEndpoint" binding="tns:CalculatorBinding" address="http://localhost:8080/services/calculator" />
</wsdl:service>
</wsdl:description>
WSDL 1.1 和 2.0 之間的差異
有關兩個版本之間差異的圖形概述,請參見下圖。
( 來源 )
從影象中可以看出,message
部分被移除了,現在包含在 interface
部分中。此外,一些元素已重新命名,其他元素具有不同的語法,但通常兩個 WSDL 版本與版本 2.0 基本相同,與 1.1 相比需要更少的寫入開銷。
除了通過 WSDL 2.0 定義基於 SOAP 的服務的佔地面積較小之外,較新的版本還提供了定義 REST 服務的功能, 儘管 WSDL 2.0 甚至 WADL 不建議用於 RESTful 服務,因為它們與其背後的實際想法相矛盾。
喜歡哪種風格
WSDL 繫結部分描述了服務如何繫結到 SOAP 訊息傳遞協議。上面的示例使用 document
作為繫結樣式,只要結果輸出是有效的 XML 例項,就可以按照我們想要的方式構造 SOAP 主體。這是預設的繫結樣式,通常稱為 Message-Oriented style
。
與 document
樣式相比,RPC
樣式請求體必須包含操作名稱和方法引數集。因此,XML 例項的結構是預定義的,無法更改。
除了繫結樣式之外,繫結部分還定義了一個轉換模型,用於以 literal
或 encoded
的名義繫結到 SOAP 訊息。兩者之間的區別在於,literal
模型必須符合使用者定義的 XSD 結構,可用於驗證請求和響應,而 encoded
模型必須使用像 xs:integer
或 xs:string
這樣的 XSD 資料型別,但是因此具有不符合任何使用者定義的架構。但是,這使得更難以驗證訊息體或通過 XSLT 將訊息轉換為其他格式。
繫結樣式與使用模型的組合實際上允許 4 種不同的訊息結果。第 5 個條目被新增到常用的列表中(雖然不是標準的一部分)。
- RPC /編碼
- RPC / literal
- 檔案/編碼
- 檔案/文字
- 檔案/文字(包裹)
在文件/文字樣式的訊息傳遞中,存在一種稱為 wrapped-document / literal 的模式。這只是一種模式,並不是 WSDL 規範的一部分。在 JSR 224(JAX-WS:基於 XML 的 Web 服務的 Java API)中提到了這種模式。 ( 來源 )
以下部分概述了有關 WSDL 或模式宣告的差異及其在更改繫結樣式或使用模型定義時對生成的 SOAP 訊息格式的影響。
RPC /編碼
WSDL:
...
<wsdl:message name="AddValues">
<wsdl:part name="FirstValue" type="xsd:int" />
<wsdl:part name="SecondValue" type="xsd:int" />
</wsdl:message>
<wsdl:message name="AddValuesResponse">
<wsdl:part name="Result" type="xsd:int" />
</wsdl:message>
<wsdl:portType name="CalculatorEndpoint">
<wsdl:operation="AddValues">
<wsdl:input message="AddValues" />
<wsdl:output message="AddValuesResponse" />
</wsdl:operation>
</wsdl:portType>
<!-- binding style set to 'RPC' and use to 'encoded' -->
...
SOAP 請求
<soap:envelope>
<soap:body>
<AddValues>
<FirstValue xsi:type="xsd:int">1</FirstValue>
<SecondValue xsi:type="xsd:int">2</SecondValue>
</AddValues>
</soap:body>
</soap:envelope>
SOAP 響應
<soap:envelope>
<soap:body>
<AddValuesResponse>
<Result xsi:type="xsd:int">3</Result>
</AddValuesResponse>
</soap:body>
</soap:envelope>
優點
- 直截了當的 WSDL
- 請求和響應中可用的操作名稱和元素
缺點
- XSI 型別的明確宣告
- 很難驗證
- 不符合 WS-I 標準
RPC / literal
WSDL:
...
<wsdl:message name="AddValues">
<wsdl:part name="FirstValue" type="xsd:int" />
<wsdl:part name="SecondValue" type="xsd:int" />
</wsdl:message>
<wsdl:message name="AddValuesResponse">
<wsdl:part name="Result" type="xsd:int" />
</wsdl:message>
<wsdl:portType name="CalculatorEndpoint">
<wsdl:operation="AddValues">
<wsdl:input message="AddValues" />
<wsdl:output message="AddValuesResponse" />
</wsdl:operation>
</wsdl:portType>
<!-- binding style set to 'RPC' and use to 'literal' -->
...
SOAP 請求
<soap:envelope>
<soap:body>
<AddValues>
<FirstValue>1</FirstValue>
<SecondValue>2</SecondValue>
</AddValues>
</soap:body>
</soap:envelope>
SOAP 響應
<soap:envelope>
<soap:body>
<AddValuesResult>
<Result>3</Result>
</AddValuesResult>
</soap:body>
</soap:envelope>
優點
- 直截了當的 WSDL
- 請求和響應中可用的操作名稱和元素
- 不需要 XSI 型別規範
- 符合 WS-I 標準
缺點
- 很難驗證
檔案/編碼
因此省略沒有任何意義。
檔案/文字
WSDL:
...
<types>
<schema>
<element name="FirstValueElement" type="xsd:int" />
<element name="SecondValueElement" type="xsd:int" />
<element name="ResultValueElement" type="xsd:int" />
</schema>
</types>
<wsdl:message name="AddValues">
<wsdl:part name="FirstValue" element="FirstValueElement" />
<wsdl:part name="SecondValue" element="SecondValueElement" />
</wsdl:message>
<wsdl:message name="AddValuesResponse">
<wsdl:part name="Result" element="ResultValueElement" />
</wsdl:message>
<wsdl:portType name="CalculatorEndpoint">
<wsdl:operation="AddValues">
<wsdl:input message="AddValues" />
<wsdl:output message="AddValuesResponse" />
</wsdl:operation>
</wsdl:portType>
<!-- binding style set to 'Document' and use to 'literal' -->
...
SOAP 請求
<soap:envelope>
<soap:body>
<FirstValueElement>1</FirstValueElement>
<SecondValueElement>2</SecondValueElement>
</soap:body>
</soap:envelope>
SOAP 響應
<soap:envelope>
<soap:body>
<ResultElement>3</ResultElement>
</soap:body>
</soap:envelope>
優點
- 沒有 XSI 型別編碼
- 能夠驗證身體
- WS-I 符合限制
缺點
- 由於額外的 XSD 定義,WSDL 更復雜
- 操作名稱丟失
- WS-I 只允許 SOAP 體中的一個子節點
檔案/文字(包裹)
WSDL:
...
<types>
<schema>
<element name="AddValues">
<complexType>
<sequence>
<element name="FirstValue" type="xsd:int" />
<element name="SecondValue" type="xsd:int" />
</sequence>
</complexType>
</element>
<element name="AddValuesResponse">
<complexType>
<sequence>
<element name="ResultValue" type="xsd:int" />
</sequence>
</complexType>
</element>
</schema>
</types>
<wsdl:message name="AddValues">
<wsdl:part name="in" element="AddValues" />
</wsdl:message>
<wsdl:message name="AddValuesResponse">
<wsdl:part name="out" element="AddValuesResponse" />
</wsdl:message>
<wsdl:portType name="CalculatorEndpoint">
<wsdl:operation="AddValues">
<wsdl:input message="AddValues" />
<wsdl:output message="AddValuesResponse" />
</wsdl:operation>
</wsdl:portType>
<!-- binding style set to 'Document' and use to 'literal' -->
...
SOAP 請求
<soap:envelope>
<soap:body>
<AddValues>
<FirstValue>1</FirstValue>
<SecondValue>2</SecondValue>
</AddValues>
</soap:body>
</soap:envelope>
SOAP 響應
<soap:envelope>
<soap:body>
<AddValuesResponse>
<Result>3</Result>
</AddValuesResponse>
</soap:body>
</soap:envelope>
優點
- 沒有 XSI 型別編碼
- 能夠驗證身體
- 請求和響應中可用的操作名稱和元素
- 符合 WS-I 標準
缺點
- 由於額外的 XSD 定義,WSDL 更復雜
UDDI
Universal Description, Discovery and Integration (UDDI)
是一個在 2000 年建立的開放式行業計劃,它作為基於 XML 的黃頁網頁服務登錄檔,幫助查詢解決特定任務的服務。為了找到適當的服務,需要首先使用 Web 服務登錄檔(如 UDDI)註冊服務。
UDDI 處理 SOAP 訊息交換,並提供對 WSDL 文件的訪問,這些文件可用於呼叫實際的 Web 服務。
UDDI 提供了諸如的查詢標準
- 業務識別符號
- 公司名稱
- 營業地點
- 業務類別
- 服務型別名稱
- 發現網址
但是,當前 UDDI 的一大缺點是它只允許在搜尋語句中使用一個單一條件。因此,某些實現者將其 UDDI 實現模組化,以允許同時生成多個 UDDI 的查詢,然後聚合返回的結果。
然而,在實踐中,經常不使用 UDDI。有些人甚至說 UDDI 已經死了,因為 IBM,微軟和 SAP 在 2005 年關閉了他們的 UDDI 服務 。
附加說明:
SOAP / WSDL 提供了廣泛的工具支援,並且還允許為客戶端和伺服器動態生成存根類,因為通過嵌入或連結的 XSD 模式很好地定義了訊息和資料交換的型別。
雖然 WSDL 2.0 定義 Web 服務的開銷較小,但某些語言尚未採用新標準。即 Java 中流行的工具,如 wsimport
(來自 Oracle / Sun)或 wsdl2java
(來自 Apache CXF),無法正確處理 WSDL 2.0 描述。因此,出於相容性原因,仍建議使用 WSDL 1.1。如果你需要在 Java 中開發基於 WSDL 2.0 的 SOAP 服務,請檢視來自 Apache Axis2 專案的 wsdl2java
。
然而,現在比較流行的是基於 HTTP 的 API 服務,它將 HTTP 操作呼叫與乾淨的人類可理解的 URI 混合,並對協議進行某些自定義以完成其工作,基於 REST 的服務完全符合實際建議,或者自己的位元組級協議,例如 OFTP2 。
如果你無法將任務直接對映到資源(如 HTTP / REST 基本服務),SOAP 現在仍然很有用,因為要實現的任務自然代表一個操作或必須定義某些事務語義。此外,如果你沒有資源來定義或實現自己的協議,那麼你最好使用 SOAP。如果你必須處理業務流程,SOAP 特別有用,因為 WSDL 描述與 UDDI 結合允許動態組合服務。