Hello World
          Java技術學習
          posts - 17,  comments - 7,  trackbacks - 0
          Web Service描述語言 WSDL 詳解 2

          SOAP消息

            對于使用WSDL的客戶機和服務機來說,研究WSDL文件的一種方法就是決定什么來接受所發送的信息。盡管SOAP使用底層協議,如IP和HTTP等,但應用程序決定了服務器與客戶機之間交互的高級協議。也就是說,進行一項操作,比如"echoint"把輸入的整數送回,參數的數目、每個參數的類型、以及參數如何傳送等因素決定了應用程序特定的協議。有很多方法可以確定此類協議,但我相信最好的方法就是使用WSDL。如果我們用這種視角來看待它,WSDL不只是一種接口協議,而且是一種協議特定的語言。它就是我們超越"固定"協議(IP、HTTP等)所需要的應用程序特定協議。

            WSDL可以確定SOAP消息是否遵從RPC或文檔風格。RPC風格的消息(就是示例中所用的)看起來像是函數調用。而文檔風格的消息則更普通,嵌套層次更小。下面的XML消息就是示例WSDL文件解析后的發送/接受效果,解析使用的是MS SOAP Toolkit 2.0(MSTK2)中的SoapClient對象。

            從客戶端調用"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消息由幾部分組成,首先是<Envelop>元素,包含一個可選的<Header>元素以及至少一個<body>元素。Rpc函數所調用的消息體有一個根據操作"foo"命名的元素,而回應信息體有一個"fooResponse"元素。Foo元素有一個部分<arg>,就和WSDL中描述的一樣,是單參數的。fooResponse也相應的有一個<result>的部分。注意encodingStyle、envelope和message的namespace和WSDL Bindings欄中的預定義的一致,重復如下:
          <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>

          WSDL的Types欄和Messages欄中的XML Schema
          WSDL數據類型是基于"XML Schema: Datatypes"(XSD)的,現在已經被W3C推薦。這一文檔共有三個版本(1999,2000/10,2001),因此必須在namespace屬性的<definitions>元素中指明所使用的是哪一個版本。
          xmlns:xsd="http://www.w3.org/2001/XMLSchema"?
          在本文中,我將只考慮2001版本。WSDL標準的推薦者強烈建議使用2001版。

            在本欄和以后各部分,需使用以下簡縮或前綴

          前綴代表的Namespace描述
          Soapenchttp://schemas.xmlsoap.org/soap/encodingSOAP 1.1 encoding
          Wsdlhttp://schemas.xmlsoap.org/wsdl/soapWSDL 1.1
          Xsd http://www.w3.org/2001/XMLSchemaXML Schema

            XSD基類型

            下表是直接從MSTK2文檔中取出的,列舉了MSTK2所支持的所有XSD基類型。它也告訴在客戶端或服務器端的WSDL讀取程序如何把XSD類型映射到在VB、C++和IDL中相應的類型。

          XSD (Soap)類型變量類型 VBC++IDLComments
          anyURIVT_BSTRStringBSTRBSTR?
          base64Binary VT_ARRAY | VT_UI1Byte()SAFEARRAYSAFEARRAY(unsigned char)?
          BooleanVT_BOOL Boolean VARIANT_BOOLVARIANT_BOOL?
          ByteVT_I2Integershortshort轉換時驗證范圍有效性
          DateVT_DATEDateDATEDATE時間設為 oo:oo:oo
          DateTimeVT_DATEDateDATEDATE?
          DoubleVT_R8Doubledoubledouble?
          DurationVT_BSTRStringBSTRBSTR不轉換和生效
          ENTITIESVT_BSTRStringBSTRBSTR不轉換和生效
          ENTITYVT_BSTRStringBSTRBSTR不轉換和生效
          FloatVT_R4Singlefloatfloat?
          GDayVT_BSTRStringBSTRBSTR不轉換和生效
          GMonthVT_BSTRStringBSTRBSTR不轉換和生效
          GMonthDayVT_BSTRStringBSTRBSTR不轉換和生效
          GYearVT_BSTRStringBSTRBSTR不轉換和生效
          GYearMonthVT_BSTRStringBSTRBSTR不轉換和生效
          IDVT_BSTRStringBSTRBSTR不轉換和生效
          IDREFVT_BSTRStringBSTRBSTR不轉換和生效
          IDREFSVT_BSTRStringBSTRBSTR不轉換和生效
          IntVT_I4Longlonglong?
          IntegerVT_DECIMALVariantDECIMALDECIMAL轉換時范圍生效
          LanguageVT_BSTRStringBSTRBSTR不轉換和生效
          LongVT_DECIMALVariantDECIMALDECIMAL轉換時范圍生效
          NameVT_BSTRStringBSTRBSTR不轉換和生效
          NCNameVT_BSTRStringBSTRBSTR不轉換和生效
          negativeIntegerVT_DECIMALVariantDECIMALDECIMAL轉換時范圍生效
          NMTOKENVT_BSTRStringBSTRBSTR不轉換和生效
          NMTOKENSVT_BSTRStringBSTRBSTR不轉換和生效
          nonNegativeIntegeVT_DECIMALVariantDECIMALDECIMAL轉換時范圍生效
          nonPositiveIntegerVT_DECIMALVariantDECIMADECIMAL轉換時范圍生效
          normalizedStringVT_BSTRStringBSTRBSTR?
          NOTATIONVT_BSTRStringBSTRBSTR不轉換和生效
          NumberVT_DECIMALVariantDECIMALDECIMAL?
          positiveIntegerVT_DECIMALVariantDECIMALDECIMAL轉換時范圍生效
          QnameVT_BSTRStringBSTRBSTR不轉換和生效
          ShortVT_I2Integershortshort?
          StringVT_BSTR StringBSTRBSTR?
          TimeVT_DATEDateDATEDATE日設為1899年12月30日
          TokenVT_BSTRStringBSTRBSTR不轉換和生效
          unsignedByteVT_UI1Byteunsigned charunsigned char?
          UnsignedIntVT_DECIMALVariantDECIMALDECIMAL轉換時范圍生效
          unsignedLongVT_DECIMALVariantDECIMALDECIMAL轉換時范圍生效
          unsignedShortVT_UI4LongLongLong轉換時范圍生效

            XSD定義了兩套內建的數據類型:原始的和派生的。在下文中查閱內建數據類型的層次十分有益:
          http://www.w3.org/TR/2001/PR-xmlschema-2-20010330?

          complex類型

            XML schema允許complex類型的定義,就像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>
            不過,complex類型可以表達比struct更多的信息。除了<sequence>以外,它還可以有其他的子元素,比如<all>
          <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>?

          這意味著<element>的成員變量可以以任何順序排列,每一個都是可選的。這和C中的struct類型不太一樣。

            注意內建數據類型string, int, float。C的string也是XML的string,float也類似。但C中的long類型在XML中是int(上表中)。

            在WSDL文件中,像上面的complex類型可以在Types欄聲明。例如,我可以用以下方式聲明PERSON類型并用在Messages欄。

          <?xml?version="1.0"?encoding="UTF-8"??>
          <definitions?…?>
          <types>
          <schema?targetNamespace="someNamespace"?
          xmlns:typens
          ="someNamespace"?>
          <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>
          </schema>
          </types>

          <message?name="addPerson">
           
          <part?name="person"?type="typens:PERSON"/>
          </message>

          <message?name="addPersonResponse">
           
          <part?name="result"?type="xsd:int"/>
          </message>
          </definitions>?

            上例中第一個消息由"adperson",并且有一個<part>,其類型為"PERSON"。PERSON類型是在Types欄聲明的。

            如果我們使用完整的WSDL文件包含以上的部分,并以之初始化MSTK2 SoapClient,它將成功的解析該文件。當然,它不會去調用<addPerson>。這是因為SoapClient本身并不知道如何處理complex類型,它需要定制類型映射來處理complex類型。MSTK2文檔中有包含定制類型映射的示例。

            還有另一種方法可以把<part>元素聯系到類型聲明。這就是使用元素。下例中我將Types欄中聲明兩個元素("Person"和"Gendr"),然后我將在"addPerson"<message>中使用元素屬性來引用它們。

          <?xml?version="1.0"?encoding="UTF-8"??>
          <definitions?…?>
          <types>
          <schema?targetNamespace="someNamespace"?
           xmlns:typens
          ="someNamespace"?>
          <element?name="Person">
          <xsd:complexType>
           
          <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>
          </element>
          <element?name="Gender">
          <xsd:simpleType>
           
          <xsd:restriction?base="xsd:string">
            
          <xsd:enumeration?value="Male"?/>
            
          <xsd:enumeration?value="Female"?/>
           
          </xsd:restriction>
          </xsd:simpleType>
          </element>
          </schema>
          </types>

          <message?name="addPerson">
           
          <part?name="who"?element="typens:Person"/>
           
          <part?name="sex"?element="typens:Gender"/>
          </message>

          <message?name="addPersonResponse">
           
          <part?name="result"?type="xsd:int"/>
          </message>
          </definitions>?

            Types欄中的Gender<element>里嵌入了枚舉類型,其枚舉值為"Male""Female"。然后我又在"addPerson"<message>中通過元素屬性而不是類型屬性來引用它。

            "元素屬性"和"類型屬性"在把某特定類型關聯到<part>時有什么不同呢?使用元素屬性,我們可以描述一個部分,它可以假定幾個類型(就像變量一樣),而是用類型屬性我們就無法這樣做。下例說明了這一點。

          <?xml?version="1.0"?encoding="UTF-8"??>
          <definitions?…?>
          <types>
          <schema?targetNamespace="someNamespace"?
          xmlns:typens
          ="someNamespace">
          <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>
          <xsd:complexType?name="femalePerson">
          <xsd:complexContent>
           
          <xsd:extension?base="typens:PERSON"?>
           
          <xsd:element?name="favoriteLipstick"?type="xsd:string"?/>
          </xsd:extension>
          </xsd:complexContent>
          </xsd:complexType>
          <xsd:complexType?name="malePerson">
          <xsd:complexContent>
          <xsd:extension?base="typens:PERSON"?>
          <xsd:element?name="favoriteShavingLotion"?type="xsd:string"?/>
          </xsd:extension>
          </xsd:complexContent>
          </xsd:complexType>
          <xsd:complexType?name="maleOrFemalePerson">
          <xsd:choice>
           
          <xsd:element?name="fArg"?type="typens:femalePerson"?>
           
          <xsd:element?name="mArg"?type="typens:malePerson"?/>
          </xsd:choice>
          </xsd:complexType>
          </schema>
          </types>

          <message?name="addPerson">
           
          <part?name="person"?type="typens:maleOrFemalePerson"/>
          </message>

          <message?name="addPersonResponse">
           
          <part?name="result"?type="xsd:int"/>
          </message>
          </definitions>?

            上例也告訴我們extension的派生。"femailPerson"和"malePerson"都是從"PERSON"派生出來的。它們各有一些額外的元素:"femalePerson"有"favoriteLipstick"元素,"malePerson"有"favoriteShavingLotion"元素。兩派生類型都歸入一個complex類型"maleOrFemalePerson",使用的是<choice>構造。最后,在"adperson"<message>中,新類型有"person"<part>引用。這樣,參數或<part>就可以是"femalePerson"或"malePerson"了。

          數組
            XSD提供<list>結構來聲明一個數組,元素之間有空格界定。不過SOAP不是使用XSD來編碼數組的,它定義了自己的數組類型--"SOAP-ENC: Array"。下列的例子揭示了從這一類型派生出一位整數數組的方法:

          <xsd:complexType?name="ArrayOfInt">
          <xsd:complexContent>
           
          <xsd:restriction?base="soapenc:Array">
            
          <attribute?ref="soapenc:arrayType"?wsdl:arrayType="xsd:int[]"/>
           
          </xsd:restriction>
          </xsd:complexContent>
          </xsd:complexType>

            新的complex類型從soapenc:array限制派生。然后又聲明了complex類型的一個屬性。引用"soapenc:arrayType"實際上是這樣完成的:

          <xsd:attribute?name="arrayType"?type="xsd:string"/>

          wsdl:arrayType屬性值決定了數組每個成員的類型。數組的成員也可以是Complex類型。:

          <xsd:complexType?name="ArrayOfPERSON">
          <xsd:complexContent>
          <xsd:restriction?base="soapenc:Array">
          <attribute?ref="soapenc:arrayType"?
          wsdl:arrayType
          ="typens:PERSON[]"/>
          </xsd:restriction>
          </xsd:complexContent>
          </xsd:complexType>?

            WSDL要求數組的類型由"ArrayOf"和每個數組元素的類型串聯而成。很顯然,顧名思義,"ArrayOfPERSON"是PERSON結構的數組。下面我將使用ArrayOfPERSON來聲明一個<message>,并加入不止一個PERSON:

          <?xml?version="1.0"?encoding="UTF-8"??>
          <definitions?…?>
          <types>
          <schema?targetNamespace="someNamespace"?
          xmlns:typens
          ="someNamespace"?>
          <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>
          <xsd:complexType?name="ArrayOfPERSON">
          <xsd:complexContent>
          <xsd:restriction?base="soapenc:Array">
          <attribute?ref="soapenc:arrayType"?
          wsdl:arrayType
          ="typens:PERSON[]"/>
          </xsd:restriction>
          </xsd:complexContent>
          </xsd:complexType>
          </schema>
          </types>

          <message?name="addPersons">
           
          <part?name="person"?type="typens:ArrayOfPERSON"/>
          </message>

          <message?name="addPersonResponse">
           
          <part?name="result"?type="xsd:int"/>
          </message>

          </definitions>


          ?

          posted on 2007-01-22 12:37 Java初心 閱讀(1407) 評論(0)  編輯  收藏 所屬分類: Web Service

          <2007年1月>
          31123456
          78910111213
          14151617181920
          21222324252627
          28293031123
          45678910

          常用鏈接

          留言簿(1)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 新乡市| 昌黎县| 伊金霍洛旗| 邢台县| 安溪县| 江北区| 江达县| 昭觉县| 中方县| 七台河市| 葫芦岛市| 涿鹿县| 万宁市| 象山县| 凤庆县| 东平县| 尼木县| 沈丘县| 改则县| 仙居县| 陵水| 黄浦区| 江油市| 安康市| 龙井市| 蒲江县| 金塔县| 黄浦区| 荆州市| 息烽县| 荔波县| 呼图壁县| 阳高县| 托克托县| 车致| 新民市| 曲阳县| 庆城县| 邵阳县| 绍兴市| 江孜县|