帳號:
密碼:
最新動態
產業快訊
CTIMES / 文章 /
剖析WSDL的架構與實作
 

【作者: 姚巧玫、胡百敬】   2004年12月01日 星期三

瀏覽人次:【6502】

WSDL 1.0(Web Services Description Language 1.0)是在2000年9月發表,用以取代Microsoft先前提出的SCL(SOAP Contract Language,SCL)與IBM倡導的NASSL,它用一種和具體程式語言無關的抽象方式定義Web服務(Web Service)呼叫和回應有關的操作和訊息。


WSDL 2.0協定目前已經被提交給網際網路標準組織W3C(World Wide Web Consortium)審查,目前還處於「草案」狀態i。SOAP1.1與WSDL1.1目前在網際網路標準組織W3C的規範屬性均屬Notes狀態,WSDL 1.2才是真正由W3C主導的規範,但目前仍在草案階段,草案版也已在網際網路標準組織W3C網站中可以查詢到。


W3C維持著正規的標準化系統同時,提交提案必須經過確定的一套批准過程才能最終成為官方協議。由於網路服務與平台的提供者,如微軟、IBM、昇陽...等,有責任將欲提供的Web服務利用本規範製作成為一個WSDL文件,而製作的過程可藉由許多它們所支援的工具來協助完成。因此,雖然規格尚未成為標準,但我們已經可以透過.NET、Java等不同平台上的開發工具來建立Web服務,而這些平台也都可以產生彼此理解的服務規格描述:WSDL。


WSDL的本質

WSDL(Web Service Description Language)是以XML的XSD格式撰寫而成,由於XML是極為嚴謹的語言,如此一來可減少錯誤的產生。Web服務在本質上應可與其他不同的協定共同運作,惟在現階段WSDL 1.1規範中是以SOAP、HTTP GET/POST及MINE運作為主。用來描述服務的提供者提供了哪些服務,正確的資料傳遞格式,以及如何存取這些服務。


就其定義來說,不能僅僅把WSDL當作一種物件介面定義語言,例如,CORBA或COM等應用程式結構就會用到物件介面定義語言IDL(Interface Description Language)。WSDL保持協定中立,但它確實內建了對SOAP通訊協定的支持,從而與SOAP建立了不可分割的聯繫。利用WSDL的服務描述語言可清楚地定義溝通介面與位置,然後透過SOAP通訊協定,便可以將使用者端與Web服務呼叫往返的訊息包裝成XML格式的文件。


此外,它也包含了以往COM世界IDL的功能。當前端使用者要存取這個服務時,需要了解呼叫服務會用到哪些型別、有哪些函數可以呼叫、函數的參數型別、回傳資料型別、透過什麼樣的協定可以存取、以及在哪裡可以取得服務等等,這些都是WSDL需要描述的。簡單的說,WSDL就是用來描述一個Web服務能做什麼?位置在哪?如何呼叫?


WSDL重要性

為什麼需要WSDL?這的確是個好問題。想像一下以下沒有WSDL的情形,每當我們要使用一個Web服務時,就利用E-mail或電話詢問提供服務的廠商該如何使用網路上的服務,若是每家提供服務的廠商沒有固定存取資料的格式,則會有更多無法預期的狀況發生,因為即使我們依照所給的資料來使用Web服務,也都會有可能發生無法預期的錯誤,例如,某個產品的編號是13579,別以為它是一個數值型態的資料,實際上它卻是一個字串型態的資料,在這種情況之下,錯誤就因此而產生了;除了細節的處理問題外,最主要的困難仍是不方便及不標準制式化。


WSDL具有可延伸性,可透過名稱領域(namespace)的定義拓展其應用,無論使用者採行何種網路協定與訊息格式,WSDL皆可描述其端點(end point)與訊息。WSDL會要求傳送的訊息應該包含那些資訊,以及回應的訊息應該使用那種方式,再加上目前大部分的WSDL檔案都可以由應用程式或執行平台來產生,所以對服務提供者來說,將可省去撰寫WSDL檔案的麻煩,而對服務需求者而言,也可由開發工具來讀入WSDL檔案,然後產生使用Web服務時所需的代理程式。


WSDL檔案在服務導向架構中的定位及關係可以由(圖一)來闡釋,透過WSDL檔案,服務需求者可以知道如何使用這個Web服務,但前提是Web服務提供者必須要提供這個WSDL檔案才行。也就是說,當服務提供者對外公佈它所提供的網路服務時,它必須先建立一個描述Web服務的WSDL檔案,然後在註冊Web服務到UDDI註冊中心的同時,也一併將這個WSDL檔案予以註冊。如此一來,服務需求者在經由UDDI註冊中心取得網路服務資訊時,也能夠同時取得用來描述此網路服務的WSDL檔案。無論三者間是何種作業,彼此溝通的方式都是使用SOAP協定。WSDL不僅只是描述網路服務,它也肩負提供資訊給服務需求者在服務請求中的SOAP內容及UDDI註冊中心的部份資訊,因此WSDL還涉及了綿密的解譯及對應架構。


《圖一 Web Service的基本功能》
《圖一 Web Service的基本功能》

WSDL定義、架構

Web服務描述語言的架構是由XML語言所組成,藉由XML Schema來界定文件內的元素、屬性等資料,進而達成「描述」Web服務(應用程式)之目的。WSDL文件將網路服務定義為服務的端點(end point)或埠(port)的集合,亦即實際執行應用程式的位置,在XML Schema中使用六個主要元素,如(圖二)


  • 1.資料類型集(Types):定義訊息交換時,會用到的資料型別。


  • 2.訊息(Message):描述需要溝通的訊息。


  • 3.介面定義(Port Type):一組操作行為,以及該行為會用到的訊息。


  • 4.服務鏈結(Binding):定義不同行為實際溝通的協定細節,以及如何把前述抽象的訊息結構化為實體的傳輸格式。除此之外,在這個部分,也可以定義如果執行中,出現錯誤時,應該如何回應!


  • 5.服務端點(Port):binding與網路位置合起來定義的端點(end point)


  • 6.實作服務(Service):將相關的port群組在一起。



《圖二 WSDL文件主要組成元素的分類》
《圖二 WSDL文件主要組成元素的分類》

圖二的右側是說明WSDL內六個主要元素的排列,其中前四個元素相當於「介面描述」,後二個元素則相當於「執行描述」。也可以說WSDL的六個主要元素其實可大分為介面描述與執行描述兩項,接著我們分別就介面描述及執行描述的順序說明六個主要元素。WSDL文件以元素<definitions>為XML根節點(Root Element),而WSDL文件的基本結構如下:



<definitions命名空間的定義>

<types>
  types 的定義...
</types>

<message>
  messages 的定義...
</message>

<portType>
  port 的定義...
</portType>

<binding>
  binding 的定義...
</binding>

<service>
  <port 指定 binding>
    指定端點
  <port>
</service>

</definitions>

另外,繼承了XML本身的特色,WSDL文件也可以包含其他延伸的元素。而service元素讓它可以群組多個web服務的定義放在單一的WSDL文件中。


WSDL實做範例

以下就簡單地描述一個Web服務所對應的WSDL,而筆者透過Visual Basic.NET所撰寫的Web服務程式範例定義如下:



Imports System.Web.Services
Imports System.Xml.Serialization
<XmlRoot("Employee")>_
Public Class Employee
    '前端所看到的Employee物件屬性將是LName,FName
    'Title而不是LastName,FirstName,Title
    <XmlElement("LName")> Public LastName As String
    <XmlElement("FName")> Public FirstName As String
    <XmlElement("Title")> Public Title As String
End Class
<WebService(Namespace:="http://myDemo/")>
Public Class Service1
    Inherits WebService
    <WebMethod()> Public Function GetEmployee( _
    ByVal intI As Integer) As Employee
        Dim emp As New Employee()
        emp.LastName = "胡"
        emp.FirstName = "百敬"
        emp.Title = "顧問"
        Return emp
    End Function
End Class

這個程式碼列表(1)描述回傳物件結構的Web Service。


當我們透過ASP.NET撰寫如程式碼列表(1)的Web服務後,對應上述的六大部分,檢視.NET Framework為該Web服務自動建立的WSDL如下。因為透過ASP.NET/.NET Framework 1.0所撰寫的Web服務自動支援三種叫用方式:SOAP、HTTP GET、HTTP POST,所以WSDL同一類的資料大都有為三種存取方式撰寫不同的描述,但.Net Framework 1.1預設把HTTP GET/POST方法停用了,你需要自行到machine.config內啟動Web服務對HTTP GET/POST溝通協定的支援。筆者在此處故意要有三種協定的Web服務溝通方式,讓你可以對WSDL的內容有一個比較:


首先是根元素<definitions>:



<definitions xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:s0="http://myDemo/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" targetNamespace="http://myDemo/" xmlns="http://schemas.xmlsoap.org/wsdl/">

在根元素中,可以看到大量以下各元素可能會用到的命名空間。在根元素之後的是<types>元素。接著是定義傳入傳出哪些資料型別,因為GetEmployee方法傳入的參數是一個整數,所以types元素內對應的定義如下:



<s:complexType>
  <s:sequence>
    <s:element minOccurs="1" maxOccurs="1" name="intI" type="s:int" />
  </s:sequence>
</s:complexType>

而GetEmployee方法回傳的資料型別是Employee類別,因此描述資料格式如下:



<s:complexType name="Employee">
  <s:sequence>
    <s:element minOccurs="0" maxOccurs="1" name="LName" type="s:string" />
    <s:element minOccurs="0" maxOccurs="1" name="FName" type="s:string" />
    <s:element minOccurs="0" maxOccurs="1" name="Title" type="s:string" />
  </s:sequence>
</s:complexType>

上述的XSD是定義Employee類別經過XML序列化後的結構,你可以與該類別序列化的結果做一個比對,這也就是實際透過SOAP傳遞的物件個體。筆者擷取使用者端程式與Web服務溝通的內容如下所示:


<Employee xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns=http://myDemo/>
  <LName>胡</LName>
  <Fname>百敬</FName>
  <Title>顧問</Title>
</Employee>

types將資料型別分別對應到函數呼叫的參數與回傳資料型別,定義如下:


<s:element name="GetEmployee">
  <s:complexType>
    <s:sequence>
      <s:element minOccurs="1" maxOccurs="1" name="intI" type="s:int" />
    </s:sequence>
  </s:complexType>
</s:element>
<s:element name="GetEmployeeResponse">
  <s:complexType>
    <s:sequence>
       <s:element minOccurs="1" maxOccurs="1" name="Employee" nillable="true" type="s0:Employee" />
    </s:sequence>
  </s:complexType>
</s:element>

其中屬性name與函數同名的是代表輸入參數,如上述的GetEmployee。在函數名稱後加上Response代表的是函數回傳的資料型別,如上述的GetEmployeeResponse。


message元素

types元素所描述的「參數本身的資料結構,搭配上方法的輸出入方向後的資料結構」與傳遞的協定無關。其後可接收的訊息應該也與使用何種協定並無直接關係,但因為用何種協定會影響實際可傳遞的訊息結構,例如以SOAP協定呼叫Web Service時,可以傳遞物件當作輸入參數,但若是以HTTP Get/Post呼叫Web Service,則只能傳遞簡單的資料型別。所以Web Service可用的訊息就被分為好幾種,內容如下:



<message name="GetEmployeeSoapIn">
  <part name="parameters" element="s0:GetEmployee" />
</message>
<message name="GetEmployeeSoapOut">
  <part name="parameters" element="s0:GetEmployeeResponse" />
</message>
<message name="GetEmployeeHttpGetIn">
  <part name="intI" type="s:string" />
</message>
<message name="GetEmployeeHttpGetOut">
  <part name="Body" element="s0:Employee" />
</message>
<message name="GetEmployeeHttpPostIn">
  <part name="intI" type="s:string" />
</message>
<message name="GetEmployeeHttpPostOut">
  <part name="Body" element="s0:Employee" />
</message>

若我們在程式碼列表(1)的GetEmployee函數,輸入的參數是物件型別,例如就是程式碼列表(1)內定義的Employees,則上述有關HttpGet與HttpPost的兩個部分就會消失,因為透過HttpGet和HttpPost呼叫Web Service時,無法傳遞物件當作傳入參數,自然就不會有此訊息。


另外,若詳細一點觀察可以發現Soap的這一組訊息,輸出入的對應都是parameters 元素,資料結構的定義則是我們自定的,所以xsd使用的命名空間是s0,也就是代表在程式碼列表(1)中,我們以WebService Attribute替類別Class1所定義的命名空間http://myDemo/,這個別名的對應是定義在根元素<definitions>上。


而HttpGet或HttpPost在傳入參數時,只能用簡單的資料型態,透過對應到命名空間http://www.w3.org/2001/XMLSchema的s,可以知道這些簡單資料型別是W3C定義的。而它們回傳的內容可以是資料節構,所以是“s0:Employee”,並放在Http封包的Body部分。


portType元素

在服務接口(port Type)中,主要是定義各項Web服務抽象邏輯上的操作行為,以及該行為用到的訊息。主要是資料輸入與資料輸出定義。WSDL規格上四種端點訊息溝通模式定義如下:


  • ●接受服務(one-way):使用端點接收訊息


  • ●尋求/回應(request/response):端點接受訊息、並送出相關訊息


  • ●請求/回應(solicit/response):端點送出訊息、並接收相關服務


  • ●通知(notification):使用者送出訊息



雖然規格上描述了四種訊息往返的模式,但一般來說我們撰寫的Web服務方法只有前兩種,也就是使用者端呼叫,但沒有傳回值,以及使用者端呼叫後,該方法有傳回值。


Web服務的提供者一次可以提供多種Web服務,同一個Web服務可以支援多種協定讓前端程式存取。這裡描述每一種協定存取該Web服務時,可以用哪一種前述的Message,因此這個元素也等於在定義邏輯的通訊埠(port)。上述程式碼列表1的因為是一般的函數,所以port Type元素的範例採用的是「尋求/回應」模式如下:



<portType name="Service1Soap">
  <operation name="GetEmployee">
    <input message="s0:GetEmployeeSoapIn" />
    <output message="s0:GetEmployeeSoapOut" />
  </operation>
</portType>
<portType name="Service1HttpGet">
  <operation name="GetEmployee">
    <input message="s0:GetEmployeeHttpGetIn" />
    <output message="s0:GetEmployeeHttpGetOut" />
  </operation>
</portType>
<portType name="Service1HttpPost">
  <operation name="GetEmployee">
    <input message="s0:GetEmployeeHttpPostIn" />
    <output message="s0:GetEmployeeHttpPostOut" />
  </operation>
</portType>

假若你所撰寫的Web Service內某個方法傳入的參數是物件型別,則HttpGet和HttpPost兩個呼叫方式無法支援,在其內的operation子元素就不會出現該方法。operation元素下的input和output所指定的message,則是在前一個message區段所定義的message元素。


binding元素

定義完邏輯的聯絡埠後,接著要定義每個埠的實體存取方式,也就是透過不同協定要實際存取到該服務時,所需的細節內容。範例如下:



<binding name="Service1Soap" type="s0:Service1Soap">
  <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" />
  <operation name="GetEmployee">
    <soap:operation soapAction="http://myDemo/GetEmployee" style="document" />
    <input>
      <soap:body use="literal" />
    </input>
    <output>
      <soap:body use="literal" />
    </output>
  </operation>
</binding>
<binding name="Service1HttpGet" type="s0:Service1HttpGet">
  <http:binding verb="GET" />
  <operation name="GetEmployee">
    <http:operation location="/GetEmployee" />
    <input>
      <http:urlEncoded />
    </input>
    <output>
      <mime:mimeXml part="Body" />
    </output>
  </operation>
</binding>
<binding name="Service1HttpPost" type="s0:Service1HttpPost">
  <http:binding verb="POST" />
  <operation name="GetEmployee">
    <http:operation location="/GetEmployee" />
    <input>
      <mime:content type="application/x-www-form-urlencoded" />
    </input>
    <output>
      <mime:mimeXml part="Body" />
    </output>
  </operation>
</binding>

在上方SOAP的區段內,定義了HTTP表頭內的SOAP Action項目的內容是http://myDemo/GetEmployee,資料內容編碼的方式是document而非rpc,參數編碼的方式literal而非encodedii。相對於HTTP Get方式的存取,HTTP所使用的動詞是GET而非POST,參數傳遞的方式要經過url編碼。當然你可以將HTTP GET與POST的區段做一個比較,就可以大概了解binding元素要描述的內容。


service元素

提供上述各存取協定邏輯埠,實際要存取Web服務的端點(endpoint),主要是說明如何進行由服務介面所提供的服務,包括提供服務的名稱、內容及服務的網路位置等。



<service name="Service1">
  <port name="Service1Soap" binding="s0:Service1Soap">
    <soap:address location="http://localhost/GetWSDL/Service1.asmx" />
  </port>
  <port name="Service1HttpGet" binding="s0:Service1HttpGet">
    <http:address location="http://localhost/GetWSDL/Service1.asmx" />
  </port>
  <port name="Service1HttpPost" binding="s0:Service1HttpPost">
    <http:address location="http://localhost/GetWSDL/Service1.asmx" />
  </port>
</service>

結論

上述文件中,實體的端點,也就是以port元素描述是採用哪一種溝通方式,就直接以name屬性指定之前port Type元素內所定義的埠名稱,而binding屬性則指定之前binding元素所定義與通訊協定相關的連線細節。而address元素則指定實體存取的路徑。


綜合以上各段,若提供的Web Service可以用不同的方式存取,如ASP.NET所提供的Web Service預設可以用SOAP、HTTP Get和HTTP Post三種方式存取,則所提供的服務會參照到三種邏輯連接的埠(port Type)定義,每個埠有不同的連結細節(binding),邏輯埠可以傳遞不同的訊息(message),每種訊息包含不同的資料型態(types)。


延 伸 閱 讀
WSDL 1.0依其功能與應用詳述說明。相關介紹請見「WSDL 1.0延伸資料 」一文。
WSDL 2.0功能與應用舉例詳述說明。你可在「WSDL 2.0延伸資料」一文中得到進一步的介紹。
針對rpc/document和literal/encoded 之間的差異加以說明。在「rpc/document、literal/encoded的差異 」一文為你做了相關的評析。
相關組織網站

WSDL官方網站

W3C官方網站

昇陽公司網站
相關文章
氫能競爭加速,效率與安全如何兼得?
智慧製造移轉錯誤配置 OT與IT整合資安防線
創新光科技提升汽車外飾燈照明度
以模擬工具提高氫生產燃料電池使用率
眺望2025智慧機械發展
comments powered by Disqus
相關討論
  相關新聞
» 施耐德電機響應星展銀行ESG Ready Program 為台灣打造減碳行動包
» 台達推出5G ORAN小型基地台 實現智慧工廠整合AI應用
» 歐洲航太技術展在德國盛大展開,全球吸睛 鐳洋推出衛星通訊整合方案,目標搶佔龐大的歐洲衛星商機
» 經濟部促成3GPP大會來台爭話語權 大廠共商5G/6G技術標準
» 經濟部支持跨國研發有成 台歐雙方分享B5G~6G規劃


刊登廣告 新聞信箱 讀者信箱 著作權聲明 隱私權聲明 本站介紹

Copyright ©1999-2024 遠播資訊股份有限公司版權所有 Powered by O3  v3.20.2048.18.119.162.226
地址:台北數位產業園區(digiBlock Taipei) 103台北市大同區承德路三段287-2號A棟204室
電話 (02)2585-5526 #0 轉接至總機 /  E-Mail: webmaster@ctimes.com.tw