Hello World
          Java技術(shù)學(xué)習(xí)
          posts - 17,  comments - 7,  trackbacks - 0
          Web Service描述語言 WSDL 詳解 2

          SOAP消息

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

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

            從客戶端調(diào)用"foo(5131953)"函數(shù):

          <?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>
           從服務(wù)器接受的信息:
            
          <?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>

            兩函數(shù)都調(diào)用了消息,其回應(yīng)是有效的XML。SOAP消息由幾部分組成,首先是<Envelop>元素,包含一個可選的<Header>元素以及至少一個<body>元素。Rpc函數(shù)所調(diào)用的消息體有一個根據(jù)操作"foo"命名的元素,而回應(yīng)信息體有一個"fooResponse"元素。Foo元素有一個部分<arg>,就和WSDL中描述的一樣,是單參數(shù)的。fooResponse也相應(yīng)的有一個<result>的部分。注意encodingStyle、envelope和message的namespace和WSDL Bindings欄中的預(yù)定義的一致,重復(fù)如下:
          <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數(shù)據(jù)類型是基于"XML Schema: Datatypes"(XSD)的,現(xiàn)在已經(jīng)被W3C推薦。這一文檔共有三個版本(1999,2000/10,2001),因此必須在namespace屬性的<definitions>元素中指明所使用的是哪一個版本。
          xmlns:xsd="http://www.w3.org/2001/XMLSchema"?
          在本文中,我將只考慮2001版本。WSDL標(biāo)準(zhǔn)的推薦者強烈建議使用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基類型。它也告訴在客戶端或服務(wù)器端的WSDL讀取程序如何把XSD類型映射到在VB、C++和IDL中相應(yīng)的類型。

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

            XSD定義了兩套內(nèi)建的數(shù)據(jù)類型:原始的和派生的。在下文中查閱內(nèi)建數(shù)據(jù)類型的層次十分有益:
          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類型可以表達(dá)比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類型不太一樣。

            注意內(nèi)建數(shù)據(jù)類型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,它將成功的解析該文件。當(dāng)然,它不會去調(diào)用<addPerson>。這是因為SoapClient本身并不知道如何處理complex類型,它需要定制類型映射來處理complex類型。MSTK2文檔中有包含定制類型映射的示例。

            還有另一種方法可以把<part>元素聯(lián)系到類型聲明。這就是使用元素。下例中我將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>中通過元素屬性而不是類型屬性來引用它。

            "元素屬性"和"類型屬性"在把某特定類型關(guān)聯(lián)到<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"元素。兩派生類型都?xì)w入一個complex類型"maleOrFemalePerson",使用的是<choice>構(gòu)造。最后,在"adperson"<message>中,新類型有"person"<part>引用。這樣,參數(shù)或<part>就可以是"femalePerson"或"malePerson"了。

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

          <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屬性值決定了數(shù)組每個成員的類型。數(shù)組的成員也可以是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要求數(shù)組的類型由"ArrayOf"和每個數(shù)組元素的類型串聯(lián)而成。很顯然,顧名思義,"ArrayOfPERSON"是PERSON結(jié)構(gòu)的數(shù)組。下面我將使用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初心 閱讀(1406) 評論(0)  編輯  收藏 所屬分類: Web Service

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

          常用鏈接

          留言簿(1)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 长岛县| 东丰县| 黄石市| 吉林省| 红安县| 翁源县| 汉阴县| 贵德县| 汉源县| 方城县| 五大连池市| 贵溪市| 天气| 两当县| 越西县| 屏南县| 承德市| 广州市| 秀山| 涡阳县| 兴业县| 西吉县| 政和县| 岑溪市| 务川| 灵寿县| 集贤县| 东平县| 郸城县| 布拖县| 扎囊县| 沙田区| 西宁市| 顺义区| 麻阳| 湘阴县| 婺源县| 积石山| 江津市| 成武县| 莎车县|