posts - 495,comments - 227,trackbacks - 0

          理解 SOAP

          現(xiàn)在已經(jīng)安裝了軟件,接下來(lái)可以開(kāi)始著手處理實(shí)際的 Web 服務(wù)了。正如我在其他類型的 Web 服務(wù)中提到的,您可以選擇多種格式。在本系列中,將使用 SOAP。

          XML 簡(jiǎn)介

          進(jìn)行傳遞的所有這些消息都基于可擴(kuò)展標(biāo)記語(yǔ)言(Extensible Markup Language,XML)。如果完全不熟悉 XML,在深入了解各個(gè) Web 服務(wù)主題前,真的應(yīng)該進(jìn)行一些相關(guān)研究。不過(guò),以下提供了繼續(xù)學(xué)習(xí)本教程所需的基本知識(shí)。

          XML 是一種“標(biāo)記語(yǔ)言”,即給出了一種提供實(shí)際內(nèi)容的附加信息的方式。此信息以“標(biāo)記”的形式提供,這些標(biāo)記用于指示“元素”。例如,考慮一下清單 5 中所示的簡(jiǎn)單 XML 文檔。


          清單 5. 包含基本內(nèi)容的 XML 文件
                              
          <article articleId="88271" categoryId="classifieds" subcategoryId="forsale">
            <articleHeadline>Fun, fun, fun</articleHeadline>
            <articleText>Vintage 1963 T-Bird.  Less than 300 miles.
          Driven by my daughter until I took it away.  Serious 
          inquires only.  555-3264 after 7 PM.</articleText>
          </article>
          

          請(qǐng)留意此文本中的幾個(gè)值得注意的地方。首先,這是文本。這就使其可以供任何人閱讀,或在其中包含關(guān)于任何事物的內(nèi)容。其次,標(biāo)記使用 > 和 < 指示,開(kāi)始標(biāo)記具有一個(gè)名稱,并可能帶有各種屬性(如文章 ID),而結(jié)束標(biāo)記以反斜杠 (/) 表示。元素必須為自包含的,并進(jìn)行了恰當(dāng)嵌套。也就是說(shuō),不能使用與清單 6 所示類似的 XML 文檔。


          清單 6. 無(wú)效 XML 文檔示例
                              
          <article articleId="88271" categoryId="classifieds" subcategoryId="forsale">
            <articleHeadline>Fun, fun, fun
            <articleText></articleHeadline>Vintage 1963 T-Bird.  
          Less than 300 miles. Driven by my daughter until I 
          took it away.  Serious inquires only.  555-3264 after 
          7 PM.</articleText>
          </article>
          

          XML 還提供了將內(nèi)容劃分為不同“命名空間”的方法,以便由應(yīng)用程序?qū)ζ溥M(jìn)行不同的處理。例如,SOAP 消息可能與以下的清單 7 類似。


          清單 7. 示例 SOAP 消息
                              
          <?xml version='1.0' ?>
          <env:Envelope xmlns:env="http://www.w3.org/2003/05/SOAP-envelope"> 
           <env:Header>
           </env:Header>
           <env:Body>
            <cms:getNumberOfArticles xmlns:cms="http://www.daily-moon.com/cms">
              <cms:category>classifieds</cms:category>
              <cms:subcategory>forsale</cms:subcategory>
            </cms:getNumberOfArticles>
           </env:Body>
          </env:Envelope>
          

          不要擔(dān)心消息的實(shí)際結(jié)構(gòu),但要注意存在兩種不同的“前綴”,每個(gè)前綴與特定的命名空間對(duì)應(yīng)。在這種情況下,我們是為了將 SOAP“信封”與實(shí)際的有效負(fù)載進(jìn)行區(qū)分。

          再次說(shuō)明,關(guān)于 XML 有很多需要學(xué)習(xí),但這些只是本教程需要了解的基礎(chǔ)知識(shí)。





          回頁(yè)首


          SOAP 信封

          Web 服務(wù)消息的基本單元是實(shí)際的 SOAP 信封。這是包含處理消息所必需的所有信息的 XML 文檔(請(qǐng)參見(jiàn)清單 8)。


          清單 8. 示例 SOAP 信封
                              
          <?xml version='1.0' ?>
          <env:Envelope xmlns:env="http://www.w3.org/2003/05/SOAP-envelope"> 
           <env:Header>
          </env:Header>
          <env:Body>
          </env:Body>
          </env:Envelope>
          

          在本例中,獲得了一個(gè)簡(jiǎn)單的 Envelope,其命名空間指定為 SOAP 1.2 版本。其中包含兩個(gè)子元素 HeaderBody。讓我們了解一下這兩個(gè)子元素所起的作用。





          回頁(yè)首


          SOAP Header

          SOAP 消息中的 Header 用于提供有關(guān)消息本身的信息,與用于應(yīng)用程序的信息相對(duì)。例如,Header 可以包括路由信息,像清單 9 中的示例類似。


          清單 9. Header 中的路由信息
                              
          <?xml version='1.0' ?>
          <env:Envelope xmlns:env="http://www.w3.org/2003/05/SOAP-envelope"> 
           <env:Header>
            <wsa:ReplyTo xmlns:wsa=
                  "http://schemas.xmlSOAP.org/ws/2004/08/addressing">
             <wsa:Address>
          http://schemas.xmlSOAP.org/ws/2004/08/addressing/role/anonymous
             </wsa:Address>
            </wsa:ReplyTo>
            <wsa:From>
             <wsa:Address>
          http://localhost:8080/axis2/services/MyService</wsa:Address>
            </wsa:From>
            <wsa:MessageID>ECE5B3F187F29D28BC11433905662036</wsa:MessageID> 
            </env:Header>
          <env:Body>
          </env:Body>
          </env:Envelope>
          

          本例中有一個(gè) WS-Addressing 元素,其中包含有關(guān)消息將送達(dá)何處以及應(yīng)將應(yīng)答送達(dá)何處的信息。Header 可包含關(guān)于消息本身的所有類型的消息。事實(shí)上,SOAP 規(guī)范中使用了大量篇幅說(shuō)明哪些元素可以放入 Header以及應(yīng)由“SOAP 中間層”如何對(duì)其進(jìn)行處理。也就是說(shuō),SOAP 規(guī)范并不假定消息將直接從一個(gè)點(diǎn)傳遞到另一個(gè)點(diǎn)(從客戶機(jī)到服務(wù)器)。規(guī)范考慮了 SOAP 消息在送達(dá)最終目的地的過(guò)程中可能實(shí)際由多個(gè)中間層處理的情況,很清楚地說(shuō)明了中間層應(yīng)如何對(duì)待在 Header 中找到的信息。不過(guò),對(duì)此的討論不在本教程的范圍之內(nèi)。因此,目前只要知道 Header 可以提供許許多多的功能(如果您需要)即可。

          接下來(lái)讓我們看看實(shí)際的有效負(fù)載。





          回頁(yè)首


          SOAP 體

          發(fā)送 SOAP 消息時(shí),都是有目的性的。您在嘗試告訴接收者執(zhí)行某種操作,或嘗試向服務(wù)器傳遞相關(guān)信息。此信息稱為“有效負(fù)載”。有效負(fù)載位于 EnvelopeBody 中。它還具有自己的命名空間,在本例中其命名空間與內(nèi)容管理系統(tǒng)對(duì)應(yīng)。在此情況下,可以完全隨意地選擇命名空間。只需要與 SOAP 命名空間相異即可(請(qǐng)參見(jiàn)清單 10)。


          清單 10. 有效負(fù)載示例
                              
          <?xml version='1.0' ?>
          <env:Envelope xmlns:env="http://www.w3.org/2003/05/SOAP-envelope"> 
           <env:Header>
          ...
          </env:Header>
           <env:Body>
            <cms:addArticle xmlns:cms="http://www.daily-moon.com/cms">
              <cms:category>classifieds</category>
              <cms:subcategory>forsale</cms:subcategory>
              <cms:articleHeadline></cms:articleHeadline>
              <cms:articleText>Vintage 1963 T-Bird.  Less than 300 miles.  
          Driven by my daughter until I took it away.  Serious inquires only.  
          555-3264 after 7 PM.</cms:articleText>
            </cms:addArticle>
           </env:Body>
          </env:Envelope>
          

          在此例中,有效負(fù)載很簡(jiǎn)單,其中包含將文章添加到 Daily Moon 的內(nèi)容管理系統(tǒng)的指令。

          如何設(shè)計(jì)有效負(fù)載的選擇過(guò)程將涉及到樣式和編碼的內(nèi)容。





          回頁(yè)首


          樣式和編碼

          本系列教程的第 2 部分將更深入地了解此主題的內(nèi)容(該部分討論 Web 服務(wù)描述語(yǔ)言——WSDL),但在創(chuàng)建應(yīng)用程序時(shí),您將需要確定要發(fā)送和接收的實(shí)際有效負(fù)載的結(jié)構(gòu)。為此,讓我們花點(diǎn)時(shí)間討論一下編程樣式和編碼。

          簡(jiǎn)單來(lái)說(shuō),有兩種不同的主流 SOA 消息編程樣式。第一種是 RPC 樣式,基于使用 SOAP 消息創(chuàng)建遠(yuǎn)程過(guò)程調(diào)用(Remote Procedure Call)的概念。在此樣式中,基本思路是在向服務(wù)器發(fā)送命令(如“添加文章”),并將該命令的參數(shù)(如要添加的文章和應(yīng)該添加到的類別)作為整個(gè)方法的子元素包含在其中,如清單 11 中所示。


          清單 11. RPC 樣式
                              
          <env:Envelope xmlns:env="http://www.w3.org/2003/05/SOAP-envelope">
           <env:Header> 
          

          RPC 樣式的替代方法將數(shù)據(jù)直接作為 SOAP 體的內(nèi)容處理,并在應(yīng)用服務(wù)器對(duì)消息進(jìn)行路由的信息中包含有關(guān)其所屬的過(guò)程或函數(shù)的信息。(請(qǐng)參見(jiàn)清單 12)。


          清單 12. 將數(shù)據(jù)作為 SOAP 體中的內(nèi)容
                              
          <env:Envelope xmlns:env="http://www.w3.org/2003/05/SOAP-envelope"> 
           <env:Header>
           </env:Header>
           <env:Body>
            <cms:addArticle xmlns:cms="http://www.daily-moon.com/cms">
              <cms:category>classifieds</category>
              <cms:subcategory>forsale</cms:subcategory>
              <cms:articleHeadline></cms:articleHeadline>
              <cms:articleText>Vintage 1963 T-Bird.  Less than 300 
          miles.  Driven by my daughter until I took it away.  
          Serious inquires only.  555-3264 after 7 PM.</cms:articleText>
            </cms:addArticle>
           </env:Body>
          </env:Envelope>
          

          RPC 樣式的一個(gè)變體就是與上面看到的 RPC/literal 相對(duì)的 RPC/encoded。在這種情況下,消息中包含類型信息,如清單 13 中所示。


          清單 13. RPC/encoded 示例
                              
          <?xml version='1.0' ?>
          <env:Envelope xmlns:env="http://www.w3.org/2003/05/SOAP-envelope"> 
           <env:Header>
           </env:Header>
           <env:Body>
            <cms:addArticle xmlns:cms="http://www.daily-moon.com/cms">
              <cms:category xsi:type="xsd:string">classifieds</category>
              <cms:subcategory xsi:type="xsd:string">forsale
          </cms:subcategory>
              <cms:articleHeadline xsi:type="xsd:string" />
              <cms:articleText xsi:type="xsd:string">Vintage 1963 
          T-Bird.  Less than 300 miles.  Driven by my daughter until
          I took it away.  Serious inquires only.  555-3264 after 7 
          PM.</cms:articleText>
            </cms:addArticle>
           </env:Body>
          </env:Envelope>
          

          第二個(gè)樣式稱為 document/literal 樣式,即將相應(yīng)的數(shù)據(jù)直接添加到消息中,如清單 14 中所示。


          清單 14. Document/literal 樣式示例
                              
          <?xml version='1.0' ?>
          <env:Envelope xmlns:env="http://www.w3.org/2003/05/SOAP-envelope"> 
           <env:Header>
           </env:Header>
           <env:Body>
              <category>classifieds</category>
              <subcategory>forsale</subcategory>
              <articleHeadline></articleHeadline>
              <articleText>Vintage 1963 T-Bird.  Less than 300 miles.
            Driven by my daughter until I took it away.  Serious 
          inquires only.  555-3264 after 7 PM.</articleText>
          </env:Body>
          </env:Envelope>
          

          在這種情況下,消息本身并不包含有關(guān)數(shù)據(jù)所提交到的進(jìn)程的信息,此工作由路由軟件進(jìn)行。例如,所有對(duì)特定 URL 或端點(diǎn)的調(diào)用都可能指向特定的操作。另外,從技術(shù)上講,可以使用 document/encoded 樣式,但目前還沒(méi)有人這樣做,因此可以將其忽略。

          在每個(gè)樣式中都涉及到不同的折衷,本系列的第 2 部分將進(jìn)一步對(duì)此進(jìn)行詳細(xì)討論。不過(guò),務(wù)必知道還有第三種樣式“document wrapped”,并未正式地確定此樣式,但由于各種互操作性原因而大受歡迎。在此情況下,有效負(fù)載的內(nèi)容包裝為單個(gè)元素,但元素并不據(jù)數(shù)據(jù)所屬的過(guò)程或函數(shù)進(jìn)行命名。從肉眼來(lái)看,這些消息幾乎與 RPC/literal 消息完全相同。





          回頁(yè)首


          消息交換模式

          談到發(fā)送消息,您有很多選擇,可以發(fā)送請(qǐng)求并等待響應(yīng),發(fā)送請(qǐng)求但不等待響應(yīng),發(fā)送請(qǐng)求并在到達(dá)最終的目的地前通過(guò)多個(gè)中間層。但就實(shí)質(zhì)而言,只有兩個(gè)選擇:

          • 請(qǐng)求/響應(yīng):在請(qǐng)求/響應(yīng)模式種,以 SOAP 消息的形式發(fā)送請(qǐng)求,然后直接等待發(fā)送回響應(yīng)。請(qǐng)求可以為同步的,也可以是異步的。
          • 單向消息傳遞:這種情況也稱為“Fire and Forget”方法,發(fā)送請(qǐng)求但并不等待響應(yīng)。可以在僅傳遞信息時(shí)或并不關(guān)心接收者對(duì)此如何響應(yīng)時(shí)使用此方法。

          現(xiàn)在,請(qǐng)注意并沒(méi)有使用術(shù)語(yǔ)“客戶機(jī)”和“服務(wù)器”。之所以這樣,是因?yàn)檫@些消息交換模式幾乎可以用于創(chuàng)建與上面提到的方法類似的任意數(shù)量的不同備選方法。例如,可以發(fā)送一條請(qǐng)求,然后依靠接收者對(duì)其進(jìn)行處理,并在將來(lái)完成應(yīng)完成的工作時(shí)發(fā)送一條消息。為此,將使用多個(gè)單向消息的組合,因此談“客戶機(jī)”和“服務(wù)器”并不合理,因?yàn)槊總€(gè)消息都有其接收方和發(fā)送方,所謂的客戶機(jī)和服務(wù)器的位置會(huì)發(fā)生對(duì)換。





          回頁(yè)首


          構(gòu)建 SOAP 客戶機(jī)

          上面已經(jīng)對(duì)理論進(jìn)行了介紹,現(xiàn)在讓我們開(kāi)始構(gòu)建實(shí)際的實(shí)現(xiàn)。首先從客戶機(jī)開(kāi)始。

          以前的老方式

          最初出現(xiàn)用于使用 SOAP 消息的 Java API 時(shí),其用途非常特定化。它們的用途相當(dāng)直接,用于創(chuàng)建 SOAP 消息。需要?jiǎng)?chuàng)建消息、EnvelopeHeaderBody 等等。例如,可以構(gòu)建“舊式”客戶機(jī)來(lái)訪問(wèn)前面安裝的 MyService 服務(wù)的 echo 函數(shù)(請(qǐng)參見(jiàn)清單 15)。

          注意:為了編譯并運(yùn)行此客戶機(jī),將需要 SAAJ 實(shí)現(xiàn)(如原始 Axis 軟件)。可以從 http://ws.apache.org/axis/ 下載 Axis。據(jù)說(shuō) Axis2 0.95 也包含此實(shí)現(xiàn),但本教程未針對(duì)其進(jìn)行測(cè)試。


          清單 15. 舊式 SOAP 客戶機(jī)
                              
          import javax.xml.SOAP.*; 
          import javax.xml.transform.*;
          import java.io.FileInputStream;
          import javax.xml.transform.stream.*;
          import org.w3c.dom.*;
          
          public class SendSOAP {
              
             public static void main(String args[]) {
                  
                try {
                
                   MessageFactory messageFactory = MessageFactory.newInstance();
                   SOAPMessage message = messageFactory.createMessage();
                   
                   //Create objects for the message parts            
                   SOAPPart SOAPPart = message.getSOAPPart();
                   SOAPEnvelope envelope = SOAPPart.getEnvelope();
                   SOAPBody body = envelope.getBody();
          
                   SOAPElement bodyElement = 
                     body.addChildElement(envelope.createName("echo", 
                      "req", "http://localhost:8080/axis2/services/MyService/"));
                   bodyElement.addChildElement("category")
                                       .addTextNode("classifieds");
                   message.saveChanges();
          
                   SOAPPart SOAPpartbefore = message.getSOAPPart();
                   SOAPEnvelope reqenv = SOAPpartbefore.getEnvelope();
          
                   System.out.println("REQUEST:");
                   System.out.println(reqenv.toString());
          
                   //Now create the connection
                   SOAPConnectionFactory SOAPConnFactory = 
                                     SOAPConnectionFactory.newInstance();
                   SOAPConnection connection = 
                                     SOAPConnFactory.createConnection();
                   
                   SOAPMessage reply = connection.call(message, 
                             "http://localhost:8080/axis2/services/MyService");
          
                   SOAPPart SOAPpart = reply.getSOAPPart();
                   SOAPEnvelope replyenv = SOAPpart.getEnvelope();
          
                   System.out.println("\nRESPONSE:");
                   System.out.println(replyenv.toString());
          
                   connection.close();
               
               } catch (Exception e){
                   System.out.println(e.getMessage());
               }
            }
          }
          

          請(qǐng)注意,您要直接創(chuàng)建 SOAPEnvelopeSOAPBody 等內(nèi)容。可以向消息體添加 echocategory 等元素。將從其中創(chuàng)建連接,進(jìn)行調(diào)用,同樣也能遍歷 SOAP 消息的結(jié)構(gòu)來(lái)獲取實(shí)際的內(nèi)容。如果要運(yùn)行此客戶機(jī),應(yīng)該看到與清單 16 中所示類似的響應(yīng)。


          清單 16. 當(dāng)時(shí)的客戶機(jī)
                              
          REQUEST:
          <SOAPenv:Envelope xmlns:SOAPenv=
                 "http://schemas.xmlSOAP.org/SOAP/envelope/" 
               xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
           <SOAPenv:Body>
            <req:echo xmlns:req=
                   "http://localhost:8080/axis2/services/MyService/">
               <req:category>classifieds</req:category>
            </req:echo>
           </SOAPenv:Body>
          </SOAPenv:Envelope>
          
          RESPONSE:
          <SOAPenv:Envelope xmlns:SOAPenv=
                "http://schemas.xmlSOAP.org/SOAP/envelope/" xmlns:wsa=
                "http://schemas.xmlSOAP.org/ws/2004/08/addressing">
           <SOAPenv:Header>
            <wsa:ReplyTo>
             <wsa:Address>
          http://schemas.xmlSOAP.org/ws/2004/08/addressing/role/anonymous
             </wsa:Address>
            </wsa:ReplyTo>
            <wsa:From>
             <wsa:Address>
          http://localhost:8080/axis2/services/MyService</wsa:Address>
            </wsa:From>
            <wsa:MessageID>ECE5B3F187F29D28BC11433905662036</wsa:MessageID>
           </SOAPenv:Header>
           <SOAPenv:Body>
            <req:echo xmlns:req=
                   "http://localhost:8080/axis2/services/MyService/">
               <req:category>classifieds</req:category>
            </req:echo>
           </SOAPenv:Body>
          </SOAPenv:Envelope>
          

          echo 服務(wù)所進(jìn)行的所有工作實(shí)際就是對(duì)其所接收到的請(qǐng)求進(jìn)行應(yīng)答,通過(guò)這一點(diǎn)可以很好地了解舊式處理方法與新式處理方法間的差別。接下來(lái)讓我們看看二者的差異。





          回頁(yè)首


          新方式

          現(xiàn)在越來(lái)越趨向于對(duì)程序員隱藏使用基于 XML 的 Web 服務(wù)消息的復(fù)雜性。為此進(jìn)行了大量的工作,其中大部分的目標(biāo)都是希望盡可能讓 Web 服務(wù)編程與任何其他體系結(jié)構(gòu)的編程工作一樣進(jìn)行。

          在 Axis2 中,實(shí)際上并不僅限于此。Axis2 引入了一種全新的方式來(lái)使用表示 SOAP 消息的 XML(盡管表面看來(lái)與使用文檔對(duì)象模型類似)。AxIs 對(duì)象模型(Axis Object Model,AXIOM)進(jìn)行了一系列更改,但我暫時(shí)將僅提一下其對(duì)消息的信息集的關(guān)注,消息集是元素和屬性中包含的實(shí)際信息,而不是通常看到的序列化版本。不過(guò),更為重要的是,Axis2 將為您處理 SOAP 信封,從而可以將精力放在構(gòu)建有效負(fù)載上(或者,如果是實(shí)際的服務(wù),則是分析有效負(fù)載和創(chuàng)建響應(yīng))。接下來(lái)讓我們看看如何進(jìn)行此工作。





          回頁(yè)首


          創(chuàng)建請(qǐng)求

          要開(kāi)始創(chuàng)建客戶機(jī),請(qǐng)確保 Axis2 lib 目錄中的所有 *.jar 文件——指 Standard 分發(fā)版,而不是 War 分發(fā)版——都在您的 CLASSPATH 上,并創(chuàng)建名為 ClassifiedClient 的新類。創(chuàng)建有效負(fù)載,如清單 17 中所示。


          17. 有效負(fù)載
                              
          import org.apache.axis2.addressing.EndpointReference;
          import org.apache.axis2.client.Options;
          import org.apache.axis2.client.ServiceClient;
          import org.apache.axis2.om.OMElement;
          import javax.xml.stream.XMLOutputFactory;
          import javax.xml.stream.XMLStreamException;
          import java.io.StringWriter;
          import org.apache.axis2.om.OMAbstractFactory;
          import org.apache.axis2.SOAP.SOAPFactory;
          import org.apache.axis2.om.OMFactory;
          import org.apache.axis2.om.OMNamespace;
          
          public class ClassifiedClient {
          
              public static OMElement getEchoOMElement() {
                  SOAPFactory fac = OMAbstractFactory.getSOAP12Factory();
                  OMNamespace omNs = fac.createOMNamespace(
                          "http://daily-moon.com/cms", "cms");
                  OMElement method = fac.createOMElement("echo", omNs);
                  OMElement value = fac.createOMElement("category", omNs);
                  value.addChild(fac.createText(value, "classifieds"));
                  method.addChild(value);
          
                  return method;
              }
          
              public static void main(String[] args) {
                  try {
                      OMElement payload = ClassifiedClient.getEchoOMElement();
                  } catch (Exception e) { //(XMLStreamException e) {
                      System.out.println(e.toString());
                  }
              }
          }
          

          首先,創(chuàng)建工廠和命名空間,并使用其創(chuàng)建各個(gè)元素。在本例中,您將創(chuàng)建與前面示例完全相同的元素,因?yàn)閷⒃俅问褂么丝蛻魴C(jī)訪問(wèn) echo 函數(shù)。(稍后將對(duì)其進(jìn)行更改,以訪問(wèn)真正的服務(wù)。)

          接下來(lái),將創(chuàng)建請(qǐng)求。





          回頁(yè)首


          創(chuàng)建請(qǐng)求

          下一步將創(chuàng)建實(shí)際的請(qǐng)求。同樣,這方面也體現(xiàn)出技術(shù)隨時(shí)間的發(fā)展。這里不會(huì)直接將請(qǐng)求發(fā)送到 URL,而要設(shè)置“端點(diǎn)引用”,如清單 18 中所示。


          清單 18. 請(qǐng)求中的端點(diǎn)引用
                              
          ...
          public class ClassifiedClient {
              private static EndpointReference targetEPR = new
                  EndpointReference(
                     "http://localhost:8080/axis2/services/MyService");
          
              public static OMElement getEchoOMElement() {
          ...
              }
          
              public static void main(String[] args) {
                  try {
                      OMElement payload = ClassifiedClient.getEchoOMElement();
                      Options options = new Options();
                      options.setTo(targetEPR);
                      options.setTransportInProtocol(Constants.TRANSPORT_HTTP);
          
                  } catch (Exception e) { //(XMLStreamException e) {
                      System.out.println(e.toString());
                  }
              }
          }
          

          對(duì) WS-Addressing 的全面討論不在本教程的范疇之內(nèi),但完全可以說(shuō)端點(diǎn)引用包含消息將定向到的 URL,還可以有選擇地包含其他信息,如應(yīng)答地址和其他資源屬性等。

          首先,為請(qǐng)求創(chuàng)建 Options,以便為請(qǐng)求設(shè)置 EPR 和其他信息(如打算使用的傳輸協(xié)議)。完成了這些后,就可以實(shí)際發(fā)送請(qǐng)求了。





          回頁(yè)首


          發(fā)送請(qǐng)求

          完成了設(shè)置后,就可以發(fā)送請(qǐng)求了。對(duì)于 Axis 的 0.94 版,首選的方式是通過(guò) ServiceClient 類發(fā)送消息,如清單 19 中所示。


          清單 19. 發(fā)送請(qǐng)求
                              
          ...
              public static void main(String[] args) {
                  try {
                      OMElement payload = ClassifiedClient.getEchoOMElement();
                      Options options = new Options();
                      options.setTo(targetEPR);
                      options.setTransportInProtocol(Constants.TRANSPORT_HTTP);
          
                      ServiceClient sender = new ServiceClient();
                      sender.setOptions(options);
                      OMElement result = sender.sendReceive(payload);
          
                  } catch (Exception e) { //(XMLStreamException e) {
                      System.out.println(e.toString());
                  }
              }
          }
          

          將創(chuàng)建 ServiceClient 對(duì)象,并為其設(shè)置前面創(chuàng)建的 Options。然后就可以直接發(fā)送消息了。由于希望得到響應(yīng),因此將使用 sendReceive() 方法(該方法用于 in/out 類型的消息)。將在本教程的單向服務(wù)部分討論單向消息的信息。sendReceive() 方法將在客戶機(jī)接收到實(shí)際響應(yīng)時(shí)將其返回。





          回頁(yè)首


          輸出結(jié)果

          實(shí)際上,sendReceive() 并不會(huì)返回整個(gè)響應(yīng),而僅返回有效負(fù)載。如果將結(jié)果輸出到命令行,應(yīng)該清楚地看到清單 20 中的內(nèi)容。


          清單 20. sendReceive 輸出
                              
          
          ...
                      sender.setOptions(options);
                      OMElement result = sender.sendReceive(payload);
          
                      System.out.println(result.toString());
          
                  } catch (Exception e) { //(XMLStreamException e) {
                      System.out.println(e.toString());
                  }
              }
          }
          

          運(yùn)行此客戶機(jī)將獲得清單 21 中所示的響應(yīng)。


          清單 21. sendReceive 響應(yīng)
                              
          <cms:echo xmlns:cms="http://daily-moon.com/cms"><cms:catego
          ry>classifieds</cms:category></cms:echo>
          

          當(dāng)然,接收到此數(shù)據(jù)后,可以使用其進(jìn)行任何工作。接下來(lái),我們將構(gòu)建實(shí)際的 getNumberofArticles() 服務(wù)。





          回頁(yè)首

          posted on 2006-12-29 18:35 SIMONE 閱讀(1336) 評(píng)論(0)  編輯  收藏 所屬分類: AXISJAVA
          主站蜘蛛池模板: 亚东县| 山丹县| 霍城县| 罗江县| 西林县| 咸阳市| 松滋市| 石家庄市| 临漳县| 福安市| 县级市| 漳州市| 兴仁县| 安庆市| 余江县| 乐业县| 惠来县| 河源市| 象州县| 阳西县| 徐闻县| 轮台县| 桃园县| 大洼县| 满洲里市| 宁波市| 巴彦县| 台南县| 汉阴县| 美姑县| 浦江县| 河东区| 嘉峪关市| 沈丘县| 德州市| 五峰| 平潭县| 田东县| 沙雅县| 长治市| 洪泽县|