WSDL——Web Service Description Language

來源:互聯網
上載者:User

讓我們來看一個樣本WSDL檔案的結構及工作原理。請注意這隻是一個十分簡單的WSDL文檔執行個體。我們的目的只是簡單展示下最顯著的特徵,後面的章節有對其詳細的討論。

<?xml version="1.0" encoding="UTF-8" ?> <definitions name="FooSample" targetNamespace="http://tempuri.org/wsdl/" xmlns:wsdlns="http://tempuri.org/wsdl/" xmlns:typens="http://tempuri.org/xsd" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:stk="http://schemas.microsoft.com/soap-toolkit/wsdl-extension" xmlns="http://schemas.xmlsoap.org/wsdl/"><types> <schema targetNamespace="http://tempuri.org/xsd" xmlns="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" elementFormDefault="qualified" > </schema></types><message name="Simple.foo"> <part name="arg" type="xsd:int"/> </message><message name="Simple.fooResponse"> <part name="result" type="xsd:int"/> </message><portType name="SimplePortType"> <operation name="foo" parameterOrder="arg" > <input message="wsdlns:Simple.foo"/> <output message="wsdlns:Simple.fooResponse"/> </operation></portType><binding name="SimpleBinding" type="wsdlns:SimplePortType"> <stk:binding preferredEncoding="UTF-8" /> <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>  <operation name="foo"><soap:operation soapAction="http://tempuri.org/action/Simple.foo"/><input> <soap:body use="encoded" namespace="http://tempuri.org/message/" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /></input><output> <soap:body use="encoded" namespace="http://tempuri.org/message/" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /></output> </operation> </binding><service name="FOOSAMPLEService"> <port name="SimplePort" binding="wsdlns:SimpleBinding"> <soap:address location="http://carlos:8080/FooSample/FooSample.asp"/>  </port> </service> </definitions>

下面只是對該WSDL文檔的預覽:

        第一行定義了該文檔是一份XML文檔。儘管這一行不是必需的,但這一行有助於XML解析器對WSDL文檔進行解析。

        第二行定義了WSDL文檔的根項目:<definitions>並有一些命名空間屬性定義在根項目內,就與<types>的子項目<schema>類似。

        <types>元素組成了類型段。當沒有資料類型要定義時,該段可能被忽略。在樣本WSDL中,該段中沒有特定於應用程式的資料類型定義,但還是使用了類型段,只是用於定義在該文檔中使用的schema命名空間。

        <message>元素組成訊息段。如果你將一個操作比作函數,那麼<message>元素則定義了函數的所有參數。每個<message>的<part>子項目與參數相對應。輸入參數在獨立的<message>元素中定義,與輸出參數隔離,輸出參數定義在自己的<message>元素中。輸出參數<message>元素的name屬性以“Response”結尾,用於與輸入參數進行區分。每一個<part>元素都有name和type屬性,就像函數的參數具有類型和名稱類似。<part>元素的type屬性值可以是XSD基本類型,SOAP定義的類型,WSDL定義的類型或類型段定義的類型。

        在PortTypes段中可以定義零個,1個或多個<portType>元素。可以不包含該段的原因是該段可以定義在獨立的WSDL文檔中。樣本中只包含了一個<portType>元素。<portType>元素可以通過<operation>子項目定義一個或多個操作。樣本只包含一個<operation>元素,名稱為“foo”。這個名稱就相當於函數名。<operation>元素可以包含一個,兩個或三個子項目:<input>,<output>,<fault>,這三個子項目中的message屬性值與訊息段中的<message>元素相對應。樣本中的整個<portType>元素就相當於C語言中int
foo(int arg);函數的定義。

        在Binding段中可以定義零個,1個或多個<binding>元素。它的功能是指定每個<operation>請求和響應如何通過網路傳輸。

        在Services段中可以定義零個,1個或多個<service>元素。<service>元素包含<port>子項目並與Binding段中的<binding>元素相對應。

命名空間

        根項目<definitions>和子項目<schema>都有namespace屬性。

        每個namespace屬性定義了每個應用在文檔中namespace的縮寫。例如:“xmlns:xsd”為http://www.w3.org/2001/XMLSchema命名空間定義了xsd縮寫。定義後就可以在以後的文檔中使用縮寫來代表完整的命名空間。

        什麼是命名空間?命名空間的使用是為了避免名字衝突。如果我建立了一個web Service並在WSDL檔案中包括了一個name屬性為foo的元素。你準備將這個服務與另一個服務一起使用,如果沒有命名空間,則另一個服務中就不能在其WSDL檔案中包括“foo”名稱。每個服務能使用相同的名字只有當這些名字在相同的執行個體中表示同一個意思。使用不同的命名空間,我自己的服務中“foo”名字可以與另一個服務中相同的名字表示不同的意思。

        屬性targetNamespace定義了一個命名空間,所有在元素中的名稱都屬於這個命名空間。在樣本檔案中,根項目<definitions>的targetNamespace屬性定義為http://tempuri.org/wsdl/。即所有定義在該文檔中的名稱都屬於這個命名空間。<schema>元素有自己的targetNamespace屬性,值為http://tempuri.org/xsd,所有定義在<schema>元素中的名字都屬於這個命名空間而非上層的命名空間。

        <schema>元素的下一行中定義了預設的命名空間(xmlns="http://www.w3.org/2001/XMLSchema"),所有未經限定的名稱都屬於這個命名空間。

SOAP訊息

        一種查看WSDL檔案的方法:用戶端和伺服器端使用該檔案,該檔案決定了網路上傳輸的資料內容。儘管SOAP使用底層的IP或HTTP協議,但應用程式決定了高層在客戶和伺服器端所使用的協議。換句話說,給定一個操作叫“echoInt”,執行簡單的返回輸入的整型操作,參數的數量,每個參數的類型以及參數在網路中如何傳輸(serialization)組成了應用程式規定的協議。這樣的協議可以由多種方式進行指定,但我相信最好的方法是使用WSDL。如果我們通過這種方法重新審視WSDL,則其不僅是“介面契約”,而且還是一個協議定義語言。

        WSDL可以定義SOAP訊息是否遵循rpc或document格式。一個rpc-style訊息,像樣本檔案中定義的,就像一個帶有零個或多個參數的函數調用。一個document-style訊息則更平面化且只需要少量的嵌套層次。下面的XML訊息是使用SoapClient object in MS SOAP Toolkit 2.0對同一個WSDL檔案解析後發送和接收的結果。

        從用戶端發起一個函數調用“foo(5131953)”:

<?xml version="1.0" encoding="UTF-8" standalone="no"?> <SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Body><m:foo xmlns:m="http://tempuri.org/message/"> <arg>5131953</arg> </m:foo> </SOAP-ENV:Body></SOAP-ENV:Envelope>

        從伺服器端接到響應:

<?xml version="1.0" encoding="UTF-8" standalone="no"?> <SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Body> <SOAPSDK1:fooResponse xmlns:SOAPSDK1="http://tempuri.org/message/"><result>5131953</result></SOAPSDK1:fooResponse></SOAP-ENV:Body> </SOAP-ENV:Envelope>

        函數調用的訊息及其返回的訊息都是有效XML。一個SOAP訊息包括一個<Envelope>元素,該元素包括可選的<Header>元素及最少一個<Body>元素。發送和接收訊息在<Envelope>元素都有單個的<Body>元素。rpc功能調用訊息體有一個“foo”操作名,同時返回訊息體中包括了“fooResponse”元素。foo元素只有一個子項目<arg>,它代表單個參數,在樣本WSDL檔案中描述。同樣fooResponse元素也有一個<result>子項目。

XML Schema在WSDL類型和訊息段

        WSDL的資料類型是基於“XML Schema:Datatypes”(XSD)也是W3C所推薦的。XSD文檔有三個不同的版本(1999, 2000/10, and 2001),將其申明在<definitions>元素的一個nameSpace屬性中,指定在特殊WSDL檔案中所使用的版本。

        xmlns:xsd="http://www.w3.org/2001/XMLSchema"

Prefix Equivalent Namespace Description
soapenc http://schemas.xmlsoap.org/soap/encoding SOAP 1.1 enc
wsdl http://schemas.xmlsoap.org/wsdl/soap WSDL 1.1
xsd http://www.w3.org/2001/XMLSchema XML Schema

        XSD定義了兩類內建類型:基本和繼承,具體的參見:http://www.w3.org/TR/2001/PR-xmlschema-2-20010330

複雜類型

        XML Schema允許定義複雜類型,在C語言中則用struct來表示。例如,定義下面C struct:

typedef struct { string firstName; string lastName; long ageInYears; float weightInLbs; float heightInInches;} PERSON;

        使用XML Schema來表示:

<xsd:complexType name="PERSON"> <xsd:sequence><xsd:element name="firstName" type="xsd:string"/><xsd:element name="lastName" type="xsd:string"/> <xsd:element name="ageInYears" type="xsd:int"/> <xsd:element name="weightInLbs" type="xsd:float"/> <xsd:element name="heightInInches" type="xsd:float"/></xsd:sequence> </xsd:complexType>

        但是<complexType>能夠表達C struct所不能表達的功能。除了<sequence>子項目還允許其它的子項目。可以使用<all>子項目來代替<sequence>:

<xsd:complexType name="PERSON"> <xsd:all><xsd:element name="firstName" type="xsd:string"/><xsd:element name="lastName" type="xsd:string"/> <xsd:element name="ageInYears" type="xsd:int"/> <xsd:element name="weightInLbs" type="xsd:float"/> <xsd:element name="heightInInches" type="xsd:float"/></xsd:all> </xsd:complexType>

        當<all>子項目出現時,表示其內部的子項目可以以任意的順序出現且每個子項目都是可選的。這就不太像C struct了。

<portType>和<operation>元素

        一個portType定義了若干個operation。在portType中的operation元素定義了該portType中所有方法調用的文法。每一個operation元素定義了方法名,參數(使用<message>元素)以及每個參數的類型(<message>中定義的<part>元素)。

        一個WSDL文檔中可以有多個<portType>元素。每組<portType>包含了一組相關的操作。

        在<operation>元素中,只能出現一個<input>,一個<output>,一個<fault>元素,每個元素都有name和message屬性。

        <input>,<output>,<fault>三個元素的name屬性有何作用呢?它的作用是用來對相同操作名進行區分(重載)。

<binding>和<operation>元素

        Binding段是用來對傳輸中的協議,序列化和編碼進行全面的定義。因此,Types,Message和Port Type段用來處理抽像的資料內容,Binding段則用來定義傳輸過程中物理細節。

        將binding規範從資料及訊息中分離表示服務提供者們如果使用相同的業務類型可以將其標準化到一組操作中(portType)。每一個提供者可以根據自己的要求對binding進行定製。這就有助於將抽像的定義(types, message, portType)從WSDL文檔中分離出並定義到獨立的文檔中,所有的商務規則相同的服務提供者使用相同的抽像定義,而對binding進行定製。例如:銀行可以定義一組標準的銀行操作並定義到一個抽像的WSDL文檔中,而各個銀行可以對使用協議,序列化和編碼進行定製。

        從樣本中提取的binding段:

<binding name="SimpleBinding" type="wsdlns:SimplePortType"> <stk:binding preferredEncoding="UTF-8" /> <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>  <operation name="foo"><soap:operation soapAction="http://tempuri.org/action/foo1"/> <input name="foo1"> <soap:body use="encoded" namespace="http://tempuri.org/message/" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /></input> </operation> <operation name="foo"><soap:operation soapAction="http://tempuri.org/action/foo2"/> <input name="foo2"> <soap:body use="encoded" namespace="http://tempuri.org/message/" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /></input> </operation> </binding>

        <binding>元素有一個name屬性(樣本中值為“SimpleBinding”),定義這個name是為了在Services段的<port>元素中對其進行引用。type屬性則是對<portType>元素的引用。第二行是MSTK2的擴充元素,<stk:binding>,指定了優先使用的編碼類別型為UTF-8。

        <soap:binding>元素指定了訊息格式(rpc)和transport方式。transport屬性引用一個namespace指定使用HTTP SOAP協議。

        有兩個<operation>元素具有相同的名字“foo”,通過<input>元素的name屬性進行區分,分別為“foo1”和“foo2”。在<operation>元素中的<soap:operation>元素都包括“soapAction”屬性,其值為一個URI。這個URI是由SOAP規範進行指定並使用在SOAP訊息中。SOAP訊息中帶有SOAPAction訊息頭將<soap:operation>元素中的URI作為其值。soapAction屬性只有在HTTP
binding中才需要。該屬性的用法在寫該文檔時並不十分明確。建議的用法是伺服器可以通過這個屬性對訊息進行路由而不需要對所有的訊息進行解析。<soap:operation>還可以有style屬性,該屬性可以對<soap:binding>中的style屬性進行重載。

        <operation>元素可以包含<input>,<output>和<fault>元素,這些元素與portTypes段中的相關元素對應。上面的例子中只有<input>元素。這三個元素中都有一個可選的name屬性,在本例中,用來對相同名稱的操作進行區分。在樣本的<input>元素中是<soap:body>元素,該元素指定了SOAP訊息體的內容。這個元素有以下三個屬性:

                Use:這個屬性指定了資料是否進行了編碼或是字面的意思。字面的意思為SOAP訊息體中的資料格式與抽像定義(Types, messages, portTypes段)完全相同。編碼錶示使用“encodingStyle”屬性值決定了編碼。

                Namespace:每個SOAP訊息體都可以有其自己的命名空間來避免名字衝突。在這個屬性中指定的URI會完全的使用到返回訊息中。

                EncodingStyle:為SOAP編碼,該屬性的URI值為"http://schemas.xmlsoap.org/soap/encoding/"

Document類型的binding

        上一節中,<soap:binding>元素中的style屬性指定的值為“rpc”,當該屬性指定為document時則會改變傳輸中的資料序列,使用文檔傳輸來代替函數簽名。如果使用這種binding方式,則<message>元素中定義了文檔格式而非函數簽名。作為例子,考慮下面的WSDL片段:

<definitions xmlns:stns="(SchemaTNS)" xmlns:wtns="(WsdlTNS)" targetNamespace="(WsdlTNS)"><schema targetNamespace="(SchemaTNS)" elementFormDefault="qualified"><element name="SimpleElement" type="xsd:int"/> <element name="CompositElement" type="stns:CompositeType"/><complexType name="CompositeType"><all> <element name='a' type="xsd:int"/> <element name='b' type="xsd:string"/></all> </complexType></schema><message...> <part name='p1' type="stns:CompositeType"/><part name='p2' type="xsd:int"/> <part name='p3' element="stns:SimpleElement"/> <part name='p4' element="stns:CompositeElement"/></message>...</definitions>

        schema有兩個元素:SimpleElement和CompositElement,後一個類型為CompositeType。唯一的<message>元素定義了四個part:p1,類型為CompositeType;p2,類型為int;p3為SimpleElement以及p4為CompositeElement。下面展示了對由style/use確定的四種binding方式的傳輸格式:

rpc/literal

<operation name="method1" style="rpc" ...> <input> <soap:body parts="p1 p2 p3 p4" use="literal" namespace="(MessageNS)"/> </input> </operation>

SOAP訊息中的格式:

<soapenv:body... xmlns:mns="(MessageNS)" xmlns:stns="(SchemaTNS)"><mns:method1> <mns:p1><stns:a>123</stns:a> <stns:b>hello</stns:b> </mns:p1> <mns:p2>123</mns:p2> <mns:p3><stns:SimpleElement>123</stns:SimpleElement> </mns:p3> <mns:p4> <stns:CompositeElement> <stns:a>123</stns:a> <stns:b>hello</stns:b> </stns:CompositeElement> </mns:p4></mns:method1> </soapenv:body>

rpc/encoded

<operation name="method1" style="rpc" ...> <input> <soap:body parts="p1 p2" use="encoded" encoding="http://schemas.xmlsoap.org/soap/encoding/" namespace="(MessageNS)"/> </input> </operation>

SOAP訊息中的格式:

<soapenv:body... xmlns:mns="(MessageNS)"> <mns:method1> <p1 HREF="#1" TARGET="_self"/> <p2>123</p2></mns:method1> <mns:CompositeType id="#1"> <a>123</a> <b>hello</b> </mns:CompositeType> </soapenv:body>

document/literal/type

<operation name="method1" style="document" ...> <input> <soap:body parts="p1" use="literal"> </input> </operation>

SOAP訊息中的格式:

<soapenv:body... xmlns:stns="(SchemaTNS)"> <stns:a>123</stns:a> <stns:b>hello</stns:b> </soapenv:body>

document/literal/element

<operation name="method1" style="document" ...> <input> <soap:body parts="p3 p4" use="literal"> </input> </operation>

SOAP訊息中的格式:

<soapenv:body... xmlns:stns="(SchemaTNS)"> <stns:SimpleElement>123</stns:SimpleElement> <stns:CompositeElement> <stns:a>123</stns:a> <stns:b>hello</stns:b> </stns:CompositeElement> </soapenv:body>

document/encoded

<operation name="method1" style="document" ...> <input> <soap:body parts="p1 p2" use="encoded" encoding="http://schemas.xmlsoap.org/soap/encoding/" namespace="(MessageNS)"/> </input> </operation>

SOAP訊息中的格式:

<soapenv:body... xmlns:mns="(MessageNS)"> <mns:CompositeType> <a>123</a> <b>hello</b></mns:CompositeType> <soapenc:int>123</soapenc:int> </soapenv:body>

<service>和<port>元素

        一個service有一組<port>元素。每個<port>元素與binding通常有一對一的對應關係。如果多個<port>元素與同一個<binding>相聯絡,則需要指定可選的location。

<service name="FOOService"> <port name="fooSamplePort" binding="fooSampleBinding"><soap:address location="http://carlos:8080/fooService/foo.asp"/></port> </service>

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.