監(jiān)理公司管理系統(tǒng) | 工程企業(yè)管理系統(tǒng) | OA系統(tǒng) | ERP系統(tǒng) | 造價咨詢管理系統(tǒng) | 工程設計管理系統(tǒng) | 甲方項目管理系統(tǒng) | 簽約案例 | 客戶案例 | 在線試用
X 關閉

使用WSDL部署Web服務,第2部分:簡單對象訪問協(xié)議(SOAP)

申請免費試用、咨詢電話:400-8352-114

AMTeam.org

使用WSDL部署Web服務,第2部分:簡單對象訪問協(xié)議(SOAP)  

--學習SOAP語法,用SOAP部署WSDL應用程序


Bilal Siddiqui (wap_monster@yahoo.com)

CEO, WAP Monster

2002 年 3 月

簡單對象訪問協(xié)議(SOAP)提供對遠程對象的訪問。這些對象有的是簡單的 JavaBeans 組件或者是企業(yè) JavaBeans 組件和 COM/COM+ 對象等。這些對象駐留在不同企業(yè)內部并且可能存在于因特網的任何位置。因此,SOAP 通過因特網進行通信,它是一種在不同企業(yè)間交換信息的機制。在本文中,Bial 會詳細的討論 SOAP 通信,對象是怎樣用 SOAP 發(fā)布其功能的,怎樣調用 SOAP 對象,怎樣在有 SOAP 意識的應用程序間交換信息。他還會展示第 1 部分中提到的 WSDL 應用程序的 SOAP 服務部署,以及遠程服務器對它的調用。

SOAP 和 WSDL

我在本系列文章的第 1 部分介紹了 WSDL。WSDL 描述了 Web 服務的接口。Web 服務所有者將用 SOAP 來實現(xiàn)他們的接口。因此,WSDL 服務實際上作為 SOAP 服務一樣存在。一旦 Web 服務用戶擁有 WSDL 文件,他或者她就知曉接口的細節(jié)。他或者她就會用 SOAP 來與 Web 服務通信。

可以把 Web 服務考慮為對象,可以通過 WSDL 接口公開并且使用 SOAP 通過因特網遠程訪問。既然服務是對象,那么肯定有每種服務的相關屬性和每種服務調用的行為。SOAP 消息是 XML 文檔,可通過 HTTP 工作。

為什么用 SOAP?

B2B(Business-to-business)和 A2A(application-to-application )需求表明企業(yè)之間為交換信息而相互通信。這種概念被用在 B2B、工作流和跨企業(yè)集成中。例如,設想一條垂直供應鏈,在鏈上一家企業(yè)為了滿足它的客戶需求而需要調用其提供者的服務。而一些提供者需要沿供應鏈進一步下行來調用其它企業(yè)的服務。

很明顯,在此應用程序中互操作性是最為重要的。任何單個企業(yè)只能實現(xiàn) SOAP 通信通道的一端。另一端將是因特網上任何地方的實體。

在最近幾年里,企業(yè)之間的集成和互操作性已經成為軟件工程師和企業(yè)的一個挑戰(zhàn)性任務。平臺相關性也成為取得集成和互操作性的一個大問題。SOAP 依然是在企業(yè)間取得集成和互操作性最簡單的機制。

SOAP 體系結構

有了對 SOAP 和它的用途的基本理解,我現(xiàn)在就展開對其體系結構的討論以了解一些深層知識。請參閱圖 1,在此圖里面您可以識別典型 SOAP 通信體系結構中的一些組件:

SOAP 客戶機

SOAP 服務器

實際服務

圖 1. 一個典型 SOAP 通信體系結構的組件


 

讓我解釋上面所提到的每個實體的體系結構角色。

下面的討論參照圖 1。

SOAP 客戶機

SOAP 客戶機是一臺有 SOAP 機制的機器,它可以產生 SOAP 請求并通過 HTTP 發(fā)送到服務器。一條 SOAP 請求是一種類型的 SOAP 消息,通常只有兩種類型的 SOAP 消息:一條 SOAP 請求就是一臺 SOAP 客戶機發(fā)送給 SOAP 服務器的內容,一條 SOAP 響應就是 SOAP 服務器對 SOAP 客戶機響應的內容。清單 1 是典型的 SOAP 請求,請參閱清單 2 來回顧 SOAP 響應。

清單 1:一條簡單的 SOAP 請求

<SOAP-ENV:Envelope  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" >
   <SOAP-ENV:Body>
 <m:getListOfModels xmlns:m = "uri reference" >
 </m:getListOfModels>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

SOAP 服務器

SOAP 服務器也是一臺有 SOAP 機制的機器,能夠接收來自 SOAP 客戶機的請求,并對之作出適當?shù)捻憫?。這些編過碼的響應會返回發(fā)出請求的 SOAP 客戶機。在 SOAP 服務器內部有三個實體:

服務管理器

被部署服務的列表

XML 轉換程序

服務管理器負責根據請求管理服務。請參閱清單 1 的服務請求,在這里元素 <m:getListOfModels xmlns:m="urn:MobilePhoneservice" > 包含了服務的名稱。服務管理器會讀取 SOAP 客戶機想調用的 SOAP 服務的名稱并檢查所需的服務實際上是否駐留于這臺 SOAP 服務器上。此后,它會查詢被部署服務的列表(SOAP 服務器所托管的所有服務的列表)。若存在,服務管理器將把 SOAP 請求傳送給 XML 轉換程序。XML 轉換程序就負責將 SOAP 請求的 XML 結構轉換成程序員用來實現(xiàn)實際服務的編程語言(例如,Java 編程語言)的結構。還要負責將來自實際服務的響應轉換回 SOAP 響應的 XML 結構。請參閱清單 2 獲得 SOAP 響應的說明。

清單 2:一條簡單的 SOAP 響應

<SOAP-ENV:Envelope  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
   <SOAP-ENV:Body>
 <m:getListOfModelsResponse xmlns:m="urn:MobilePhoneservice">
  <Model>M1</Model>
  <Model>M2</Model>
  <Model>M3</Model>
 </m:getPriceResponse>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

實際服務

圖 1 中標有 actual service 的框就是實際服務駐留的位置。服務實現(xiàn)可以是:例如,COM 組件或 JavaBeans 組件的形式。XML 轉換程序負責將 XML 結構轉換成合適的方法調用。當 XML 轉換程序調用了實際服務實現(xiàn)的某個方法時,這個方法就會完成它的工作并且將結果信息返回 XML 轉換程序。

請看一看圖 1 中連接 XML translator 和 actual service 的箭頭。箭頭的兩端同在一個企業(yè)內,這意味著同一個組織控制著通信兩端的接口。與穿過企業(yè)邊界的在 SOAP 客戶機和 SOAP 服務器之間的箭頭相比,這正是 SOAP 的目的所在。

SOAP 請求響應機制

當 SOAP 客戶機向 SOAP 服務器發(fā)送 SOAP 消息時,用 HTTP 協(xié)議傳輸。這就叫做 SOAP 與 HTTP 綁定。當 SOAP 服務器收到消息時,將消息交給服務管理器。服務管理器檢查被部署服務的列表,查找在 SOAP 消息中所需的服務。若沒有查找到所請求的服務,它將請求失敗返回給 SOAP 客戶機。但是若此項服務可以提供,控制權由服務管理器轉移給 XML 轉換程序(轉換程序完成合適語言的轉換并訪問實際服務實現(xiàn))。服務實現(xiàn)會處理請求并將結果返回給 XML 轉換程序。XML 轉換程序將結果轉換成 SOAP 客戶機能夠理解的 SOAP 響應(XML 文檔)。然后又一次用 HTTP 綁定來傳輸 SOAP 響應。

現(xiàn)在讓我們看一下 SOAP 與 HTTP 的綁定細節(jié)。

SOAP 與 HTTP 綁定

當您將 SOAP 和 HTTP 綁定在一起或在 HTTP 上操作 SOAP 時,您實際上將 HTTP 報頭加到了 SOAP 請求和響應上了。清單 1 是典型 SOAP 請求的結構,而清單 3、4、5 和 6 都是完整的 HTTP 請求,用來演示如何將 HTTP 報頭添加到清單 1 上。相似地,清單 7 是一條完整的 HTTP 響應,針對于來自清單 2 的 SOAP 響應。

無論您何時在 HTTP 上使用 SOAP,Content-Type 字段必須是 text/xml?,F(xiàn)在您可以察看清單 3 到清單 7 的詳情。

使用 HTTP 的 SOAP 請求

您可以將 SOAP 和 HTTP 的 POST 請求方法連用。為了發(fā)送一條 SOAP HTTP 請求,您需要在 HTTP 中提供一個 SOAPAction 報頭字段。
SOAPAction 指定了 SOAP 請求的目的。服務器(例如過濾 HTTP 中 SOAP 請求消息的防火墻)可以用字段 SOAPAction 的值來做決定。

HTTP 客戶機在發(fā)送一條 SOAP HTTP 請求時必須用此報頭字段。SOAPAction 可以有如下幾種值:

SOAPAction:"URI-Reference"
SOAPAction:"filename"
SOAPAction:""
SOAPAction:

清單 3:演示 SOAPAction 報頭字段中的 URI 引用

POST /Vendors HTTP/1.1
Host:
www.mobilephoneservice.com
Content-Type:"text/xml";Charset="utf-8"
Content-Length: nnnn
SOAPACtion:"
www.mobilephoneservice.com/Vendors/MobilePhoneservice#getListOfModels"

<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"  >
 <SOAP-ENV:Body>
  <m:getListOfModels xmlns:m="urn:MobilePhoneservice" >
  </m:getListOfModels>
 </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

 清單 3 在 SOAPAction 中包括如下 URI 引用:www.mobilephoneservice.com/Vendors/MobilePhoneservice#getListOfModels

這個 SOAPAction 展示了兩部分內容。第一部分是一個特別 SOAP 部署的地址:www.mobilephoneservice.com/Vendors/MobilePhoneservice

第二部分是一個片段標識符,它給出了我們感興趣的方法的名字(#getListOfModels)。

清單 4:演示 SOAPAction 報頭字段中的一個文件名

POST /Vendors HTTP/1.1
Host:
www.mobilephoneservice.com
Content-Type:"text/xml";Charset="utf-8"
Content-Length: nnnn
SOAPAction:"MobilePhoneservice#getListOfModels"

<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"  >
 <SOAP-ENV:Body>
  <m:getListOfModels xmlns:m="urn:MobilePhoneservice" >
  </m:getListOfModels>
 </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

 清單 4 在 SOAPAction 中包含一個文件名(MobilePhoneservice#getListOfModels)。MobilePhoneservice 文件必須出現(xiàn)在主機 URI(www.mobilephoneservice.com/Vendors)中。這個主機 URI 是在 HTTP 報頭中 host 字段(www.mobilephoneservice.com)和文件夾名(/Vendors)的結合。

清單 5:演示 SOAPAction 報頭中的空字符串

POST /Vendors HTTP/1.1
Host:
www.mobilephoneservice.com
Content-Type:"text/xml";Charset="utf-8"
Content-Length: nnnn
SOAPAction:""

<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"  >
 <SOAP-ENV:Body>
  <m:getListOfModels xmlns:m="urn:MobilePhoneservice" >
  </m:getListOfModels>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

清單 5 在 SOAPAction 中包含一個空字符串("")。空字符串值表明 SOAP 的目的和 Host URI(www.mobilephoneservice.com/Vendors)的目的是一樣的。

清單 6:演示無值 SOAPAction 報頭

POST /Vendors HTTP/1.1
Host:
www.mobilephoneservice.com
Content-Type:"text/xml";Charset="utf-8"
Content-Length: nnnn
SOAPAction:

<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"  >
 <SOAP-ENV:Body>
  <m:getListOfModels xmlns:m ="urn:MobilePhoneservice" >
  </m:getListOfModels>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

清單 6 沒有包含 SOAPAction 值。這表明沒有關于消息目的的信息。

用 HTTP 的 SOAP 響應

響應將可能是兩種類型的 SOAP 響應中的一種:

一個成功的 SOAP 操作產生 SOAP 結果

一個不成功的 SOAP 操作產生一條 SOAP 錯誤消息

清單 7:一條帶有 HTTP 報頭的成功 SOAP 響應

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

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" >
<SOAP-ENV:Body>
 <m:getListOfModelsResponse xmlns:m = "URI-Reference">
  <model>m1</model>
  <model>m2</model>
 </m:getListOfModels>
</SOAP-ENV:Body>

 清單 7 是第一種情況,在此可以從 SOAP 服務器取得有意義的結果。

清單 8 是一條典型的 SOAP 錯誤消息。SOAP HTTP 響應遵循 HTTP 中通信狀態(tài)信息的 HTTP 狀態(tài)碼的語義。若在處理一條請求時發(fā)生一個 SOAP 錯誤,SOAP HTTP 服務器必須發(fā)出一條 HTTP 500 "Internal Server Error" 響應,同時在響應中包括一條帶有 SOAP 出錯元素的 SOAP 消息。

清單 8:一條帶有 HTTP 報頭的典型 SOAP 錯誤消息

HTTP/1.1 500 Internal Server Error
Content-Type: "text/xml"; Charset="utf-8"
Content-Length: nnnn

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" >
 <SOAP-ENV:Body>
  <SOAP-ENV:Fault>
  <faultstring>Failed to process the request</faultstring>
  </SOAP-ENV:Fault>
 </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

使用電子郵件的 SOAP

HTTP 不是唯一綁定 SOAP 消息的解決方案。若 HTTP 不合適,您可以用諸如 SMTP 的其它機制來用于 SOAP 綁定。將 SOAP 和 SMTP 綁定,您可以建立一條單向傳輸路由。兩條單向消息可以用來建立請求/響應通信。用 SMTP 來發(fā)送一條 SOAP 消息,您需要遵從以下步驟:

使用 MIME-Version 報頭字段

MIME-Version 用一個版本號來區(qū)別不同的 MIME 版本。它應用郵件處理代理(例如一個 POP 服務器)來區(qū)別舊版本和新版本所生成的郵件消息。請參閱清單 9,它使用了一個 MIME-Version 報頭字段。

清單 9:一個使用電子郵件的 SOAP 示例

TO: <
info@waxsys.com>
From: <
abc@punjab.com>
Reply-To: <
abc@punjab.com>
Date: SAT, 2 Feb 2002 16:00:00
Message-Id: <
4FAB345C8D93E93B7A6E9@punjab.com>
 MIME-Version: 1.0
Content-Type: text/xml; charset=utf-8
Content-Transfer-Encoding: QUOTED-PRINTABLE

<?xml version ="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
 <SOAP-ENV:Body>
  <prnt:echoString xmlns:prnt="http://waxsys.com">
   <msgString>Put your mail Message</msgString>
  </prnt:echoString>
 </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

 使用 Content-Type 報頭字段:

Content-Type 用來標識消息主體中的數(shù)據類型。對于 SOAP 消息 Content-Type 應該有一個值“text/xml”。請參閱清單 9 ,它使用了 Content-Type。

使用 Content-Transfer-Encoding 字段:

Content-Transfer-Encoding 用來指定傳輸編碼的類型,也就是您所要傳輸?shù)臄?shù)據是字符格式還是二進制格式。清單 9 使用 Quoted-Printable 編碼,這種編碼符合依照 ASCII 字符集的可打印字符。這種對數(shù)據的編碼方式使郵件傳輸代理不可能修改結果八位元。請參閱清單 9,它使用了 Content-Transfer-Encoding 。

SOAP 模式與實現(xiàn)

SOAP 消息

一條 SOAP 消息只是一個 XML 文檔,由一個強制性的 SOAP Envelope 組成,SOAP Envelope 有一個可選的 SOAP Header 和一個必須有的 SOAP Body。

SOAP 模式的元素:

Envelope
Header
Body
Fault

Envelope:

Envelope 是表示一條 SOAP 消息的頂層元素。為了發(fā)送一條 SOAP 消息,必須包括此元素。Envelope 使用必要的 SOAP 名稱空間標識符(http://schemas.xmlsoap.org/soap/envelope/ )。若 Envelope 包含了錯誤的名稱空間,會產生一個關于 Envelope 名稱空間版本的錯誤。清單 10 是一個空 Envelope。稱其為“空 Envelope”是為了強調在通過“投遞”發(fā)出它之前,它最終應該包含一封“信”(也許是商業(yè)信)。SOAP 模式中的“信”就是指“SOAP Body”,HTTP POST(在 HTTP 與 SOAP 的綁定一部分討論過)就是傳輸機制。

清單 10:一個空 SOAP Envelope

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">

</SOAP-ENV:Envelope>

Header:

SOAP Header 是可選的。您可以直接將 SOAP Body 放到 SOAP Envelope 中并完全忽略報頭。報頭提供了一個擴展 SOAP 消息功能的機制。例如,認證就是由 SOAP Header 條目所提供的一種典型擴展。在此情況下,將有一個認證框架,它會使用 SOAP 作為更低級別的傳輸。請參閱清單 11 來查看在 SOAP 中的報頭實現(xiàn)。

清單 11:在一個 SOAP Envelope 中的報頭實現(xiàn)

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
 <m:Order xmlns:m="some URI" SOAP-ENV:mustUnderstand="1">
 </m:Order>
</SOAP-ENV:Header>
</SOAP-ENV:Envelope>

Body:

Body 元素包含您實際要發(fā)送的消息。它是一個強制性的元素且其子元素通常屬于一個用戶定義的名稱空間。清單 12 展示了一條引用一個用戶定義的名稱空間“u”的 SOAP 消息。Body 元素是必要信息的容器。這個元素必須在 SOAP 消息中出現(xiàn)并且必須是 SOAP Envelope 元素的一個直接子元素。它也必須直接跟在 SOAP Header 元素的后面。若沒有 Header 元素,那么它應直接跟在 Envelope 元素的后面。主體可以包含子元素并且子元素可能是受限于名稱空間的。

清單 12: SOAP Envelope 內有 Header,還有 Body

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
 <m:Order xmlns:m="some URI" SOAP-ENV:mustUnderstand="1">
 </m:Order>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
 <u:GetPrice xmlns:u="some URI" >
  <model>m1</model>
 </u:GetPrice>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

 Fault:

這個元素表明一條錯誤消息。它應作為一個主體條目出現(xiàn)并且不能在 Body 元素中出現(xiàn)一次以上。通常,F(xiàn)ault 元素會在一條 SOAP 響應消息中出現(xiàn),以表明在 SOAP 請求中出現(xiàn)錯誤。

Fault 的子元素:

faultcode(錯誤的標識)

faultstring(錯誤的描述)

faultactor(標識由誰導致的錯誤)

detail(錯誤細節(jié)。通常是一個應用程序特定錯誤,也就是說,它相當于在 SOAP 請求主體中用到地用戶定義的名稱空間)

清單 13 是一條典型的錯誤消息。

清單 13: 當應用程序出現(xiàn)錯誤時,SOAP Fault 的使用

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
<m:Order xmlns:m="some URI" SOAP-ENV:mustUnderstand="1">
</m:Order>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<SOAP-ENV:Fault>
<faultcode>SOAP-ENV:Server</faultcode>
<faultstring>Not necessary information</faultstring>
<detail>
 <d:faultdetail xmlns:d = "uri-referrence">
  <msg>
   application is not responding properly.
  </msg>
  <errorcode>12</errorcode>
 </d:faultdetail>
</detail>
</SOAP-ENV:Fault>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

來自第 1 部分的一條對 WSDL 文件的 SOAP 請求

已經解釋了 SOAP 消息(請求和響應)的常規(guī)語法,我將展示如何對本系列第 1 部分中的 MobilePhoneservice 開發(fā)一條 SOAP 請求。在第 1 部分中您設計一個完整的 WSDL 接口來解釋 MobilPhoneservice。移動公司在 MobilePhoneservice 中提供了兩種方法,一種是 getListOfModels(),另一種是 getPrice(modelNumber)。GetListOfModels() 沒有參數(shù)但是返回手機型號的一張列表,而 getPrice(modelNumber) 有一個參數(shù) modelNumber 并返回需求型號的 price。您將用 SOAP 請求格式對它作成文檔,但是首先讓我展示給您一般的 SOAP 請求和響應格式。

清單 14:SOAP 請求的一般格式

<SOAP-ENV:Envelope xmlns:SOAP-ENV ="SOAP schema's URI"
<SOAP-ENV:Body>
 <Instance:"Method Name" xmlns:Instance= "URI where method is located">
  <parameter1>value</parameter1>
  <parametern>value</parametern>
 </Instance:"Method Name">
</SOAP_Envelop:Body>
</SOAP-ENV:Envelope>

 一條簡單的 SOAP 請求或響應只能表明一種服務的一個方法。包含一條 SOAP 請求的 Envelope 的一般格式遵從清單 14。將這種一般格式與清單 16 中的 getListOfModels() 的方法調用請求比較。在清單 16 中,我已經提供了方法和 URI 的名稱。既然在 getListOfModels() 中不需要參數(shù),所以 <m:getListOfModels> 在清單 16 中是一個空元素。

清單 15:一條 SOAP 響應的一般格式

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
 <Instance:"Method Name"+"Response"
 xmlns:Instance="URI where method is located">
 <return>
  <responseparameter1>value</responseparameter1>
  <responseparametern>value</responseparametern>
 </return>
 </Instance: "Method Name"+"Response">
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

清單 15 是一條一般的 SOAP 響應。Apache SOAP 服務器在方法名稱的后面增加了"Response"關鍵字并將返回值封入元素 <return> 中作為一個直接子方法元素。若返回值是復合型結構,那么 <return> 元素包含一個或多個 <item> 元素。將清單 15 與清單 17 相比,清單 17 是來自 getListOfModels() 的實際響應。清單 17 包含一系列項目,作為 Vector 數(shù)據類型,它是返回參數(shù)。相似地,清單 18 和 19 展示了針對 MobilePhoneservice 的方法 getPrice() 的 SOAP 請求和響應。

清單 16:調用 getListOfModels() 方法的 SOAP 請求

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
 <m:getListOfModels xmlns:m = "
www.mobilphoneservice.com" >
 </m:getListOfModels>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

清單 17:針對于來自清單 16 請求的 SOAP 響應

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
 xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
 xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
 xmlns:xsd="http://www.w3.org/1999/XMLSchema">
<SOAP-ENV:Body>
 <ns1:getListOfModelsResponse xmlns:ns1="urn:MobilePhoneservice"
 SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
 <return xmlns:ns2="http://xml.apache.org/xml-soap"
  xsi:type="ns2:Vector">
  <item xsi:type="xsd:string">M1</item>
  <item xsi:type="xsd:string">M2</item>
  <item xsi:type="xsd:string">M3</item>
  <item xsi:type="xsd:string">M4</item>
  <item xsi:type="xsd:string">M5</item>
 </return>
 </ns1:getListOfModelsResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

清單 18:對于 getPrice 方法的 SOAP 請求

<SOAP-ENV:Envelope
 xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
 xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
 xmlns:xsd="http://www.w3.org/1999/XMLSchema">
<SOAP-ENV:Body>
 <m:getPrice xmlns:m ="
www.mobilphoneservice.com">
  <modelNumber xsi:type ="xsd:String">M1</modelNumber>
 </m:getPrice>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

清單 19:對于來自清單 18 請求的 SOAP 響應

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
 xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
 xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
 xmlns:xsd="http://www.w3.org/1999/XMLSchema">
<SOAP-ENV:Body>
 <ns1:getPriceResponse xmlns:ns1="urn:MobilePhoneservice"
  SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
   <return xsi:type="xsd:string"> 5000 </return>
 </ns1:getPriceResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

 在 SOAP 服務器上部署基于 WSDL 的服務

在此部分您將在 Apache SOAP 服務器上部署來自第 1 部分的 WSDL 服務。Apache SOAP 工具箱將 WSDL 服務信息保存在一個部署描述符文件里面。部署描述符包含了 WSDL 服務的名稱和它擁有的所有方法。在運行時部署描述符會將這些名稱提供給 SOAP 服務器。同樣的部署描述符文件還包含了實現(xiàn)接口的 JavaBean 組件的地址。

清單 20:一個部署描述符的框架

<isd:service xmlns:isd="http://xml.apache.org/xml-soap/deployment"
 id="URN:SERVICE-URN">
<isd:provider type="java"
 scope="Request"
 methods="EXPOSED-METHODS">
 <isd:java class="IMPLEMENTING-CLASS"/>
</isd:provider>
<isd:faultListener>org.apache.soap.server.DOMFaultListener
</isd:faultListener>
</isd:service>

 清單 20 是一個部署描述符的框架,為了作為基于 WSDL 服務的部署描述符使用,它需要三項信息(URN:SERVICE-URN、EXPOSED-METHODS 和 IMPLEMENTING-CLASS)。URN:SERVICE-URN 是被部署服務的名稱。在此例中它是“urn:MobilePhoneservice”。EXPOSED-METHODS 是一個單空格分隔的由服務提供的方法的列表。在此部署中它是 getListOfModels getPrice。

IMPLEMENTING-CLASS 是帶有全路徑的 Java 類名稱。例如,samples.phonequote.MobilePhoneservice。在此例中測試應用程序時,您有如下目錄結構:

Apache SOAP 服務器:C:fooSOAP-2_2

Mobile phone 服務實現(xiàn):

C:fooSOAP-2_2samplesphonequoteMobilePhoneservice

因此,IMPLEMENTING-CLASS 路徑請參照您安裝 SOAP 工具箱的目錄。我沒有提供 Java 類的實際實現(xiàn)。它取決于業(yè)務邏輯并且可以是任何東西。

清單 21:MobilePhoneservice 的部署描述符

<isd:service xmlns:isd="http://xml.apache.org/xml-soap/deployment"
id="urn:MobilePhoneservice">
<isd:provider type="java"
 scope="Request"
 methods="getListOfModels getPrice">
 <isd:java class="samples.phonequote.MobilePhoneservice"/>
</isd:provider>
<isd:faultListener>
 org.apache.soap.server.DOMFaultListener
</isd:faultListener>
</isd:service>

清單 21 是來自第 1 部分對 WSDL 文件的完整部署描述符。

SOAP 客戶機與 SOAP 服務器的通信

我已經提供過一個應用程序樣本來演示一臺 SOAP 客戶機與一臺 SOAP 服務器的通信。為此我給過三個列表:Startup.html(清單 22)、Operation.html(清單 23)和 Execute.jsp(清單 24)。

StartUp.html(清單 22)是一個簡單的 HTML 文件,提供給用戶一個 GUI 并詢問他將要調用哪一個 SOAP 方法。用戶會選擇一個他需要的方法。

清單 22:一個作為前端的簡單 HTML 頁

<HTML>
<BODY bgcolor="Teal">
<br/>
<p align="center">
 <font size="5" face="Arial" color="white"><b>
 SOAP method invocation demo </b></font>
</p>
<hr/>
<font face="Arial" color="whitesmoke" size="3">
<br/><b>
 Click any of the method name to execute.<br/>
 1. Get the List of all Models that we manufacture....
  <a href="execute.jsp?index=1">
  <font color="orange"> GetListOfModels </font></a> <br/>
 2. Get the Price of any particular model......................
  <a href="operation.html">
  <font color="orange"> GetPrice </font></a>
</b>
</BODY>
</HTML>

Operation.html(清單 23)將詢問客戶提供方法調用所需的參數(shù)。

清單 23:根據他或她所選擇的方法給予客戶一個 GUI

<HTML>
<BODY bgcolor="Teal">
<br/>
<p align="center">
<font size="5" face="Arial" color="white"><b>
 GetPrice Operation input Form </b>
</font></p>
<hr/>
<p align="center">
<form action="execute.jsp" method="POST">
<input type="hidden" name="index" value="0">
<table textColor="white">
<tr><td>
<font color="whitesmoke"><b>Description :</b></font>
</td><td><font color="whitesmoke">
 Method GetPrice is used to Get Price of given Model Number</font>
</td></tr>
<tr><td>
<font color="whitesmoke"><b>Parameter(s)</b></font></td><td>
</td></tr>
<tr><td><font color="whitesmoke">Model Number </td></font>
<td><font color="whitesmoke">
 <input type="text" name="parameter" size="30">
 (required) </font>
</td></tr>
<tr><td>
 </td><td><input type="Submit" value="Invoke">
</td></tr>
</font>
</table>
</form>
</p>
</BODY>
</HTML>

Execute.jsp(清單 24)包含了所有的令人感興趣的代碼。它檢測所調用的方法和所傳遞的參數(shù)。然后發(fā)送給遠程服務器一個方法調用。

清單 24:檢測方法并發(fā)送給遠程服務器一個調用

<%@ page language="java" import="java.util.Vector" %>
<%@ page import="java.net.MalformedURLException, java.net.URL" %>
<%@ page import="java.util.Vector" %>
<%@ page import="org.apache.soap.SOAPException,
  org.apache.soap.Constants" %>
<%@ page import="org.apache.soap.rpc.Call, org.apache.soap.rpc.Response,
  org.apache.soap.rpc.Parameter" %>
<%@ page import="org.apache.soap.transport.http.SOAPHTTPConnection" %>
<%@ page import="org.apache.soap.Fault" %>

<HTML>
<BODY bgcolor="Teal">
<br/>
<p align="center">
<font color="whitesmoke">
<%
 boolean isParameter = false ;
 SOAPHTTPConnection soapTransport = new SOAPHTTPConnection();

 // Address of the remote server.
 // Normally this should be dynamically passed and detected.
 // We have hard coded it only for demonstration.
 URL url = new URL ("http://localhost:8080/soap/servlet/rpcrouter");

 // Build the call.
 Call call = new Call ();
 call.setTargetObjectURI ("urn:MobilePhoneservice");
 call.setSOAPTransport (soapTransport);
 call.setEncodingStyleURI(Constants.NS_URI_SOAP_ENC);

 // We'll detect which method user selected
 // and give a call accordingly.
 // We'll pass parameters if present.

 if (request.getParameter("parameter")!=null)
 isParameter = true;

 if (request.getParameter("index").equals("0"))
 {
  call.setMethodName("getPrice");
  Vector params = new Vector();
  String message = new String (request.getParameter("parameter"));
  params.addElement (new Parameter("message", String.class,
  message , null));
  call.setParams(params);
 }
 else
  call.setMethodName("getListOfModels");

 Response resp = call.invoke ( url, /* actionURI */ "" );
 out.println("<p align=left>
 <font size="4" face="Arial" color="white">
 Response of [ "+call.getMethodName()+" ]
 </font><hr/>");
 
 // Check the response.
 if (resp.generatedFault ()) {
  Fault fault = resp.getFault ();
  out.println("<b>Fault is:</b>"+ fault.getFaultCode ()
  +" ["+fault.getFaultString ()+"]");

 } else {
  Parameter result = resp.getReturnValue ();
  out.println("<b>Response is: </b>"+ result.getValue ()+"");
 }
%>
<font>
</p>
</BODY>
</HTML>

 為了運行此應用程序,您需要兩臺 Apache SOAP 服務器。一臺服務器將用來與用戶通信并托管清單 22、23 和 24。另一臺服務器(也稱為遠程服務器)就是我們需要部署第 1 部分所講的基于 WSDL 服務的地方(在前一節(jié)描述,“在 SOAP 服務器上基于 WSDL 服務的部署”)。僅僅是為了演示,遠程服務器的地址 http://localhost:8080/soap/servlet/rpcrouter 已經硬編碼在 Execute.jsp(清單 24)中。在實際操作中您可以從 WSDL 文件中讀取它。

SOAP 中的簡單與復合數(shù)據類型

在此節(jié)中,我將從解釋簡單與復合數(shù)據類型的不同開始。然后展示如何在 SOAP 中對它們編碼。

簡單類型包括字符串、浮點數(shù)、整數(shù)、枚舉等。例如一部手機的“name”的數(shù)據類型就是“string”。復合類型由簡單類型組成但只代表一個實體。例如,“Student”類型記錄可以有不同的屬性,如“studentName”屬于類型“string”,“studentRollNumber”屬于類型“int”但都只代表一個實體“Student”。

清單 25 包含了一個名稱為“Mobile”的復合數(shù)據類型。您會在后面的 SOAP 請求中用到。

清單 25: “Mobile”類型的模式定義結構

1<? xml version="1.0" ?>
2<xsd:schema xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
3  xmlns:xsd="http://www.w3.org/1999/XMLSchema">
4  targetNameSpace= "
www.mobilephoneservice.com/phonequote">
5 <xsd:element name ="Mobile">
6 <xsd:complexType>
7  <xsd:element name="modelNumber" type="xsd:int">
8  <xsd:element name="modelName" type="xsd:string">
9  <xsd:element name="modelWeight" type="xsd:int">
10  <xsd:element name="modelSize" type="xsd:int">
11  <xsd:element name="modelColor">
12   <simpleType base="xsd:string">
13   <enumeration value="white" />
14   <enumeration value="blue" />
15   <enumeration value="black" />
16   <enumeration value="red" />
17   <enumeration value="pink" />
18   </simpleType>
19  </xsd:element>
20 </complexType>
21 </xsd:element>
22</xsd:schema>

在清單 25 中的第 5 行展示了我們的類型名稱(Mobile),而第 6 行說明它是復合數(shù)據類型。因復合數(shù)據類型有屬性,所以在第 7 行到第 12 行展示了定義為子元素的“Mobile”數(shù)據類型的屬性。

第 7 行聲明的元素展示了“Mobile”類型有一個名稱為“modelNumber”的屬性且其類型為“int”(也就是說,“modelNumber”只能采用整數(shù)值)。類似的,第 9 行和第 10 行聲明的元素具有同樣的類型但有不同的屬性名稱。在第 8 行定義的元素具有名稱為“modelName”的屬性且其類型是“string”。

第 11 行的元素因有位于第 12 行的、名稱為“simpleType”的子元素,所以需要更好的理解。這里您在復合類型 Mobile 中定義了一個簡單類型。simpleType 的名稱為“modelColor”且它的類型是“enumeration”。它有一個屬性“base”具有的值為 "xsd:string",這表明簡單類型“modelColor”具有在 SOAP 模式中定義的類型“string”的功能。在第 13 行到第 17 行中的每一個 <enumeration> 標記都具有一個屬性:“value”("white" "blue"、 "black"、 "red" 和 "pink")。枚舉類型使我們能夠從多項選項中選擇一個值。

在 SOAP 請求中使用復合數(shù)據類型

清單 26 演示了在 SOAP 請求中復合類型的使用。它展示了一個在 Body 元素中的攜帶請求的 Envelope,在 Body 元素中,您正調用“m”名稱空間的 addModel 方法。清單 26 使用數(shù)據類型“Mobile”,此數(shù)據類型在清單 25 中定義。

AddModel 方法攜帶一個類型為“Mobile”的參數(shù)。我們以“msd”名稱空間引用來引用“Mobile”結構。請參閱清單 26 的 <SOAP-ENV:Envelope> 元素中的 "xmlns:msd" 聲明。這是一個在 SOAP 請求中使用用戶定義數(shù)據類型的示例。

清單 26:實現(xiàn)在清單 25 中定義的“Mobile”結構

1 <SoAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
2 xmlns:xsd="http://www.w3.org/1999/XMLSchema"
3 xmlns:msd="
www.mobilephoneservice.com/phonequote">
4 <SOAP-ENV:Body>
5  <m:addModel xmlns:m="
www.mobilephoneservice.com">
6  <msd:Mobile>
7   <modelNumber>1</modelNumber>
8   <modelName>mlr97</modelName>
9   <modelWeight>10</modelWeight>
10   <modelSize>4</modelSize>
11   <modelColor>white</modelColor>
12  </msd:Mobile>
13  </m:addModel>
14 </SOAP-ENV:Body>
15<SOAP-ENV:Envelope>

 總結

在這一部分中,您已經學習了 SOAP 語法、請求、響應、HTTP 綁定和使用電子郵件的 SOAP 使用。您也了解了服務于 Apache SOAP 客戶機的 Apache SOAP 服務器。最后,我簡述了用戶定義數(shù)據類型的主題,它是一個需要我們仔細學習的高級主題。在此系列文章的下一部分,您會學習更多的用戶定義數(shù)據類型示例。我還會檢驗 SOAP 的互操作性(也就是說,怎樣使來自不同供應商的 SOAP 實現(xiàn)相互協(xié)調)。

參考資料

  • 請單擊在此文章頂部或底部的討論來參加關于此文章的討論論壇
  • 簡單對象訪問協(xié)議(SOAP) 1.1 是 W3C SOAP 的正式規(guī)范。
  • 此系列文章的第 1 部分:用 WSDL 部署 Web 服務
  • 一篇有趣的 XML.Com 上的 SOAP 文章。
  • 一篇對 SOAP 基礎知識的介紹。
  • Scribner, Kenn 等的“Understanding SOAP” ,Sams。
  • Bequet, Henry 的“Professional Java SOAP”,Wrox。
  • 自 Apache's Web 站點下載本文所用到的 Apache SOAP 工具箱。

關于作者

Bilal Siddiqui 是一位 XML 顧問。自 1995 年畢業(yè)于 Lahore 工程技術大學電子工程專業(yè)后,他開始為工業(yè)控制系統(tǒng)設計軟件解決方案。后來他轉到了 XML 并用自己 C++ 的編程經驗來構建基于 Web 和 WAP 的 XML 處理工具、服務器端的解析解決方案和服務應用程序。您可以通過
wap_monster@yahoo.com 發(fā)電子郵件給 Bilal 來索取本文中包含的代碼文件的拷貝。

瀏覽:使用WSDL部署Web服務,第1部分:Web服務和WSDL簡介

發(fā)布:2007-03-25 13:26    編輯:泛普軟件 · xiaona    [打印此頁]    [關閉]
相關文章:
石家莊OA系統(tǒng)
聯(lián)系方式

成都公司:成都市成華區(qū)建設南路160號1層9號

重慶公司:重慶市江北區(qū)紅旗河溝華創(chuàng)商務大廈18樓

咨詢:400-8352-114

加微信,免費獲取試用系統(tǒng)

QQ在線咨詢