posts - 495,comments - 227,trackbacks - 0

          構(gòu)建 SOAP 服務(wù)

          如果您覺得構(gòu)建 Web 服務(wù)客戶機的過程相當(dāng)簡單,事實的確如此。而就很多方面而言,構(gòu)建服務(wù)的過程也同樣簡單。

          總體過程

          創(chuàng)建 Axis2 Web 服務(wù)的整個過程涉及以下步驟:

          1. 創(chuàng)建服務(wù)清單
          2. 創(chuàng)建類
          3. 將其打包為 Axis 存檔文件
          4. 將 Axis 存檔文件上載到 Axis2 Web 應(yīng)用程序
          5. 重新啟動服務(wù)器(如果有必要)

          這就是全部步驟。讓我們首先從服務(wù)清單開始。





          回頁首


          創(chuàng)建清單

          服務(wù)清單告知 Axis2 應(yīng)用程序(就更大的范圍而言,應(yīng)用服務(wù)器)哪個請求與哪個類對應(yīng)。例如,可以如清單 22 中所示的那樣指定兩個服務(wù)函數(shù)。


          清單 22. 在清單中指定兩個服務(wù)函數(shù)
                              
          <service name="CMSService">
              <description>
                  This is a sample Web Service for the newspaper's
           Content Managment System.
              </description>
          
              <parameter name="ServiceClass" locked="false"
          >CMSService</parameter>
          
              <operation name="getNumberOfArticles">
                  <messageReceiver class=
          "org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/>
              </operation>
              <operation name="addArticle">
                  <messageReceiver class=
          "org.apache.axis2.receivers.RawXMLINOnlyMessageReceiver"/>
              </operation>
          </service>
          

          首先,定義服務(wù),提供其名稱和描述,并指定實際為請求服務(wù)的類。接下來,定義實際的操作。請注意,此示例指定了兩種不同類型的 messageReceiver。第一個 RawXMLINOutMessageReceiver 用于傳統(tǒng)的請求/響應(yīng)服務(wù)。第二個 RawXMLINOnlyMessageReceiver 用于單向消息。操作的名稱與有效負載的根元素以及要執(zhí)行的方法對應(yīng)。

          將此文件保存為 services.xml。

          接下來,讓我們創(chuàng)建實際的應(yīng)用程序。





          回頁首


          創(chuàng)建應(yīng)用程序

          讓我們首先創(chuàng)建模擬前面看到的 echo 函數(shù)的類(將直接返回原始有效負載的副本),如清單 23 中所示。


          清單 23. CMSService 類
                              
          import org.apache.axis2.om.OMElement;
          import javax.xml.stream.XMLStreamException;
          
          public class CMSService {
          
              public OMElement getNumberOfArticles(OMElement element)
                                        throws XMLStreamException {
          
                  element.build();
                  element.detach();
          
                  return element;
              }
          }
          

          要編譯此應(yīng)用程序,請確保 <axis2_home>/lib 中的所有 *.jar 文件都在您的 CLASSPATH 上。

          此應(yīng)用程序相當(dāng)簡單,僅包含一個與 getNumbereOfArticles 操作對應(yīng)的類。此函數(shù)和任何要作為操作的函數(shù)一樣,接收單個 OMElement 參數(shù)(表示有效負載)。此處,您將首先使用 build() 方法來確定已接收到所有數(shù)據(jù)——AXIOM 使用一個 pull 方法訪問數(shù)據(jù)——然后將元素從其當(dāng)前樹中分離,以便能夠?qū)⑵浞祷亍?/p>

          如果喜歡冒險,可以自由地部署服務(wù)訪問服務(wù),以訪問服務(wù)并查看結(jié)果。應(yīng)該看到與清單 24 中所示類似的結(jié)果輸出。


          清單 24. CMSService 類響應(yīng)
                              
          <cms:getNumberOfArticles><cms:category>classifieds</cms:category></cms:
          getNumberOfArticles>
          

          接下來讓我們了解如何實際處理數(shù)據(jù)。





          回頁首


          提取有效負載

          為了從有效負載提取信息,將使用與 DOM 非常類似的技術(shù)來對接收到的有效負載元素進行操作(請參見清單 25)。


          清單 25. 提取有效負載信息
                              
          ...
          import javax.xml.stream.XMLStreamException;
          
          public class CMSService {
              public OMElement getNumberOfArticles(OMElement element) 
                                    throws XMLStreamException {
                  element.build();
                  element.detach();
          
                  String rootName = element.getLocalName();
                  OMElement categoryElement = element.getFirstElement();
                  String categoryElementName = categoryElement.getLocalName();
                  String categoryValue = childElement.getText();
          
                  return element;
              }
          }
          

          請記住,有效負載的根是 getNumberOfArticles 函數(shù)接收的元素。在此情況下,將提取元素的名稱,然后移動到第一個元素子項(與第一個子項不同,后者可能是空格文本節(jié)點)并提取其名稱和值。請注意,使用的是 getText() 方法來提取實際上是 category 元素的文本節(jié)點子項的值。這無疑非常簡捷!





          回頁首


          創(chuàng)建并返回響應(yīng)

          最后,將需要使用從請求的有效負載提取數(shù)據(jù)來創(chuàng)建響應(yīng)。在本例中,將從第二個函數(shù)(在實際應(yīng)用程序中,該函數(shù)將進行一些其他的工作)提供響應(yīng)(請參見清單 26)。


          清單 26. 創(chuàng)建響應(yīng)
                              
          ...
          import javax.xml.stream.XMLStreamException;
          
          public class CMSService {
              public OMElement getNumberOfArticles(OMElement element) 
                                   throws XMLStreamException {
                  element.build();
                  element.detach();
          
                  String rootName = element.getLocalName();
                  OMElement childElement = element.getFirstElement();
                  String childName = childElement.getLocalName();
                  String categoryValue = childElement.getText();
          
                  SOAPFactory factory = OMAbstractFactory.getSOAP12Factory();
                  OMNamespace namespace = factory.createOMNamespace(
                                      "http://daily-moon.com/cms/", "resp");
                  OMElement resultElem = factory.createOMElement(
                                             "numberOfArticles",namespace);
          
                  String actualValue = 
                                   (articleCount(categoryValue)).toString();
                  resultElem.setText(actualValue);
          
                  return resultElem;
              }
          
              private Integer articleCount(String catId){
          
                 //Perform some function such as searching the CMS 
                 //database, and return the actual value.  For our 
                 //purposes, you'll hardcode it.
                 return new Integer(42);
          
              }
          }
          

          首先,創(chuàng)建將用于創(chuàng)建所有其他對象的工廠,然后創(chuàng)建將添加到響應(yīng)的有效負載的命名空間。接下來,創(chuàng)建實際結(jié)果元素,在本例中為名為 numberOfArticles 的元素。

          numberOfArticles 元素的內(nèi)容將為 articleCount() 函數(shù)返回的一個數(shù)字,在本例中,該函數(shù)可以為任何內(nèi)容。在實際的應(yīng)用程序中,將進行所需進行的任何工作來獲取此數(shù)據(jù)。獲取了此數(shù)據(jù)后,會將其設(shè)置為 numberOfArticles 元素的內(nèi)容,并直接返回該元素。

          現(xiàn)在剩下的就是部署服務(wù)了。





          回頁首


          部署服務(wù)

          為了部署服務(wù),需要創(chuàng)建一個 Axis 存檔文件。此文件和 *.jar 或 *.war 文件類似,實際是使用特殊文件擴展名(在本例中使用的是 .aar)的 zip 文件。請按照以下步驟創(chuàng)建此文件:

          1. 將 <AXIS2_HOME>/lib 目錄中的所有文件添加到 CLASSPATH 并編譯 CMSService.java 文件。
          2. 在與 CMSService.class 文件相同的目錄中創(chuàng)建名為 META-INF 的新目錄。
          3. 從包含 CMSService.class 文件的目錄中發(fā)出以下命令:<code type="section" width="100"> jar cvf CMSService.aar ./* </code> 應(yīng)該看到與以下類似的結(jié)果:<code type="section" width="100"> added manifest adding:CMSService.class(in = 513) (out= 330)(deflated 35%) adding:CMSService.java(in = 328) (out= 182)(deflated 44%) ignoring entry META-INF/ adding:META-INF/services.xml(in = 391) (out= 229)(deflated 41%) </code>
          4. 使用安裝示例服務(wù)中列出的步驟將此服務(wù)添加到服務(wù)器上。(如果看到 Web 接口上有 Servlet 錯誤,請確保登錄到了 Axis2 應(yīng)用程序。如果會話已過期,應(yīng)用程序?qū)⒉灰欢〞ㄖ赡軙苯语@示錯誤。)
          5. 如果有必要,請重新啟動 Geronimo。(將可能不必在添加服務(wù)后進行此操作,但在進行更改后可能必須這樣做。)

          如果單擊 View services 鏈接,應(yīng)該看到與圖 4 中所示類似的內(nèi)容。


          圖 4. 可用服務(wù)
          可用服務(wù)?




          回頁首


          訪問服務(wù)

          現(xiàn)在已經(jīng)完成了服務(wù)構(gòu)建,接下來要通過客戶機對其進行訪問。對前面創(chuàng)建的 ClassifiedClient.java 文件進行以下更改(請參見清單 27)。


          清單 27. 修改 ClassifiedClient
                              
          ...
          public class ClassifiedClient {
              private static EndpointReference targetEPR = 
                   new EndpointReference(
                     "http://localhost:8080/axis2/services/CMSService");
          
              public static OMElement getEchoOMElement() {
                  SOAPFactory fac = OMAbstractFactory.getSOAP12Factory();
                  OMNamespace omNs = fac.createOMNamespace(
                          "http://daily-moon.com/cms", "cms");
                  OMElement method = fac.createOMElement("getNumberOfArticles", 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();
                      Options options = new Options();
                      options.setTo(targetEPR);
                      options.setTransportInProtocol(Constants.TRANSPORT_HTTP);
          
                      ServiceClient sender = new ServiceClient();
                      sender.setOptions(options);
                      OMElement result = sender.sendReceive(payload);
          
                      String response = result.getText();
                      System.out.println("There are "+response+" classifieds at the moment.");
          
                  } catch (Exception e) { //(XMLStreamException e) {
          System.out.println(e.toString());
                  }
              }
          }
          

          編譯并運行了此應(yīng)用程序后,應(yīng)看到清單 28 中所示的響應(yīng)。


          清單 28. ClassifiedClient 響應(yīng)
                              
          There are 42 classifieds at the moment.
          





          回頁首

          單向服務(wù)

          繼續(xù)討論之前,讓我們了解一下處理單向服務(wù)(而非請求/響應(yīng)服務(wù))時涉及到的不同之處。

          服務(wù)

          創(chuàng)建單向服務(wù)非常簡單。此過程與創(chuàng)建請求/響應(yīng)服務(wù)完全類似,至少不會實際返回任何內(nèi)容。例如,可以為 CMSService 類創(chuàng)建 addArticle 操作,如圖 29 中所示。


          清單 29. CMSServiceclass 中的 addArticle 操作
          ...
              private Integer articleCount(String catId){
          ...
              }
          
              public void addArticle(OMElement element) 
                                       throws XMLStreamException{
                 element.build();
                 System.out.println(element);
              }
          }
          

          在 services.xml 文件中,將 addArticle 操作指定為“in only”操作,因此不會等待返回任何內(nèi)容,但即使這樣,也能看到會實際發(fā)生一些事項,會在命令行輸出接收到的有效負載。您將在 Geronimo 窗口中看到此信息。

          在實際應(yīng)用程序中,此方法將從有效負載提取信息,并會實際添加到某種類型的數(shù)據(jù)庫或其他存儲庫。





          回頁首


          客戶機

          此服務(wù)的客戶機也與請求/響應(yīng)服務(wù)所使用的服務(wù)類似(請參見清單 30)。


          清單 30. 創(chuàng)建客戶機
                              
          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 org.apache.axis2.SOAP.SOAPFactory;
          import org.apache.axis2.om.OMAbstractFactory;
          import org.apache.axis2.om.OMNamespace;
          
          public class AddArticleClient {
              private static EndpointReference targetEPR = 
                   new EndpointReference(
                       "http://localhost:8080/axis2/services/CMSService");
          
              private static OMElement getOMElement(){
          
                  SOAPFactory fac = OMAbstractFactory.getSOAP12Factory();
                  OMNamespace omNs = fac.createOMNamespace(
                          "http://daily-moon.com", "cms");
                  OMElement method = fac.createOMElement("addArticle", omNs);
          
                  OMElement category = fac.createOMElement("category", omNs);
                  category.setText("classifieds");
          
                  OMElement subcategory = 
                                  fac.createOMElement("subcategory", omNs);
                  category.setText("wantads");
          
                  OMElement adtext = fac.createOMElement("article", omNs);
                  adtext.setText("Do you  have good head for numbers"+
                        " and a great deal of patience?  Do you like"+
                        " to sit for hours sorting objects by their"+
                        " size?  If so, then you could be the"+
                        " next goober counter in the world famous"+
                        " Murphy Brothers peanut factory. "+
                        " Willingness to dress up as our mascot"+
                        " helpful, but not required.");
          
                  method.addChild(category);
                  method.addChild(subcategory);
                  method.addChild(adtext); 
          
                  return method;
          
              }
          
              public static void main(String[] args) {
                  try {
                      OMElement payload = AddArticleClient.getOMElement();
                      ServiceClient serviceClient = new ServiceClient();
          
                      Options options = new Options();
                      serviceClient.setOptions(options);
                      options.setTo(targetEPR);
          
                      serviceClient.fireAndForget(payload);
          
                  } catch (AxisFault axisFault) {
                      axisFault.printStackTrace();
                  }
              }
          
          }
          

          盡管有效負載不同,但正如您在 getOMElement() 方法中看到的,編程方面目前的唯一真正的更改是使用 fireAndForget() 方法替代 sendReceive() 方法。此方法并不會返回響應(yīng)。

          如果運行此客戶機,應(yīng)該在 Geronimo 窗口中看到與圖 5 中所示類似的輸出。


          圖 5. 命令行輸出
          命令行輸出




          回頁首

          posted on 2006-12-29 18:39 SIMONE 閱讀(854) 評論(0)  編輯  收藏 所屬分類: AXISJAVA
          主站蜘蛛池模板: 阿瓦提县| 山丹县| 南丹县| 鹰潭市| 奈曼旗| 西贡区| 得荣县| 德清县| 米林县| 阜城县| 奈曼旗| 保德县| 芮城县| 宁武县| 临漳县| 视频| 敦化市| 通辽市| 博乐市| 当雄县| 巴东县| 南京市| 临汾市| 贵阳市| 金乡县| 胶南市| 房山区| 当阳市| 巴林右旗| 沙田区| 诸暨市| 田东县| 麻阳| 泰安市| 龙陵县| 唐海县| 灵璧县| 泸溪县| 太白县| 夏河县| 临夏市|