Java RPC通信機制之SOAP:應用Apache Axis進行Web Service開發

Java RPC通信機制之SOAP:應用Apache Axis進行Web Service開發

一、概述

SOAP原意爲Simple Object Access Protocol(簡單對象訪問協議),是一個用於分佈式環境的、輕量級的、基於XML進行信息交換的通信協議(SOAP is an XML based protocol used to exchange information throughout a distributed environment)。

以下是w3c網站上的定義:

SOAP Version 1.2 (SOAP) is a lightweight protocol intended for exchanging structured information in a decentralized, distributed environment. It uses XML technologies to define an extensible messaging framework providing a message construct that can be exchanged over a variety of underlying protocols. The framework has been designed to be independent of any particular programming model and other implementation specific semantics.

可以認爲SOAPXML-RPC的高級版本,二者基於相同的原理:利用HTTP + XML封裝進行RPC調用。

SOAP最初由MS發起研究,用以解決MTS/COM資源消耗大,不夠輕巧等問題,後逐漸被IBM等巨頭接納並加入研究,現已提交W3C,成爲Web Service應用傳輸標準。對於輕量級、可擴展Web Service應用協議的需求促成了SOAP的廣泛應用,也間接促進了XML的流行。關於相關歷史的更多信息,見http://www.microsoft.com/china/MSDN/library/WebServices/WebServices/SOAPSpecificationIndexPage.mspxhttp://www-128.ibm.com/developerworks/cn/webservices/ws-ref1/index.html

二、SOAP數據包結構解析

SOAP的消息被稱爲一個SOAP Envelope,包括SOAP HeaderSOAP Body。其中,SOAP Header可以方便的插入各種其它消息來擴充Web Service的功能,比如Security(採用證書訪問Web Service),SOAP Body則是具體的消息正文,也就是Marshall後的信息。

SOAP調用的時候,也就是向一個URL(比如http://api.google.com/search/beta2)發送HTTP Post報文(根據SOAP規範,HTTP Get報文也可被支持),調用方法的名字在HTTP Request Header SOAP-Action中給出,接下來就是SOAP Envelope了。服務端接到請求,執行計算,將返回結果MarshallXML,用HTTP返回給客戶端。

以下是一個典型的SOAP數據包:

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">

      <s:Header>

            <m:transaction xmlns:m="soap-transaction" s:mustUnderstand="true">

                  <transactionID>1234</transactionID>

            </m:transaction>

      </s:Header>

      <s:Body>

            <n:purchaseOrder xmlns:n="urn:OrderService">

                  <from>

                        <person>Christopher Robin</person>

                        <dept>Accounting</dept>

                  </from>

                  <to>

                        <person>Pooh Bear</person>

                        <dept>Honey</dept>

                  </to>

                  <order>

                        <quantity>1</quantity>

                        <item>Pooh Stick</item>

                  </order>

            </n:purchaseOrder>

      </s:Body>

</s:Envelope>

其中包含了一些SOAP規範定義的標籤,同時也可以包含一些具體應用相關的標籤。

Note:

如果你是一個普通的應用開發者,以上介紹已經足夠了,因爲相應的SOAP應用平臺會負責完成相應SOAP數據包的打包和解析;如果你是一個SOAP應用平臺的實現者,關於SOAP基礎理論的更多介紹可參考《Programming Web Services with SOAP》一書或SOAP Specificationhttp://www.w3.org/TR/soap12-part0/)。

三、安裝Apache Axis

Apache Axis本身也是一個Web Project,它內建了對SOAP的編碼、解析,併爲Client提供了一些使用SOAP ServiceAPI,同時,爲Web Service的發佈提供管理,並對Client提交的處理請求作出響應。對於基於Axis的應用而言,我們可以將注意力完全放在具體ServiceClient的設計上,而無需考慮中間的傳輸過程(對於Client而言,還需要使用一些Axis提供的訪問SOAP服務的特定API),這一點是與XML RPC不同的地方。

Apache Axis可以從http://ws.apache.org/axis/下載,當前的最新版本是1.4

安裝Axis的過程很簡單:

1、解壓Axis到任意目錄下;

2、拷貝Axis目錄下的webapps/axis目錄到%TOMCAT_HOME%/webapps下;

3、爲了便於編譯和測試程序,添加環境變量:

AXIS_HOME      Axis的解壓目錄

AXIS_LIB      %AXIS_HOME%/lib

AXISCLASSPATH      %AXIS_LIB%/axis.jar;%AXIS_LIB%/commons-discovery-0.2.jar;%AXIS_LIB%/commons-logging-1.0.4.jar;%AXIS_LIB%/jaxrpc.jar;%AXIS_LIB%/saaj.jar;%AXIS_LIB%/log4j-1.2.8.jar

完成上述工作後,啓動Tomcat,並用IE打開:http://localhost:8080/axis/,點擊其中的ValidationList兩個鏈接,如果沒有報告任何錯誤,則說明Axis安裝成功。

關於Apache Axis安裝的更多信息可以參考官方文檔:http://ws.apache.org/axis/java/install.pdf

四、舉例

有了上面對SOAP的基本理解,下面我們體驗一下Apache Axis 1.4提供的SOAP服務。

以下面EchoService爲例:

public class EchoService {

      public String echoString(String name) {

            return name;

      }

}

其對應的Client程序如下所示:

package demo.soap;

 

import org.apache.axis.client.Call;

import org.apache.axis.client.Service;

 

import javax.xml.namespace.QName;

 

public class EchoClient {

      public static void main(String [] args) {

            try {

                  String endpoint = "http://localhost:8080/axis/EchoService.jws";

                  // Create Service and Call object to set up a SOAP RPC

                  Service service = new Service();

                  Call call = (Call)service.createCall();

                  // Tells which service and method will be invoked

                  call.setTargetEndpointAddress(new java.net.URL(endpoint));

                  call.setOperationName(new QName("echoString"));

                  // Invoke method with required parameters

                  String ret = (String)call.invoke(new Object[] { "Hello!" });

 

                  System.out.println("Sent 'Hello!', got '" + ret + "'");

            } catch (Exception e) {

                  System.err.println(e.toString());

            }

      }

}

對於Client程序而言,對Axis Service進行訪問的基本方法是:

1、創建ServiceCall對象;

2、設置Call對象屬性,如訪問點(標明將訪問哪個Axis Service)及方法名等;

3、傳入參數數組,調用Call對象的invoke方法。

可使用如下命令編譯EchoClient.java

javac -cp %AXISCLASSPATH% EchoClient.java

Axis中,存在兩種發佈SOAP Service的方法。

方法一:

將源程序EchoService.java拷貝到%TOMCAT_HOME%/webapps/axis下,並將其後綴改爲.jws即可。

第一種方法非常的簡單,但是第一種發佈方法存在幾個重要的限制:

1、不能指定package

2、需要有Service的源碼;

因此常常不能滿足我們的需要。

方法二:

第二種發佈Axis Service的方法需通過配置來完成。

以下面的HelloService爲例(與前面的EchoService基本沒有什麼區別,但其中使用了package):

package demo.soap;

 

public class HelloService {

      public String sayHello() {

            return "Hello World!";

      }

}

要發佈上面的Service,需編寫如下的配置文件:

<deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">

      <service name="HelloService" provider="java:RPC">

            <parameter name="className" value="demo.soap.HelloService"/>

            <parameter name="allowedMethods" value="*"/>

      </service>

</deployment>

將上述內容保存爲%TOMCAT_HOME%/webapps/axis/WEB-INF/deploy.txt,並在其所在目錄下執行:

java -cp %AXISCLASSPATH% org.apache.axis.client.AdminClient deploy.txt

生成server-config.wsdd文件,打開該文件看一下,可以看到HelloService的相關信息已被添加到該文件,此外,還包括一些默認的配置信息以及AdminServiceVersion兩個基礎服務。

以下是HelloServiceClient程序的相關代碼:

package demo.soap;

 

import org.apache.axis.client.Call;

import org.apache.axis.client.Service;

 

public class HelloClient {

      public static void main(String [] args) throws Exception {

            String endpoint = "http://localhost:" + "8080" + "/axis/services/HelloService"; // Attention: A little difference

 

            Service service = new Service();

            Call call = (Call)service.createCall();

            call.setTargetEndpointAddress(new java.net.URL(endpoint));

            call.setOperationName("sayHello");

 

            String res = (String)call.invoke(new Object[] {});

 

            System.out.println(res);

      }

}

與前面的EchoClient的區別僅在於訪問點稍有不同。

發佈後如何刪除對應的Service呢?要刪除上面發佈的HelloService服務,只需在%TOMCAT_HOME%/webapps/axis/WEB-INF目錄下添加如下的undeploy.txt描述文件,其內容如下:

<undeployment xmlns="http://xml.apache.org/axis/wsdd/">

      <service name="HelloService"/>

</undeployment>

然後執行:

java -cp %AXISCLASSPATH% org.apache.axis.client.AdminClient deploy.txt

以更新server-config.wsdd文件。

刷新一下頁面:

http://localhost:8080/axis/servlet/AxisServlet

將看到前面已發佈的對應的Service已被刪除。

如果以後還要發佈新的Service,你可以選擇直接更新上面產生的server-config.wsdd文件,或者重複上面的步驟。

Note:除了發佈自己的Web ServiceAxis,你也可以將Axis集成到自己的Web Application,具體方法見http://ws.apache.org/axis/java/install.pdf

五、Google Web API

在繼續下面的討論之前,先娛樂一下,談談Google Web API

爲了便於程序員體驗Google的搜索服務,或者將Google的搜索服務集成到自己的應用中,Google2002發佈了Google Web API,可以讓世界各地的Java.NETPerlPython等程序員,免費地通過Google提供的SOAP開發接口以Web Services的方式,對Google下達查找指令,並且可以將結果使用於自己的程序或網頁中。(不過使用上也有限制,它一天只允許未付費的程序員查找1000次。要使用前,必須先向Google註冊帳號,取得一個32位長度的license key,每次呼叫查詢時,必須帶入這個license key。)

通過使用Google Web API,能夠從Google那兒以結構化數據的形式(xml格式)取得檢索結果,所帶來的最大好處就是你可以根據你自己的意願和設計,把這些檢索結果顯示你自己的頁面上。這個頁面上可顯示自己的logo或一些其它的內容,就象自己編寫的頁面一樣,而不必非要把Googlelogo顯示在頁面的頂部和底部。一句話,你可以控制Google的檢索了,讓Google爲你的網站服務。(參考5

以下是使用Proxy連接Google SOAP服務的例子:

java -cp googleapi.jar -Dhttp.proxyHost=xxx(proxy_host_ip/name) -Dhttp.proxyPort=xxx(proxy_port) com.google.soap.search.GoogleAPIDemo xxx(license_key) search billdavid

其輸出大致如下:

Parameters:

Client key = o917zHlQFHIr2+qMGPUYflB+j89LLbcX

Directive  = search

Args       = billdavid

Google Search Results:

======================

{

TM = 0.694308

Q  = "billdavid"

CT = ""

TT = ""

CATs =

  {

  <EMPTY>

  }

Start Index = 1

End   Index = 10

Estimated Total Results Number = 1280

Document Filtering = true

Estimate Correct = false

Rs =

  {

 

  [

  URL  = "http://forums.vandyke.com/member.php?u=2050"

  Title = "VanDyke Software Forums - View Profile: <b>billdavid</b>"

  Snippet = "This is a discussion forum for users and evaluators of VanDyke Soft

ware products."

  Directory Category = {SE="", FVN=""}

  Directory Title = ""

  Summary = ""

  Cached Size = "16k"

  Related information present = true

  Host Name = ""

  ],

 

  [

  URL  = "http://forums.vandyke.com/showthread.php?t=1393"

  Title = "Will you add two new features to SecureCRT? - VanDyke Software Forums

"

  Snippet = "<b>billdavid billdavid</b> is offline. Registered User. Join Date:

Apr 2006 <b>...</b><br>  Originally Posted by <b>billdavid</b>. I think the foll

owing features are very useful: <b>...</b>"

  Directory Category = {SE="", FVN=""}

  Directory Title = ""

  Summary = ""

  Cached Size = "30k"

  Related information present = true

  Host Name = "forums.vandyke.com"

  ],

 

  [

  URL  = "http://www.beliefnet.com/user/profile_view.asp?userID=424089&popUp=1"

  Title = "Beliefnet Member Profile"

  Snippet = "Member Name: <b>billdavid</b>. Member since: 2/24/2003. Location: s

ebring, florida , us.<br>  Sex: Male. Age: 53. Occupation: Other. Organizations

and Affiliations: <b>...</b>"

  Directory Category = {SE="", FVN=""}

  Directory Title = ""

  Summary = ""

  Cached Size = "8k"

  Related information present = true

  Host Name = ""

  ],

(下略...

以下是通過ethereal抓到的本機發出的Google Search數據包:

POST http://api.google.com/search/beta2 HTTP/1.0

Host: api.google.com

Content-Type: text/xml; charset=utf-8

Content-Length: 864

SOAPAction: "urn:GoogleSearchAction"

<?xml version='1.0' encoding='UTF-8'?>

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" xmlns:xsd="http://www.w3.org/1999/XMLSchema">

      <SOAP-ENV:Body>

            <ns1:doGoogleSearch xmlns:ns1="urn:GoogleSearch" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">

                  <key xsi:type="xsd:string">xxx…xxx</key>

                  <q xsi:type="xsd:string">billdavid</q>

                  <start xsi:type="xsd:int">0</start>

                  <maxResults xsi:type="xsd:int">10</maxResults>

                  <filter xsi:type="xsd:boolean">true</filter>

                  <restrict xsi:type="xsd:string"></restrict>

                  <safeSearch xsi:type="xsd:boolean">false</safeSearch>

                  <lr xsi:type="xsd:string"></lr>

                  <ie xsi:type="xsd:string">UTF-8</ie>

                  <oe xsi:type="xsd:string">UTF-8</oe>

            </ns1:doGoogleSearch>

      </SOAP-ENV:Body>

</SOAP-ENV:Envelope>

com.google.soap.search.GoogleAPIDemo.java的源代碼可以在googleapi的壓縮包中找到,其中演示了大部分基本Google Web API的用法,關於Google Web API的更多信息見參考4

六、Axis2

隨着Web Services技術的演進,Apache Web Services中間件也在不斷髮展,從第一代的Apache SOAP,第二代的Axis,逐漸發展成爲第三代Web Service中間件Axis2。與Axis相比,Axis2採用了性能更爲優越的XML解析技術,採用面向組件的架構設計,從而具有更好的靈活性和可擴展性,並可支持異步通信需求等。參考67給出了利用Axis2進行Web Service開發的詳細步驟。

參考:

1.   勞虎,SOAPWeb serviceshttp://2tigers.net/html/tiger_column/article3.html

2.   孟巖,Web Service : WebOS中的Function Callhttp://www.mengyan.org/blog/archives/2006/06/09/125.html

3.   Axis學習筆記,http://www.javaresearch.org/article/showarticle.jsp?column=5&thread=29576

4.   Google, Google SOAP Search API, http://www.google.com/apis/

5.   Patrick Chanezon, Patch For Google APIs to handle proxy settings, http://www.chanezon.com/pat/google_proxy_patch.html

6.   Hilton,關於Google API的學習,http://hedong.3322.org/archives/000274.html

7.   Gopalakrishnan UShreevidya Rao,通過Axis2開發Web服務,http://www-128.ibm.com/developerworks/cn/webservices/ws-webaxis1/index.html

8.   joyetaApache Axis2(java web service)備忘記,http://blog.matrix.org.cn/page/joeyta?entry=apache_axis2_java_web_service

發佈了56 篇原創文章 · 獲贊 10 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章