日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

了解 Web 服務(wù)規(guī)范,第 1 部分: SOAP

 shaobin0604@163.com 2006-09-16

2006 年 9 月 11 日

面向服務(wù)的體系結(jié)構(gòu)(Service-Oriented Architectures,SOA)當(dāng)前強(qiáng)調(diào)的重點在 Web 服務(wù)上,但很容易被所傳播的各種信息搞得昏頭轉(zhuǎn)向。本系列教程將對主要 Web 服務(wù)規(guī)范進(jìn)行全面說明,從簡單對象訪問協(xié)議(Simple Object Access Protocol,SOAP)一直介紹到 WS Business Process Execution Language (WS-BPEL)。本教程將介紹 Web 服務(wù)和 SOAP 基本概念,并說明如何構(gòu)建 SOAP 服務(wù)器和客戶機(jī)。

開始之前

本系列教程將說明構(gòu)建一家假想的報社 Daily Moon 的基于 Web 訪問的工作流系統(tǒng)的詳細(xì)步驟。主要針對的是希望了解有關(guān) Web 服務(wù)的更多信息的開發(fā)人員,以便他們能更為高效地創(chuàng)建應(yīng)用程序。非技術(shù)用戶也可以從中獲得一些好處,因為在討論如何編程前對相關(guān)概念進(jìn)行了解釋。

您應(yīng)該具有基本編程知識,如果希望按照實際編程示例進(jìn)行操作,還需要一定的 Java 知識。我們將討論 XML(但沒有必要對其進(jìn)行深入討論),并將涵蓋任何必要的概念。

關(guān)于本系列

本系列教程以假想的報社 Daily Moon 為例,為了提高在競爭激烈的環(huán)境中的生產(chǎn)力,其員工將使用各種 Web 服務(wù)來創(chuàng)建工作流系統(tǒng),我們將在此過程中講述各個 Web 服務(wù)基本概念。

第 1 部分比較簡單,將說明 Web 服務(wù)背后的基本概念,并演示如何使用 SOAP(以后要討論的大部分內(nèi)容的基礎(chǔ)規(guī)范)來將 Classifieds Department 連接到內(nèi)容管理系統(tǒng)。

本系列以后的部分將以這些基本概念為基礎(chǔ):

  • 第 2 部分進(jìn)一步深入說明如何使用 Web 服務(wù)描述語言(Web Services Description Language,WSDL)定義 Web 服務(wù)預(yù)期產(chǎn)生的消息,從而使團(tuán)隊更方便地創(chuàng)建服務(wù)以及連接到服務(wù)的客戶機(jī)。
  • 在第 3 部分中,團(tuán)隊希望準(zhǔn)備一系列服務(wù),并希望能方便地查找這些服務(wù)。與此對應(yīng),統(tǒng)一描述、發(fā)現(xiàn)和集成(Universal Description, Discovery and Integration,UDDI)提供了可用服務(wù)的可搜索注冊中心,以便將自己的服務(wù)發(fā)布給其他人。
  • 第 4 部分和第 5 部分討論 WS-Security 和 WS-Policy,將詳細(xì)說明如何保證該報社的服務(wù)的安全,以及團(tuán)隊為了訪問這些剛提供了安全保護(hù)的服務(wù)需要進(jìn)行哪些更改。
  • 第 6 部分重點討論的是互操作性,因為必須從單個系統(tǒng)訪問來自幾個不同實現(xiàn)的服務(wù)。第 6 部分討論了在 WS-I 證書中涉及的要求和測試。
  • 最后,第 7 部分演示了如何使用業(yè)務(wù)流程執(zhí)行語言(Business Process Execution Language,WS-BPEL)來從各個服務(wù)創(chuàng)建復(fù)雜應(yīng)用程序。

接下來讓我們更為詳細(xì)了解一下本教程中將討論的內(nèi)容。





回頁首


關(guān)于本教程

本教程將向您以及假想的 Daily Moon Classifieds Department 介紹 Web 服務(wù)的概念。您將了解該團(tuán)隊如何與現(xiàn)有 Web 服務(wù)系統(tǒng)集成以及如何創(chuàng)建服務(wù)的詳細(xì)過程。重點將是簡單對象訪問協(xié)議 (SOAP)。

在本教程中,您將了解以下內(nèi)容:

  • Web 服務(wù)的基本概念
  • XML 的基本知識
  • SOAP 消息的結(jié)構(gòu)和用途
  • 如何安裝應(yīng)用服務(wù)器以在其上運行 Web 服務(wù)應(yīng)用程序。
  • 如何將 Web 服務(wù)實現(xiàn)安裝到應(yīng)用服務(wù)器中
  • 如何以編程方式創(chuàng)建 SOAP 消息。
  • 如果使用 Java 和 Apache Axis2 為基于 SOAP 的 Web 服務(wù)創(chuàng)建客戶機(jī)
  • 如何使用 Java 和 Apache Axis2 創(chuàng)建基于 SOAP 的 Web 服務(wù)

在本教程中,Classifieds Department 將通過創(chuàng)建客戶機(jī)來與內(nèi)容管理系統(tǒng)集成。您還將了解該部門與之交互的一個服務(wù)的創(chuàng)建過程。編程示例采用 Java 語言,并使用了 Apache Axis2 項目,但其中的概念幾乎適用于任何語言和環(huán)境。





回頁首


先決條件

為了按照本教程所示的處理代碼,您需要有以下軟件:

  • Apache Geronimo 或其他應(yīng)用服務(wù)器。您將在本教程中創(chuàng)建各種 Web 服務(wù),需要在其上運行這些服務(wù)的應(yīng)用程序。當(dāng)然,由于 Web 服務(wù)應(yīng)當(dāng)可互操作,因此使用何種應(yīng)用服務(wù)器并不重要。在本教程中,我們將演示如何安裝和使用 Apache Geronimo(IBM? WebSphere? Community Edition 也是構(gòu)建于其上的)。還可以使用 WebSphere Application Server 等其他應(yīng)用服務(wù)器。可以從 Apache Geronimo Downloads 站點下載 Apache Geronimo。
  • Apache Axis2 或其他 SOAP 實現(xiàn)??梢允謩觿?chuàng)建 SOAP 消息,也可以手動對其進(jìn)行解釋,但手邊如果有一個可用實現(xiàn)就會方便得多。您將使用的是 Apache Axis2,其中包含了各種 SOAP 相關(guān)的 API,可極大地簡化您的工作??梢栽谝韵戮W(wǎng)址下載 Apache Axis2:Apache.org。本教程使用的是 0.94 版,但應(yīng)該也能使用更高版本。
  • Java? 2 Standard Edition 1.4 或更高版本。這兩個工具都基于 Java,和將在本教程中構(gòu)建的服務(wù)和客戶機(jī)一樣??梢詮?a href="http://java./j2se/1.5.0/download.jsp">此處下載 J2SE SDK。
  • 另外,還需要 Web 瀏覽器和文本編輯器,但我想您已經(jīng)有了這兩個工具。如果愿意,還可以使用 Eclipse 之類的 IDE,但由于本教程的重點是技術(shù)而不是工具,因此我將使用文本編輯器和命令行來編輯和編譯文件。

什么是 Web 服務(wù)?

首先,讓我們從總體上了解一下什么是 Web 服務(wù),以及它們?yōu)楹螌浖_發(fā)重要。

究竟為什么重要呢?

如果您沒有聽說過有關(guān)面向服務(wù)的體系結(jié)構(gòu) (SOA) 和 Web 服務(wù)的大量信息,您就不會閱讀本文,那么問題就應(yīng)該是,為什么此內(nèi)容這樣重要?答案是,此內(nèi)容之所以重要,是因為這是應(yīng)用程序彼此進(jìn)行通信的方式的典型變化。SOAs 已經(jīng)存在很長很長時間了。SOA 最初主要由中間件應(yīng)用程序組成,至少進(jìn)行連接的兩端都屬于同一種類型的中間件。另一方面,Web 服務(wù)由一組標(biāo)準(zhǔn)組成,用于在不需要特定類型的中間件、編程語言甚至操作系統(tǒng)的前提下讓各種不同的系統(tǒng)進(jìn)行通信。接下來,讓我們了解一下其發(fā)展的歷程。





回頁首


傳統(tǒng)應(yīng)用程序

首先從計算機(jī)發(fā)明開始,當(dāng)時給人感覺非常不錯。計算機(jī)能執(zhí)行奇跡般的任務(wù),可實現(xiàn)很多手動工作的自動化,包括復(fù)雜的計算、財務(wù)工作等等很多其他任務(wù)。

但傳統(tǒng)應(yīng)用程序是“豎井”(Silo) 型的。人力資源應(yīng)用程序無法與財務(wù)應(yīng)用程序真正通信,而后者又無法和分布應(yīng)用程序進(jìn)行真正的通信。所有這些應(yīng)用程序都有獨立的領(lǐng)域,在獨立的計算機(jī)上運行,盡管很有用,但并不能很好地在彼此間共享數(shù)據(jù)。當(dāng)時可以選擇對批處理流程進(jìn)行連接,以將數(shù)據(jù)從一個系統(tǒng)移動到另一個系統(tǒng),但這并不適合進(jìn)行實時集成。





回頁首


分布式計算

在我們的進(jìn)化鏈中的第二步是分布式計算。分布式計算允許不同的應(yīng)用程序彼此進(jìn)行通信(即使位于不同的計算機(jī)上也是如此)。CORBA、MTS 和 Enterprise Java Bean (EJB) 等技術(shù)提供了包含各種類別的注冊中心的系統(tǒng),因此應(yīng)用程序可以找到其希望與之進(jìn)行交互的組件,然后像調(diào)用本地的組件一樣調(diào)用這些組件。

這些系統(tǒng)由可同時滿足這兩個要求的中間件(或更具體一些,面向消息的中間件)提供支持。現(xiàn)在能以特定的方式構(gòu)建應(yīng)用程序,即使位于不同的地理位置,也能訪問其他系統(tǒng)上的資源。

但仍然有一個問題。雖然系統(tǒng)可以自由地與系統(tǒng)內(nèi)的任何對象進(jìn)行通信,但仍然是一個封閉的系統(tǒng)。至少,客戶機(jī)應(yīng)用程序必須與服務(wù)器應(yīng)用程序使用相同的技術(shù)。另外,通常并不會將系統(tǒng)設(shè)計為從創(chuàng)建其的個體組織外進(jìn)行訪問。





回頁首


Web 服務(wù)

此進(jìn)化鏈中下一個幾乎不可避免的鏈接點就是 Web 服務(wù)。“Web 服務(wù)”基于 XML 和 HTTP(大多數(shù)情況下),對很多人具有不同的含義,但在此處,我們要將 Web 服務(wù)作為系統(tǒng)間基于 SOAP 的消息交換進(jìn)行討論。

這些消息由 XML 組成(XML 是一個基于文本的開放標(biāo)準(zhǔn)),可由來自任何應(yīng)用程序(任何設(shè)計為接收此類消息的應(yīng)用程序)的任何人進(jìn)行訪問。這就擴(kuò)展了應(yīng)用程序的范圍,從而包含任何可通過網(wǎng)絡(luò)對其進(jìn)行訪問的任何人。(如果這讓您開始考慮安全問題,不要緊,您將在本系列的第 4 部分了解如何處理這方面的問題。)

基于 SOAP 的 Web 服務(wù)將要發(fā)送與清單 1 中所示類似的 XML 消息。


清單 1. 基于 SOAP 的 Web 服務(wù)

            <SOAPenv:Envelope
            xmlns:SOAPenv="http://schemas.xmlSOAP.org/SOAP/envelope/"
            xmlns:xsd="http://www./2001/XMLSchema"
            xmlns:xsi="http://www./2001/XMLSchema-instance">
            <SOAPenv:Body>
            <req:getNumberOfArticles xmlns:req="http:///CMS/">
            <req:category>classifieds</req:category>
            </req:getNumberOfArticles>
            </SOAPenv:Body>
            </SOAPenv:Envelope>
            

這些消息將從一個系統(tǒng)進(jìn)入另一個系統(tǒng)(通常通過 HTTP)。接收系統(tǒng)對消息進(jìn)行解釋,進(jìn)行應(yīng)該進(jìn)行從處理,然后發(fā)送另一個 SOAP 消息作為響應(yīng)。

這個系統(tǒng)很簡單,正因為如此,有很多企業(yè)級計算方面的內(nèi)容都尚未涉及。幸運的是,其中的很多方面已被納入考慮范疇,且具有自己的相關(guān)規(guī)范來確定此事務(wù)應(yīng)如何進(jìn)行,以包含傳統(tǒng)的面向消息的中間件的很多安全和其他方面的內(nèi)容。





回頁首


其他類型的 Web 服務(wù)

如果我沒有說明 SOAP 并不是唯一的處理 Web 服務(wù)的方法,那就有些失職了。有很多其他基于 XML 的方法用于在系統(tǒng)間發(fā)送信息,其中一些適用于企業(yè)環(huán)境,而另一些則不適合此用途。例如,Amazon 是為公眾提供對其系統(tǒng)的 Web 服務(wù)訪問的第一批基于 Web 服務(wù)的公司之一。Amazon 包含了一個基于 SOAP 的服務(wù),但也提供了一個基于 Representational State Transfer (REST) 的服務(wù)。

REST 是一種 Web 服務(wù)類型,其中,用戶直接訪問 URL,相應(yīng)的響應(yīng)是與清單 2 中所示類似的簡單 XML 文檔。


清單 2. REST 響應(yīng)

            <currentArticles>
            <category>classifieds</category>
            <subcategory>forsale</subcategory>
            <article id="888204">
            <articleHeadline></articleHeadline>
            <articleText>30 ft ladder, only used once.  Willing to let
            go for half it‘s worth. Has slight dent near the middle.
            Harder than a human head. $150 OBO.</articleText>
            </article>
            <article id="888242">
            <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>
            </article>
            </currentArticles>
            

這些消息并沒有特定的格式??梢詾槿魏螖?shù)據(jù)。

另一種 Web 服務(wù)類型要使用 XML-RPC 之類的標(biāo)準(zhǔn)。在這種情況下,命令將通過與清單 3 中所示類似的 XML 發(fā)送到系統(tǒng)。


清單 3. XML-RPC

            <?xml version="1.0"?>
            <methodCall>
            <methodName>CMS.getNumberOfArticles</methodName>
            <params>
            <param>
            <value><string>classifieds</string></value>
            </param>
            <param>
            <value><string>forsale</string></value>
            </param>
            </params>
            </methodCall>
            

其響應(yīng)將采用類似的格式。

在學(xué)習(xí)使用 SOAP 的過程中,您可以會打心底里認(rèn)為 REST 和 XML-RPC 比基于 SOAP 的系統(tǒng)要簡單得多。的確如此。在某些情況下 REST 和 XML-RPC 比 SOAP 系統(tǒng)簡單。不過,我們討論的不是在網(wǎng)站上顯示天氣的簡單應(yīng)用程序。我們此處討論的是企業(yè)級應(yīng)用程序,而企業(yè)級的應(yīng)用程序需要企業(yè)級的屬性,如安全、互操作性等等。這些功能在有關(guān)基于 SOAP 的 Web 服務(wù)的其他規(guī)范中進(jìn)行了定義,因而,從長期來看,SOAP 更適合用于企業(yè)級應(yīng)用程序。

讓我們了解一下這些規(guī)范。





回頁首


基本 Web 服務(wù)規(guī)范

Web 服務(wù)規(guī)范通常歸為兩類:基本 Web 服務(wù)規(guī)范和擴(kuò)展 Web 服務(wù)規(guī)范?;疽?guī)范有:

  • SOAP:SOAP 規(guī)范是所有基于 SOAP 的 Web 服務(wù)的基礎(chǔ),詳細(xì)說明了實際消息的格式。其中還詳細(xì)說明了應(yīng)用程序應(yīng)如何對待消息的特定方面(如“Header”中的元素),從而可以創(chuàng)建特定類型的應(yīng)用程序,使其中的消息在達(dá)到最終的目的地前在多個中間層之間進(jìn)行傳遞。本教程將涵蓋 SOAP 規(guī)范的內(nèi)容。
  • WDSL:Web 服務(wù)描述語言是詳細(xì)說明描述基于 SOAP 的 Web 服務(wù)的標(biāo)準(zhǔn)方式的規(guī)范,包括消息應(yīng)采用的形式以及應(yīng)將其發(fā)送到何處。其中還詳細(xì)說明了此類消息的響應(yīng)。當(dāng)與相應(yīng)的工具結(jié)合使用時,WSDL 允許以編程方式創(chuàng)建對 Web 服務(wù)的調(diào)用,甚至不用知道所查找的 Web 服務(wù)是什么;應(yīng)用程序可以從 WSDL 文件中提取這些詳細(xì)信息,并提供要使用的編程接口。我們將在本系列的第 2 部分討論 WSDL。
  • UDDI:統(tǒng)一描述、發(fā)現(xiàn)和集成 (Universal Description, Discovery and Integration) 是一項從最初提出后發(fā)生了一系列變化的標(biāo)準(zhǔn)。其最初的目的是為了給各個公司提供在全球注冊中心中注冊服務(wù)并在此注冊中心中搜索可能想使用的服務(wù)的機(jī)制。不過,由于很多公司對于將其系統(tǒng)對外開放的問題上都相當(dāng)保守,這個目標(biāo)并沒有完全實現(xiàn)。但是,很多公司已將 UDDI 作為內(nèi)部的服務(wù)及服務(wù)信息注冊中心使用,本系列第 3 部分將對其使用進(jìn)行詳細(xì)論述。

以上是一些基礎(chǔ)知識。另外差不多還有數(shù)十種擴(kuò)展標(biāo)準(zhǔn),可進(jìn)一步擴(kuò)展基于 SOAP 的服務(wù)的用途。





回頁首


擴(kuò)展 Web 服務(wù)規(guī)范

總共有數(shù)十種 WS-* 規(guī)范,其中幾種對企業(yè)尤為有用。即:

  • WS-Security:此規(guī)范處理加密和數(shù)字簽名,允許創(chuàng)建特定類型的應(yīng)用程序,以防止竊聽消息,且能實現(xiàn)不可否認(rèn)功能。本系列的第 4 部分將討論 WS-Security。
  • WS-Policy:此規(guī)范對 WS-Security 進(jìn)行了擴(kuò)展,允許更具體地說明誰可以采用何種方式使用服務(wù)。本系列的第 5 部分將討論 WS-Policy。
  • WS-I:盡管 Web 服務(wù)應(yīng)設(shè)計成具有互操作性,但在實際中,各個規(guī)范對不同實現(xiàn)的解釋的靈活性常常足以導(dǎo)致出現(xiàn)問題。WS-I 提供了一組可用于防止出現(xiàn)各種問題的標(biāo)準(zhǔn)和實踐,并提供了標(biāo)準(zhǔn)化測試來檢查問題。WS-I 是本系列的第 6 部分將要討論的主題。
  • WS-BPEL:單個服務(wù)很好處理,但應(yīng)用程序在大多數(shù)情況下則較難處理。企業(yè)級計算要求至少將多個服務(wù)組合為一個完整的系統(tǒng),而 WS-BPEL 提供了用于指定創(chuàng)建此類系統(tǒng)所必需的交互(如分支和并發(fā)處理)。本系列的第 7 部分將討論 WS-BPEL。

在 Web 服務(wù)中扮演重要角色的其他規(guī)范將不在本系列中討論,其中包括 WS-ReliableMessaging(允許確定檢索一個且僅一個消息副本)、Web 服務(wù)資源框架 (WSRF)(允許使用在無狀態(tài)環(huán)境中非常重要的狀態(tài))和 Web 服務(wù)分布式管理 (WSDM)(討論 Web 服務(wù)的管理和使用問題)。可以在本教程的參考資料中獲得有關(guān)這些規(guī)范及其他規(guī)范的更多信息。





回頁首


將要完成的工作

在本教程中,您將了解 Daily Moon 報社的 Classifieds Department 如何將其自己的系統(tǒng)與內(nèi)容管理系統(tǒng)使用的基于 Web 服務(wù)的接口進(jìn)行集成。將創(chuàng)建一個應(yīng)用程序,以創(chuàng)建基于 SOAP 的消息,將其發(fā)送到服務(wù),然后檢索響應(yīng)。完成了此工作后,您將了解如何創(chuàng)建服務(wù)來響應(yīng)請求并發(fā)送自己的響應(yīng)。將通過創(chuàng)建 Java 應(yīng)用程序(使用或不使用應(yīng)用服務(wù)器)來完成此工作。
 

設(shè)置

現(xiàn)在已經(jīng)了解了所涉及的基本原理,接下來讓我們看看如何實際創(chuàng)建應(yīng)用程序。首先要使所需軟件就緒。

設(shè)置 Apache Geronimo

將需要的第一個軟件是 Web 應(yīng)用服務(wù)器。為什么需要 Web 應(yīng)用服務(wù)器呢?因為您會發(fā)現(xiàn),沒有 Web 應(yīng)用服務(wù)器很難提供 Web 服務(wù)。Web 應(yīng)用服務(wù)器將偵聽請求,將這些請求轉(zhuǎn)換為實際服務(wù)可以理解的內(nèi)容,然后進(jìn)行任何必要的處理。

此過程中幾乎可以使用任何 Web 服務(wù)器,但在大多數(shù)情況下都將使用能簡化此過程的軟件(通常要求使用某種類型的實際應(yīng)用服務(wù)器)。具體來說,本教程假定您將使用 Java 應(yīng)用服務(wù)器。(實際上,將使用 J2EE 應(yīng)用服務(wù)器。)

對于 J2EE 服務(wù)器,有很多選擇;在本例中將使用 Apache Geronimo。Geronimo 是作為 IBM WebSphere Application Server Community Edition 基礎(chǔ)的開放源代碼應(yīng)用服務(wù)器。Geronimo 很小,非常易于安裝和管理。它還能與其他 Apache 項目(如稍后將安裝的 Axis2)一起良好地工作。

請下載相關(guān)軟件(請參閱先決條件)并將文件提取到目標(biāo)目錄中。您會發(fā)現(xiàn)所提取的文件中包含自身的目錄,因此可以直接對其進(jìn)行解包,并可將其移動到任何位置。任何目錄都是可接受的,但要避免名稱中包含空格的目錄,如“Program Files”、“Documents and Settings”或其子目錄。例如,本教程的測試安裝使用的是 e:\geronimo-1.0。

就是這里。已經(jīng)在其中安裝了 Geronimo。這不是很簡單么?

要啟動此服務(wù)器,請打開命令提示符窗口,并執(zhí)行以下命令:

cd <GERONIMO_HOME>
java -jar server.jar

要確保服務(wù)器正在運行,請打開瀏覽器,并指向清單 4 中所示的 URL:

            http://localhost:8080
            

應(yīng)該看到與圖 1 中所示類似的頁面。

現(xiàn)在讓我們開始安裝 Web 服務(wù)軟件。





安裝 Apache Axis2

完全可能從普通 HTTP 服務(wù)器提供 Web 服務(wù)。不過,這樣并不明智。處理 SOAP 消息需要進(jìn)行很多工作,但沒有必要完全從頭進(jìn)行所有工作。Apache Axis 項目幾年前就對此任務(wù)進(jìn)行了簡化,創(chuàng)建了可方便地創(chuàng)建和處理 Web 服務(wù)的環(huán)境。該軟件包含了多個應(yīng)用程序,可幫助從普通項目創(chuàng)建 Web 服務(wù),從 Web 服務(wù)創(chuàng)建 Java 對象,并對二者進(jìn)行處理。Apache 小組已推出了 Axis 的新版本 Axis2,該版本繼承了 Axis 上的所有已有功能,并通過更改體系結(jié)構(gòu)實現(xiàn)了更大的靈活性,從而將其推向了一個新的高度。這很重要,因為 Web 服務(wù)規(guī)范隨時都在增加。Axis2 的構(gòu)造允許它更方便與 WSS4J、Apache 的 WS-Security 實現(xiàn)等項目集成。由于我們將在以后使用這些項目,因此請現(xiàn)在安裝 Axis2(有關(guān)下載信息,請參閱先決條件)。

請確保同時下載 Binary Distribution 和 War Distribution。前者將幫助構(gòu)建客戶機(jī),而后者用于幫助構(gòu)建服務(wù)。

要將 Axis2 安裝到 Web 服務(wù)器中,請將 axis2.war 文件復(fù)制到 Geronimo 的 deploy 目錄。(您將需要確保已經(jīng)至少啟動過 Geronimo 一次,才能保證存在此目錄。)Geronimo 將自動檢測其是否存在,因此不必手動部署任何內(nèi)容。





驗證 Axis 的安裝

要確保已經(jīng)恰當(dāng)安裝了所有內(nèi)容,請將瀏覽器指向 http://localhost:8080/axis2/index.jsp 并單擊 Validate。

應(yīng)該看到與圖 2 中所示類似的頁面。

在繼續(xù)本教程的其他內(nèi)容前,請確保成功安裝了 Axis。





安裝示例服務(wù)

將要編寫的第一個應(yīng)用程序是客戶機(jī),因此將需要其可訪問的服務(wù)。幸運的是,Axis2 分發(fā)版提供了若干此類服務(wù)。首先,將按照以下所示安裝 MyService 服務(wù):

  1. 通過將瀏覽器指向 http://localhost:8080/axis2/Login.jsp 并登錄,從而通過身份驗證。缺省用戶名和密碼分別為 adminAxis2。
  2. 單擊 Upload service>Browse。
  3. 導(dǎo)航到 MyService.aar 文件??梢栽跇?biāo)準(zhǔn) Axis2 分發(fā)版的 samples\userguide 目錄下找到該文件。單擊 OK。
  4. 單擊 Upload。

應(yīng)該看到一個通知,指示服務(wù)已添加(請參閱圖 3)。在缺省情況下,Axis2 包含“熱部署”功能,因此不必進(jìn)行任何操作來激活。

現(xiàn)在,讓我們了解一下將要構(gòu)建的內(nèi)容。
 

理解 SOAP

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

XML 簡介

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

XML 是一種“標(biāo)記語言”,即給出了一種提供實際內(nèi)容的附加信息的方式。此信息以“標(biāo)記”的形式提供,這些標(biāo)記用于指示“元素”。例如,考慮一下清單 5 中所示的簡單 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>
            

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

            <?xml version=‘1.0‘ ?>
            <env:Envelope xmlns:env="http://www./2003/05/SOAP-envelope">
            <env:Header>
            </env:Header>
            <env:Body>
            <cms:getNumberOfArticles xmlns:cms="http://www./cms">
            <cms:category>classifieds</cms:category>
            <cms:subcategory>forsale</cms:subcategory>
            </cms:getNumberOfArticles>
            </env:Body>
            </env:Envelope>
            

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

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





SOAP 信封

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

            <?xml version=‘1.0‘ ?>
            <env:Envelope xmlns:env="http://www./2003/05/SOAP-envelope">
            <env:Header>
            </env:Header>
            <env:Body>
            </env:Body>
            </env:Envelope>
            

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





SOAP Header

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

            <?xml version=‘1.0‘ ?>
            <env:Envelope xmlns:env="http://www./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>
            

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

接下來讓我們看看實際的有效負(fù)載。





SOAP 體

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

            <?xml version=‘1.0‘ ?>
            <env:Envelope xmlns:env="http://www./2003/05/SOAP-envelope">
            <env:Header>
            ...
            </env:Header>
            <env:Body>
            <cms:addArticle xmlns:cms="http://www./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ù)載很簡單,其中包含將文章添加到 Daily Moon 的內(nèi)容管理系統(tǒng)的指令。

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





樣式和編碼

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

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

            <env:Envelope xmlns:env="http://www./2003/05/SOAP-envelope">
            <env:Header>
            

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

            <env:Envelope xmlns:env="http://www./2003/05/SOAP-envelope">
            <env:Header>
            </env:Header>
            <env:Body>
            <cms:addArticle xmlns:cms="http://www./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 樣式的一個變體就是與上面看到的 RPC/literal 相對的 RPC/encoded。在這種情況下,消息中包含類型信息,如清單 13 中所示。

            <?xml version=‘1.0‘ ?>
            <env:Envelope xmlns:env="http://www./2003/05/SOAP-envelope">
            <env:Header>
            </env:Header>
            <env:Body>
            <cms:addArticle xmlns:cms="http://www./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>
            

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

            <?xml version=‘1.0‘ ?>
            <env:Envelope xmlns:env="http://www./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)行。例如,所有對特定 URL 或端點的調(diào)用都可能指向特定的操作。另外,從技術(shù)上講,可以使用 document/encoded 樣式,但目前還沒有人這樣做,因此可以將其忽略。

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





消息交換模式

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

  • 請求/響應(yīng):在請求/響應(yīng)模式種,以 SOAP 消息的形式發(fā)送請求,然后直接等待發(fā)送回響應(yīng)。請求可以為同步的,也可以是異步的。
  • 單向消息傳遞:這種情況也稱為“Fire and Forget”方法,發(fā)送請求但并不等待響應(yīng)。可以在僅傳遞信息時或并不關(guān)心接收者對此如何響應(yīng)時使用此方法。
現(xiàn)在,請注意并沒有使用術(shù)語“客戶機(jī)”和“服務(wù)器”。之所以這樣,是因為這些消息交換模式幾乎可以用于創(chuàng)建與上面提到的方法類似的任意數(shù)量的不同備選方法。例如,可以發(fā)送一條請求,然后依靠接收者對其進(jìn)行處理,并在將來完成應(yīng)完成的工作時發(fā)送一條消息。為此,將使用多個單向消息的組合,因此談“客戶機(jī)”和“服務(wù)器”并不合理,因為每個消息都有其接收方和發(fā)送方,所謂的客戶機(jī)和服務(wù)器的位置會發(fā)生對換。
 

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

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

以前的老方式

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

注意:為了編譯并運行此客戶機(jī),將需要 SAAJ 實現(xiàn)(如原始 Axis 軟件)??梢詮?http://ws./axis/ 下載 Axis。據(jù)說 Axis2 0.95 也包含此實現(xiàn),但本教程未針對其進(jìn)行測試。

            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());
            }
            }
            }
            

請注意,您要直接創(chuàng)建 SOAPEnvelope、SOAPBody 等內(nèi)容??梢韵蛳Ⅲw添加 echocategory 等元素。將從其中創(chuàng)建連接,進(jìn)行調(diào)用,同樣也能遍歷 SOAP 消息的結(jié)構(gòu)來獲取實際的內(nèi)容。如果要運行此客戶機(jī),應(yīng)該看到與清單 16 中所示類似的響應(yīng)。

            REQUEST:
            <SOAPenv:Envelope xmlns:SOAPenv=
            "http://schemas.xmlSOAP.org/SOAP/envelope/"
            xmlns:xsd="http://www./2001/XMLSchema"
            xmlns:xsi="http://www./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)行的所有工作實際就是對其所接收到的請求進(jìn)行應(yīng)答,通過這一點可以很好地了解舊式處理方法與新式處理方法間的差別。接下來讓我們看看二者的差異。





新方式

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

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





創(chuàng)建請求

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

            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:///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)建各個元素。在本例中,您將創(chuàng)建與前面示例完全相同的元素,因為將再次使用此客戶機(jī)訪問 echo 函數(shù)。(稍后將對其進(jìn)行更改,以訪問真正的服務(wù)。)

接下來,將創(chuàng)建請求。





創(chuàng)建請求

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

            ...
            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());
            }
            }
            }
            

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

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





發(fā)送請求

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

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





輸出結(jié)果

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

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

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

            <cms:echo xmlns:cms="http:///cms"><cms:catego
            ry>classifieds</cms:category></cms:echo>
            

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

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

如果您覺得構(gòu)建 Web 服務(wù)客戶機(jī)的過程相當(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 用于單向消息。操作的名稱與有效負(fù)載的根元素以及要執(zhí)行的方法對應(yīng)。

將此文件保存為 services.xml。

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





回頁首


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

讓我們首先創(chuàng)建模擬前面看到的 echo 函數(shù)的類(將直接返回原始有效負(fù)載的副本),如清單 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ù)(表示有效負(fù)載)。此處,您將首先使用 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ù)。





回頁首


提取有效負(fù)載

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


清單 25. 提取有效負(fù)載信息
            ...
            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;
            }
            }
            

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





回頁首


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

最后,將需要使用從請求的有效負(fù)載提取數(shù)據(jù)來創(chuàng)建響應(yīng)。在本例中,將從第二個函數(shù)(在實際應(yīng)用程序中,該函數(shù)將進(jìn)行一些其他的工作)提供響應(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:///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)的有效負(fù)載的命名空間。接下來,創(chuàng)建實際結(jié)果元素,在本例中為名為 numberOfArticles 的元素。

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

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





回頁首


部署服務(wù)

為了部署服務(wù),需要創(chuàng)建一個 Axis 存檔文件。此文件和 *.jar 或 *.war 文件類似,實際是使用特殊文件擴(kuò)展名(在本例中使用的是 .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ù)后進(jìn)行此操作,但在進(jìn)行更改后可能必須這樣做。)

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


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




回頁首


訪問服務(wù)

現(xiàn)在已經(jīng)完成了服務(wù)構(gòu)建,接下來要通過客戶機(jī)對其進(jìn)行訪問。對前面創(chuàng)建的 ClassifiedClient.java 文件進(jìn)行以下更改(請參見清單 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:///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 中所示。

...
            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ā)生一些事項,會在命令行輸出接收到的有效負(fù)載。您將在 Geronimo 窗口中看到此信息。

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





客戶機(jī)

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

            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://", "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();
            }
            }
            }
            

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

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

通過 GET 訪問服務(wù)

在 SOAP 1.2 推出之前,使用 HTTP 訪問基于 SOAP 的 Web 服務(wù)的唯一方法是使用 POST 請求。您將需要創(chuàng)建能創(chuàng)建 POST 請求并使用 SOAP 消息作為請求的內(nèi)容的客戶機(jī)。不過,SOAP 1.2 定義了使用 GET 請求訪問基于 SOA 的 Web 服務(wù)的方法。

GET 與 POST 對比

繼續(xù)我們的討論之前,務(wù)必了解通過 HTTP 的 GETPOST 請求的區(qū)別。盡管很多 Web 程序員所進(jìn)行的處理似乎表明二者之間是可以互換的,但實際上二者的用途并不相同。GET 中的所有關(guān)于所請求的資源的信息都包含在 URL(通常作為參數(shù)),僅用于等冪請求。這些請求是沒有“副作用”的請求。也就是說,應(yīng)該能夠數(shù)十次、數(shù)百次、數(shù)千次地調(diào)用這個請求,但這個請求不會更改任何東西。例如,請求 Albuquerque 的當(dāng)前氣溫的 Web 請求就是等冪請求。而將注釋傳入到博客數(shù)據(jù)庫的 Web 請求則不是。

這是因為 GET 請求可以添加到用戶的書簽,能在不會引發(fā)警告的情況下進(jìn)行訪問。還可以對其進(jìn)行引用,而不會引發(fā)警告。另一方面,POST 請求將其信息包含在請求的正文中,因此很難進(jìn)行隨機(jī)的重復(fù)。

就 SOAP 而言,這意味著應(yīng)該能夠?qū)H檢索信息而不進(jìn)行更改的 SOAP 請求使用 GET。對于進(jìn)行更改的任何操作,仍然都應(yīng)使用 POST





訪問服務(wù)

在 Axis2 中,可以生成 GET 請求,服務(wù)器會將其轉(zhuǎn)換為 SOAP 消息,然后將有效負(fù)載作為結(jié)果返回。例如,請將瀏覽器指向清單 31 中所示的位置。

            http://localhost:8080/axis2/services/CMSService/getNumberOfArticles?category=classifieds
            

如果使用 0.94 版,將看到清單 32 中所示的響應(yīng)。

            <resp:numberOfArcticles>42</resp:numberOfArcticles>
            

不過,這并不十分準(zhǔn)確。根據(jù) SOAP 1.2 建議規(guī)范,應(yīng)該能夠看到整個 SOAP 響應(yīng)。這在 Axis2 將來的版本中可能會發(fā)生更改。
 

處理附件

簡單 SOAP 消息的另一個變體是附件。對于附件,多年來人們早已耳熟能詳,但由于現(xiàn)在某些擴(kuò)展規(guī)范要求使用附件,因此您必須對其進(jìn)行處理。

二進(jìn)制數(shù)據(jù)和 XML

盡管 XML 是基于文本的格式,但卻不能忽略實際上是采用二進(jìn)制進(jìn)行表示的。因為這樣,將會有需要向 Web 服務(wù)傳遞或從其檢索二進(jìn)制信息的情況。

可以采用兩種方式中的一種來處理這種情況。第一種選擇是將二進(jìn)制數(shù)據(jù)實際包含在您的文檔中。這種情況的一個例子是將 Microsoft Word 文檔另存為 XML 文件時。如果在該文檔中嵌入了任何圖形,Word 會將其作為二進(jìn)制數(shù)據(jù)嵌入到 XML 文檔中(采用 Base64 編碼)。第二種選擇是直接引用該數(shù)據(jù),以便處理該文檔的應(yīng)用程序能夠找到此數(shù)據(jù)。一個極為常見的例子是 Web 瀏覽器以及其處理從 XHTML 文件引用的圖像的方式。XHTML 文本包含一個 img 元素(或者,采用了更為先進(jìn)的技術(shù),則為 object 元素),該元素包含一個 src 屬性,其中有指向?qū)嶋H數(shù)據(jù)的 URL。應(yīng)用程序可以隨后從該位置加載數(shù)據(jù)并相應(yīng)地進(jìn)行使用。

SOAP 文檔也是這樣。假如,如果向基于 SOAP 的服務(wù)提交了一個圖像,有兩個選擇??梢詫⒃摂?shù)據(jù)嵌入在有效負(fù)載中,或可以想辦法引用該數(shù)據(jù)。曾經(jīng)由于涉及到帶寬的一些問題對此進(jìn)行過討論。





XML 二進(jìn)制優(yōu)化打包

XML 已經(jīng)比二進(jìn)制對應(yīng)項冗長得多了。正因為如此,它將使用更多的帶寬。那么,當(dāng)考慮使用向 XML 文本文檔添加二進(jìn)制數(shù)據(jù)時的首選方法(將其編碼為 Base64)時,會由于兩個或更多的因素而導(dǎo)致其尺寸增大,這就帶來了一個非常實際的問題。

事實上,在過去的兩三年,曾經(jīng)有很多人強(qiáng)烈地批評缺乏對二進(jìn)制數(shù)據(jù)的實時支持,幾乎充斥著不滿的聲音,最終 W3C 開始著手處理這個問題。其工作的成果就是 XML 二進(jìn)制優(yōu)化打包(XML-binary Optimized Packages,XOP)。此協(xié)議提供了在 XML 文檔中可靠地引用外部數(shù)據(jù)的方法。例如,SOAP with Attachments 規(guī)范規(guī)定二進(jìn)制數(shù)據(jù)可以作為多部分 MIME 文檔的的一部分發(fā)送,由 XML 數(shù)據(jù)組成第一部分,而二進(jìn)制數(shù)據(jù)作為附加部分添加到其中。這樣做的問題在于,盡管您的程序可能知道數(shù)據(jù)存在,但文檔并不知道這一點。同時,還不允許對文檔進(jìn)行選擇性優(yōu)化或?qū)ΠM(jìn)制數(shù)據(jù)的現(xiàn)有文檔進(jìn)行回溯處理。

XOP 通過提供一個特殊的機(jī)制來改進(jìn)這種情況,利用這種機(jī)制可選擇性地提取要優(yōu)化的信息,將其添加到多部分 MIME 消息中(其中也包括您的 SOAP 消息)并顯式地對其進(jìn)行引用。讓我們看一個例子。

例如,假定員工不想將新文章作為文本元素添加,而希望將其作為二進(jìn)制文檔從字處理程序添加。如果將該內(nèi)容包含在消息體中,將十分混亂,如清單 33 中所示:_

            <?xml version=‘1.0‘ ?>
            <env:Envelope xmlns:env="http://www./2003/05/SOAP-envelope">
            <env:Header>
            </env:Header>
            <env:Body>
            <cms:addArticle xmlns:cms="http://www./cms">
            <cms:category>classifieds</category>
            <cms:subcategory>forsale
            </cms:subcategory>
            <cms:articleHeadline><cms:articleHeadline>
            <cms:articleText>wvetwenptiubnweoirntuwopeirt4m[456n09ew7nv
            sa0tv043u6y304o5mu60ew9rebtm45bm4-69nw-0er9utnv3094nb-26204
            95u6-49kv6-m34956h-wb09emjb-0n67u-340v,=qw-enr7w8b64b03278-
            ANDLOTSMOREBASE64ENCODEDDATAHERE</cms:articleText>
            </cms:addArticle>
            </env:Body>
            </env:Envelope>
            

相反,XOP 規(guī)定對數(shù)據(jù)進(jìn)行提取,然后使用一個引用其新位置的 Include 元素將其替換,如清單 34 中所示。

            MIME-Version: 1.0
            Content-Type: Multipart/Related;boundary=MIME_boundary;
            type="application/xop+xml";
            start="<soapmsg.xml@>";
            start-info="text/xml"
            Content-Description: An XML document with binary data in it
            --MIME_boundary
            Content-Type: application/xop+xml;
            charset=UTF-8;
            type="text/xml"
            Content-Transfer-Encoding: 8bit
            Content-ID: <soapmsg.xml@>
            <env:Envelope xmlns:env="http://www./2003/05/SOAP-envelope">
            <env:Header>
            </env:Header>
            <env:Body>
            <cms:addArticle xmlns:cms="http://www./cms">
            <cms:category>classifieds</category>
            <cms:subcategory>forsale
            </cms:subcategory>
            <cms:articleHeadline><cms:articleHeadline>
            <cms:articleText><xop:Include
            xmlns:xop=‘http://www./2004/08/xop/include‘
            href=‘cid:http:///tbird.doc‘
            /></cms:articleText>
            </cms:addArticle>
            </env:Body>
            </env:Envelope>
            --MIME_boundary
            Content-Type: application/vnd.oasis.openoffice
            Content-Transfer-Encoding: binary
            Content-ID: <http:///tbird.doc>
            // binary octets for the word processing file
            --MIME_boundary--
            

請注意,Include 元素中指定的位置與 Content-ID 減去協(xié)議 cid: 的值匹配?,F(xiàn)在要發(fā)送的是此消息,而不是純文本 SOAP 消息。





SOAP、二進(jìn)制數(shù)據(jù)和 Axis2

在 SOAP 文檔中使用 XOP 的過程稱為 MTOM(即 SOAP 消息傳輸優(yōu)化機(jī)制——Message Transmission Optimization Mechanism)。Axis2 提供了使用 SOA 數(shù)據(jù)的這個方法的支持,但必須確保對應(yīng)用程序進(jìn)行了恰當(dāng)配置。

具體來說,您必須在 axis2.war 文件內(nèi)的 axis2.xml 文件中啟用此支持(請參見清單 35)。

            <axisconfig name="AxisJava2.0">
            <!-- ================================================= -->
            <!-- Parameters -->
            <!-- ================================================= -->
            <parameter name="hotdeployment" locked="false">true</parameter>
            <parameter name="hotupdate" locked="false">true</parameter>
            <parameter name="enableMTOM" locked="false">true</parameter>
            <!-- Uncomment this to enable REST support -->
            <!--    <parameter name="enableREST" locked="false">true</parameter>-->
            <parameter name="userName" locked="false">admin</parameter>
            <parameter name="password" locked="false">axis2</parameter>
            ...
            

如果有必要,可以提取 axis2.war 文件,進(jìn)行此更改,然后將其重新壓縮成 .war 文件。

要替換 Axis2 應(yīng)用程序,請使用清單 36 中所示的 URL 訪問 Geronimo 控制臺。

            http://localhost:8080/console
            

作為 system/manager 登錄,并單擊 Application>Web App WARs,然后卸載并重新安裝 Axis2 應(yīng)用程序。(請記住,執(zhí)行此步驟后,必須重新加載 Web 服務(wù)。)

以編程方式使用 MTOM 不在本教程的討論范圍之內(nèi),但可以在參考資料部分獲取有關(guān)此主題的更多信息。只是要注意,在 Axis2 的 0.95 版之前的版本上可能不會按照預(yù)期工作,因為該版本中包含了 SOAP with Attachments API for Java (SAAJ) 實現(xiàn)。
 

結(jié)束語

在系統(tǒng)間的互操作性非常重要的當(dāng)今世界,可將 Web 服務(wù)視為面向服務(wù)的體系結(jié)構(gòu)的基礎(chǔ)。而 SOAP 則是企業(yè)級 Web 服務(wù)的基礎(chǔ)。本教程介紹了 Web 服務(wù)的基礎(chǔ)知識,并對了解和在自己的應(yīng)用程序中使用 SOAP 所必需的概念和編程知識進(jìn)行了說明。在本教程中,您了解了以下內(nèi)容:

  • 有關(guān) Web 服務(wù)的重要概念
  • 如何安裝和使用 Geronimo 應(yīng)用服務(wù)器
  • 如何安裝和使用 Axis2 Web 服務(wù)應(yīng)用程序
  • 如何創(chuàng)建客戶機(jī)來訪問 SOAP 服務(wù)
  • 如何創(chuàng)建 SOAP 服務(wù)
  • 有關(guān) SOAP 服務(wù)的其他問題,如 GET 請求和附件
在本系列的第 2 將討論 Web 服務(wù)描述語言,您將從中學(xué)習(xí)如何使用 WSDL 來實現(xiàn)在本文中執(zhí)行的很多步驟的自動化,并提供更便于其他人訪問您構(gòu)建的服務(wù)的方法。
 

下載

描述 名字 大小 下載方法
Source code ws-understand-web-services1.zip 12KB HTTP
 

參考資料

學(xué)習(xí)

獲得產(chǎn)品和技術(shù)
  • 此處下載 Apache Geronimo。

  • 此處下載 Apache Axis2。本教程使用的是 0.94 版,但應(yīng)該也能使用更高版本。

  • 此處下載 J2SE SDK。

關(guān)于作者

Nicholas Chase 曾參與多家公司的網(wǎng)站開發(fā)工作,如 Lucent Technologies、Sun Microsystems、Oracle 和 Tampa Bay Buccaneers。Nick 擔(dān)任過高中物理教師、低輻射廢料處理設(shè)施管理員、在線科幻小說雜志編輯、多媒體工程師、Oracle 講師以及一家交互通信公司的首席技術(shù)官。他已經(jīng)出版了多本圖書,其中包括 XML Primer Plus (Sams)。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多