瘋狂

          STANDING ON THE SHOULDERS OF GIANTS
          posts - 481, comments - 486, trackbacks - 0, articles - 1
            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          轉(zhuǎn)自IBM java dev
          ------------------
          Web 服務(wù)是通過 WSDL 文檔來描述的。WSDL 綁定描述了如何把服務(wù)綁定到消息傳遞協(xié)議(特別是 SOAP 消息傳遞協(xié)議)。WSDL SOAP 綁定可以是 RPC 樣式的綁定,也可以是文檔樣式的綁定。同樣,SOAP 綁定可以有編碼的用法,也可以有文字的用法。這給我們提供了四種樣式/用法模型:

          1. RPC/編碼
          2. RPC/文字
          3. 文檔/編碼
          4. 文檔/文字

          除了這些樣式之外,還有一種樣式也很常見,它稱為文檔/文字包裝的樣式,算上這一種,在創(chuàng)建 WSDL 文件時(shí)您就有了五種綁定樣式可以從中選擇。您應(yīng)該選擇哪一種呢?

          對(duì)于本文的討論,讓我們從 清單1中的 Java 方法開始,并且對(duì)其應(yīng)用 JAX-RPC Java-to-WSDL 規(guī)則

          清單 1. Java 方法
          public void myMethod(int x);
          

          RPC/編碼

          采用 清單1中的方法并且使用您喜歡的 Java-to-WSDL 工具來運(yùn)行它,指定您想讓它生成 RPC/編碼的 WSDL。您最后應(yīng)該得到如 清單2所示的 WSDL 片斷。

          清單 2. 用于 myMethod 的 RPC/編碼的 WSDL
          <message name="myMethodRequest">
              <part name="x" type="xsd:int"/>
          </message>
          <message name="empty"/>
          <portType name="PT">
              <operation name="myMethod">
                  <input message="myMethodRequest"/>
                  <output message="empty"/>
              </operation>
          </portType>
          <binding .../>  
          <!-- I won't bother with the details, just assume it's RPC/encoded. -->
          

          現(xiàn)在用“5”作為參數(shù) x 的值來調(diào)用此方法。我們將發(fā)送一個(gè)與 清單3類似的 SOAP 消息。

          清單 3. 用于 myMethod 的 RPC/編碼的 SOAP 消息
          <soap:envelope>
              <soap:body>
                  <myMethod>
                      <x xsi:type="xsd:int">5</x>
                  </myMethod>
              </soap:body>
          </soap:envelope>
          

          關(guān)于前綴和名稱空間的注意事項(xiàng)

          為了簡單起見,在本文的大部分 XML 示例中,我省略了名稱空間和前綴。不過,我還是使用了少數(shù)前綴,您可以假定它們是用下列名稱空間進(jìn)行定義的。

          • xmlns:xsd="http://www.w3.org/2001/XMLSchema"
          • xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          • xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"

           

          對(duì)于這個(gè) RPC/編碼的示例中的 WSDL 和 SOAP 消息,有許多需要注意的事項(xiàng):

          優(yōu)點(diǎn)

          • WSDL 基本達(dá)到了盡可能地簡單易懂的要求。
          • 操作名出現(xiàn)在消息中,這樣接收者就可以很輕松地把消息發(fā)送到方法的實(shí)現(xiàn)。

          缺點(diǎn)

          • 類型編碼信息(比如 xsi:type="xsd:int" )通常就是降低吞吐量性能的開銷。
          • 您不能簡單地檢驗(yàn)此消息的有效性,因?yàn)橹挥?<x xsi:type="xsd:int">5</x> 行包含在 Schema 中定義的內(nèi)容;其余的 soap:body 內(nèi)容都來自 WSDL 定義。

          有沒有一種方法能夠保留這些優(yōu)點(diǎn)而消除其中的缺點(diǎn)呢?或許有。讓我們來看一看 RPC/文字的樣式。


          RPC/文字

          用于我們的方法的 RPC/文字的 WSDL 看起來與 RPC/編碼的 WSDL 幾乎一樣(請參見 清單4)。只是綁定的用法由 編碼改為 文字。僅此而已。

          清單
          4. 用于 myMethod 的 RPC/文字的 WSDL
          <message name="myMethodRequest">
              <part name="x" type="xsd:int"/>
          </message>
          <message name="empty"/>
          <portType name="PT">
              <operation name="myMethod">
                  <input message="myMethodRequest"/>
                  <output message="empty"/>
              </operation>
          </portType>
          <binding .../>  
          <!-- I won't bother with the details, just assume it's RPC/
                  literal. -->
                

          RPC/文字的 SOAP 消息又是怎樣的呢(請參見 清單 5)?這里的更改要多一點(diǎn)。去掉了類型編碼。

          清單 5. 用于 myMethod 的
          RPC/文字的 SOAP 消息
          <soap:envelope>
              <soap:body>
                  <myMethod>
                      <x>5</x>
                  </myMethod>
              </soap:body>
          </soap:envelope>
          

          下面是這種方法的優(yōu)點(diǎn)和缺點(diǎn):

          優(yōu)點(diǎn)

          • WSDL 還是基本達(dá)到了盡可能地簡單易懂的要求。
          • 操作名仍然出現(xiàn)在消息中。
          • 去掉了類型編碼。

          缺點(diǎn)

          • 您仍然不能簡單地檢驗(yàn)此消息的有效性,因?yàn)橹挥?<x xsi:type="xsd:int">5</x> 行包含在 Schema 中定義的內(nèi)容;其余的 soap:body 內(nèi)容都來自 WSDL 定義。

          文檔樣式如何呢?它們能夠幫助克服這些困難嗎?


          文檔

          我不知道有誰懂得這種方法的真正含義。我也不知道這種方法的任何實(shí)現(xiàn)。它將可能從 WSDL 的后續(xù)版本中消失。所以我們還是討論別的吧。


          文檔

          文檔/文字的 WSDL 對(duì) RPC/文字的 WSDL 作了一些更改。它們之間的不同之處顯示在 清單6中。


          清單6. 用于 myMethod 的文檔/文字的 WSDL
                  <types>
              <schema>
                  <element name="xElement" type="xsd:int"/>
              </schema>
          </types>
          <message name="myMethodRequest">
              <part name="x" 
                  element="xElement"/>
          </message>
          <message name="empty"/>
          <portType name="PT">
              <operation name="myMethod">
                  <input message="myMethodRequest"/>
                  <output message="empty"/>
              </operation>
          </portType>
          <binding .../>  
          <!-- I won't bother with the details, just assume it's 
                  document/literal. -->
                

          而現(xiàn)在的 SOAP 應(yīng)該如 清單 7所示:


          清單7. 用于 myMethod 的文檔/文字的 SOAP 消息
          <soap:envelope>
              <soap:body>
                  <xElement>5</xElement>
              </soap:body>
          </soap:envelope>
          

          關(guān)于消息組成部分的注意事項(xiàng)

          我本來可以只更改綁定,就像我從 RPC/編碼轉(zhuǎn)到 RPC/所做的那樣。它將是合法的 WSDL。然而,WS-I 基本概要(WS-I Basic Profile)(請參見 參考資料)規(guī)定文檔/文字的消息的組成部分引用元素而不是類型,所以我遵循了 WS-I(并且此處使用元素部分可以很好地把我們帶到關(guān)于文檔/文字包裝的樣式的討論)。

          下面是這種方法的優(yōu)點(diǎn)和缺點(diǎn):

          優(yōu)點(diǎn)

          • 沒有編碼信息
          • 您可以在最后用任何 XML 檢驗(yàn)器檢驗(yàn)此消息的有效性。 soap:body<xElement>5</xElement> )中每項(xiàng)內(nèi)容都定義在 Schema 中。

          缺點(diǎn)

          • WSDL 變得有些復(fù)雜。不過,這是一個(gè)非常小的缺點(diǎn),因?yàn)?WSDL 并沒有打算由人來讀取。
          • SOAP 消息中缺少操作名。而如果沒有操作名,發(fā)送就可能比較困難,并且有時(shí)變得不可能。

          文檔/文字的樣式看起來似乎只是重新安排了 RPC/文字的模型的優(yōu)點(diǎn)和缺點(diǎn)。您可以檢驗(yàn)消息的有效性,但是您失去了操作名。有沒有一種方法可以改進(jìn)這一點(diǎn)呢?有的。它就是文檔/文字包裝的樣式。


          文檔

          在我說明文檔/文字包裝的樣式的含義之前,讓我給您展示 清單 8清單9中的 WSDL 和 SOAP 消息。


          清單8. 用于 myMethod 的文檔/文字包裝的 WSDL
          <types>
              <schema>
                  
                  <element name="myMethod"/>
                      <complexType>
                          <sequence>
                              <element name="x" type="xsd:int"/>
                          </sequence>
                      </complexType>
                  </element>
              </schema>
          </types>
          <message name="myMethodRequest">
              <part name="
                  parameters" element="
                  myMethod"/>
          </message>
          <message name="empty"/>
          <portType name="PT">
              <operation name="myMethod">
                  <input message="myMethodRequest"/>
                  <output message="empty"/>
              </operation>
          </portType>
          <binding .../>  
          <!-- I won't bother with the details, just assume it's document/literal. -->
                

          WSDL Schema 現(xiàn)在把參數(shù)放在包裝中(請參見 清單9)。


          清單:9. 用于 myMethod 的文檔/文字包裝的 SOAP 消息
          <soap:envelope>
              <soap:body>
                  <myMethod>
                      <x>5</x>
                  </myMethod>
              </soap:body>
          </soap:envelope>

          注意到此 SOAP 消息看起來非常類似于 RPC/文字的 SOAP 消息。您可能會(huì)說,它看起來與 RPC/文字的 SOAP 消息是完全一樣的,不過,這兩種消息之間存在著微妙的區(qū)別。在 RPC/文字的 SOAP 消息中, <soap:body><myMethod> 子句是操作的名稱。在文檔/文字包裝的 SOAP 消息中, <myMethod> 子句是單個(gè)輸入消息的組成部分引用的元素的名稱。因此,包裝的樣式具有這樣的一個(gè)特征,輸入元素的名稱與操作的名稱是相同的。此樣式是把操作名放入 SOAP 消息的一種巧妙方式。

          文檔/文字包裝的樣式的特征有:

          • 輸入消息只有一個(gè)組成部分。
          • 該部分就是一個(gè)元素。
          • 該元素有與操作相同的名稱。
          • 該元素的復(fù)雜類型沒有屬性。

          下面是這種方法的優(yōu)點(diǎn)和缺點(diǎn):

          優(yōu)點(diǎn)

          • 沒有編碼信息。
          • 出現(xiàn)在 soap:body 中的每項(xiàng)內(nèi)容都是由 Schema 定義的,所以您現(xiàn)在可以很容易地檢驗(yàn)此消息的有效性。
          • 方法名又出現(xiàn)在 SOAP 消息中。

          缺點(diǎn)

          • WSDL 甚至更復(fù)雜,但是這仍然是一個(gè)非常小的缺點(diǎn)。

          如您所見,文檔/文字包裝的樣式還是有一些缺點(diǎn),不過與優(yōu)點(diǎn)比起來,它們都顯得無足輕重。

          RPC/文字包裝的樣式?

          從 WSDL 的角度來看,沒有理由只是把把包裝的樣式和文檔/文字綁定聯(lián)系在一起。它可以很容易地應(yīng)用于 RPC/文字綁定。但是這樣做是相當(dāng)不明智的。SOAP 將包含操作的一個(gè) myMethod 元素和元素名稱的子 myMethod 元素。另外,即使它是一個(gè)合法的 WSDL,RPC/文字元素部分也不遵循 WS-I。

          文檔/文字的樣式在哪里定義


          這種包裝的樣式來源于 Microsoft。沒有定義這種樣式的規(guī)范;所以雖然這種樣式是一個(gè)好的東西,但不幸的是,為了與 Microsoft 和其他公司的實(shí)現(xiàn)進(jìn)行互操作,現(xiàn)在惟一的選擇就是根據(jù) Microsoft WSDL 的輸出來猜測它是如何工作的。文檔/文字包裝的樣式也實(shí)現(xiàn)在 IBM WebSphere SDK for Web Services 中(請參見 參考資料)。在這個(gè)示例中,樣式是相當(dāng)明顯的;但是也存在個(gè)別情況,在這些情況中,由于缺少定義而導(dǎo)致需要操作的適當(dāng)事項(xiàng)不夠特別清晰。我們希望看到的最理想的情況就是將來能有像 Web 服務(wù)互操作組織(Web Services Interoperability Organization)這樣的獨(dú)立團(tuán)體來幫助對(duì)此進(jìn)行穩(wěn)定化和標(biāo)準(zhǔn)化。


          為什么不始終采用文檔/文字包裝的樣式

          至此,本文已經(jīng)給了您這樣的一個(gè)印象,文檔/文字包裝的樣式是最好的方法。而實(shí)際的情況往往確實(shí)如此。不過,仍然存在著一些情況,在這些情況下,您最好是換一種別的樣式。

          采用文檔/文字非包裝的樣式的理由


          如果您已經(jīng)重載了操作,就不能采用文檔/文字包裝的樣式。

          想象一下,除了我們一直在使用的方法之外,還有另一種方法,請參見 清單10


          清單10. 用于文檔/文字包裝的問題方法
          public void myMethod(int x);
                  public void myMethod(int x, String y);
                

          關(guān)于重載的操作的注意事項(xiàng)

          WSDL 的下一個(gè)版本可能將不允許重載的操作。

          WSDL 允許重載的操作。但是當(dāng)您添加包裝的樣式到 WSDL 時(shí),需要元素有與操作相同的名稱,并且在 XML 中不能有兩個(gè)名稱相同的元素。所以您必須采用文檔/文字非包裝的樣式或某種 RPC 樣式。

          采用 RPC/文字的樣式的理由


          由于文檔/文字非包裝的樣式?jīng)]有提供操作名,所以在有些情況下,您將需要采用某種 RPC 樣式。比如說 清單11中的一組方法。


          清單11. 用于文檔/文字非包裝的樣式的問題方法
          public void myMethod(int x);
          public void myMethod(int x, String y);
                  public void someOtherMethod(int x);
                

          現(xiàn)在假定您的服務(wù)器接收到文檔/文字的 SOAP 消息(您可以回過頭在 清單 7中看一看它)。服務(wù)器應(yīng)該發(fā)送哪一種方法呢?所有您能確切知道的就是,它一定不是 myMethod(int x, String x) ,因?yàn)橄⒅挥幸粋€(gè)參數(shù),而這種方法需要兩個(gè)參數(shù)。它可能是其他兩種方法中的一種。采用文檔/文字的樣式,您沒有辦法知道是哪一種方法。

          假定服務(wù)器接收到一個(gè) RPC/文字的消息(比如 清單5中的),而不是文檔/文字的消息。對(duì)于這種消息,服務(wù)器很容易決定把它發(fā)送到哪一種方法。您知道操作名是 myMethod,并且也知道只有一個(gè)參數(shù),所以它必定是 myMethod(int x)

          采用


          采用 RPC/編碼的理由有很多。其中兩個(gè)主要的原因是:

          • 數(shù)據(jù)圖形
          • 多態(tài)性

          數(shù)據(jù)圖形

          設(shè)想您有一個(gè)二進(jìn)制樹,其中的節(jié)點(diǎn)定義在 清單12中。


          清單12. 二進(jìn)制樹節(jié)點(diǎn) Schema
          <complexType name="Node">
              <sequence>
                  <element name="name" type="xsd:string"/>
                  <element name="left" type="Node" xsd:nillable="true"/>
                  <element name="right" type="Node" xsd:nillable="true"/>
              </sequence>
          </complexType>
          

          根據(jù)這種節(jié)點(diǎn)定義,我們可以構(gòu)造一個(gè)樹形結(jié)構(gòu),它的根節(jié)點(diǎn) A 通過它左邊和右邊的的鏈接可以指向節(jié)點(diǎn) B(請參見 圖1)。


          編碼的樹

          發(fā)送數(shù)據(jù)圖形的標(biāo)準(zhǔn)方式是使用 href 標(biāo)記,它是 RPC/編碼的樣式( 清單13)的一部分。


          清單:13. RPC/編碼的二進(jìn)制樹
          <A>
              <name>A</name>
              <left href="12345"/>
              <right href="12345"/>
          </A>
          <B id="12345">
              <name>B</name>
              <left xsi:nil="true"/>
              <right xsi:nil="true"/>
          </B>
          

          在任何文字的樣式中,href 屬性都是不可用的,這樣圖形鏈接就不再起作用了( 清單14圖2)。您仍然有一個(gè)根節(jié)點(diǎn) A,它從左邊指向一個(gè)節(jié)點(diǎn) B,從右邊指向另一個(gè)節(jié)點(diǎn) B。這兩個(gè) B 節(jié)點(diǎn)是等同的,但它們不是相同的節(jié)點(diǎn)。是復(fù)制了數(shù)據(jù)而不是引用了兩次數(shù)據(jù)。


          14. 文字二進(jìn)制樹
          <A>
              <name>A</name>
              <left>
                  <name>B</name>
                  <left xsi:nil="true"/>
                  <right xsi:nil="true"/>
              </left>
              <right>
                  <name>B</name>
                  <left xsi:nil="true"/>
                  <right xsi:nil="true"/>
              </right>
          </A>


          文字樹

          在文字樣式中,您可以通過各種方法構(gòu)造圖形,但是卻沒有標(biāo)準(zhǔn)的方法;所以您做的任何事情很可能不能與網(wǎng)絡(luò)中其他端點(diǎn)上的服務(wù)進(jìn)行互操作。

          多態(tài)性

          看一看 清單15中使用多態(tài)性 Schema 的 WSDL。

          清單
          15. 一個(gè)多態(tài)性 WSDL 的示例
          <types>
            <schema>
              <complexType name="animal">
                <sequence>
                  <element name="name" type="xsd:string"/>
                </sequence>
              </complexType>
              <complexType name="dog">
                <complexContent mixed="false">
                  <extension base="animal">
                    <sequence>
                      <element name="breed" type="xsd:string"/>
                    </sequence>
                  </extension>
                </complexContent>
              </complexType>
            </schema>
          </types>
          <message name="in">
            <part name="trainee" type="animal"/>
          </message>
          <message name="empty"/>
          <portType name="AnimalTrainer">
            <operation name="train">
              <input message="in"/>
              <output message="empty"/>
            </operation>
          </portType>
          

          當(dāng)您把一個(gè) dog 的實(shí)例傳送給 train 操作時(shí),所生成的 SOAP 消息必須包含類型編碼信息,這樣接收終端才能知道它所接收的是 animal 的哪一個(gè)擴(kuò)展(請參見 清單16)。這種類型編碼信息可用在 RPC/編碼的樣式中。

          清單
          16. 一個(gè)多態(tài)性 SOAP 消息
          <soap:envelope>
            <soap:body>
              <train>
                <trainee xsi:type="Dog">
                  <name>Bob</name>
                  <breed>Bloodhound</breed>
                </trainee>
              </train>
            </soap:body>
          </soap:envelope>


          總結(jié)

          有四種綁定樣式(其實(shí)真正有五種,不過文檔/編碼的樣式?jīng)]有什么意義)。雖然每種樣式都有自己的用武之地,但是在大多數(shù)情況下,最好的樣式是文檔/文字包裝的樣式。

          主站蜘蛛池模板: 景洪市| 博湖县| 吉安市| 河西区| 旬阳县| 木里| 正阳县| 潼关县| 山阴县| 郎溪县| 陆川县| 长顺县| 商洛市| 巴楚县| 湟源县| 鄂温| 米泉市| 晋宁县| 罗定市| 池州市| 柘城县| 盘山县| 客服| 晋宁县| 南京市| 辛集市| 曲松县| 双鸭山市| 苍南县| 永靖县| 进贤县| 甘泉县| 黑山县| 南华县| 图片| 中阳县| 武穴市| 巫山县| 延长县| 南郑县| 汽车|