AXIS(Java WebSerivce)全攻略

一、Axis簡介


1. 什麼是SOAP

SOAP是一個基於XML的用於應用程序之間通信數據編碼的傳輸協議。最初由微軟和Userland Software提出,隨着不斷地完善和改進,SOAP很快被業界廣泛應用,目前完全發佈版本是1.1。在其發展過程中,W3C XML標準工作小組積極促成SOAP成爲一個真正的開放標準。在寫作此文檔之時,SOAP1.2草案已經發布,1.2對1.1中相對混亂的部分做了改進。
SOAP被廣泛作爲新一代跨平臺、跨語言分佈計算Web Services的重要部分。


2. 什麼是Axis

Axis是Apache組織推出的SOAP引擎,Axis項目是Apache組織著名的SOAP項目的後繼項目,目前最新版本是採用Java開發的1.1版本,C++的版本正在開發之中。Axis v1.1軟件包可以從http://ws.apache.org/axis/dist/1_1/下載得到。
但是Axis不僅僅是一個SOAP引擎,它還包括:
    一個獨立運行的SOAP服務器
    一個servlet引擎的插件,這個servlet引擎可以是Tomcat
    對WSDL的擴展支持
    一個將WSDL的描述生成JAVA類的工具
    一些示例代碼
    還有一個監控TCP/IP包的工具
 
二、Axis的安裝

應用Axis開發Web Services,你需要安裝如下軟件:
1.JDK1.4.2
2.一個支持Servlet的服務器引擎,比如廣爲人知的Tomcat。

當安裝好Tomcat之後,只需將下載的Axis軟件包解壓縮,將其中的“webapps”目錄下的“axis”目錄整個拷貝到Tomcat安裝目錄下的“webapps”目錄下即可。

三、Axis的配置

Axis基於Java開發,可以部署於多種操作系統,使用前需要配置一系列的系統變量,在此假定你已經在本機上裝好了Tomcat 4.0以上的版本,需要配置的系統變量如下表所示:

CATALINA_HOME
C:/Tomcat_4_1

(此處應爲Tomcat的安裝位置,注意路徑名中不要有空格)

AXIS_HOME
%CATALINA_HOME%/webapps/axis

AXIS_LIB
%AXIS_HOME%/lib

AXISCLASSPATH
%AXIS_LIB%/axis.jar;%AXIS_LIB%/commons-discovery.jar; %AXIS_LIB%/commons-logging.jar;%AXIS_LIB%/jaxrpc.jar; %AXIS_LIB%/saaj.jar;%AXIS_LIB%/log4j-1.2.8.jar; %AXIS_LIB%/xml-apis.jar;%AXIS_LIB%/xercesImpl.jar

CLASSPATH 中加入:
%AXIS_LIB%/axis.jar;%AXIS_LIB%/commons-discovery.jar; %AXIS_LIB%/commons-logging.jar;%AXIS_LIB%/jaxrpc.jar; %AXIS_LIB%/saaj.jar;%AXIS_LIB%/log4j-1.2.8.jar; %AXIS_LIB%/xml-apis.jar;%AXIS_LIB%/xercesImpl.jar

四、Axis的測試

安裝配置完畢後,應測試一下是否Axis可以正確運行了。

  啓動Tomcat服務器,在瀏覽器中訪問http://localhost:8080/axis/happyaxis.jsp,如果頁面顯示有錯誤,則需要回頭檢查一下相關配置是否正確,如果瀏覽頁面能正確顯示出系統組件、屬性等參數配置信息,則表示安裝成功。現在可以開始開發你的Web Services應用了。

五、服務的發佈
Axis提供了兩種服務發佈方式,一種是即時發佈(Instant Deployment),一種是定製發佈(Custom Deployment)。

1. 使用即時發佈 Java Web Service(JWS)

  對即時發佈的支持是Axis的特色之一,使用即時發佈使用戶只需有提供服務的Java類的源代碼,即可將其迅速發佈成Web服務。每當用戶調用這類服務的時候,Axis會自動進行編譯,即使服務器重啓了也不必對其做任何處理,使用非常簡單快捷。

  使用即時發佈首先需要一個實現服務功能的Java源文件,將其擴展名改爲.jws(Java Web Service的縮寫),然後將該文件放到“……/webapps/axis”目錄下即可。
    在此給出一個從英里到公里的長度單位轉換的服務,其源碼如下:

文件Distance.jws

public class Distance
{
    public double convertMile2Kilometre( double mile )
    { 
 return mile * 1.609;  //實現英里到公里的距離轉換
    }
}

將其放到“……/webapps/axis”目錄,通過訪問http://localhost:8080/axis/Distance.jws?wsdl可以看到這個服務的WSDL描述文件,這說明Distance服務被成功發佈了。描述的WDSL代碼如下:
<?xml version="1.0" encoding="UTF-8" ?>
- <wsdl:definitions targetNamespace="http://192.168.0.26:8080/axis/Distance.jws" xmlns="http://schemas.xmlsoap.org/wsdl/
   xmlns:apachesoap="http://xml.apache.org/xml-soap" xmlns:impl="http://192.168.0.26:8080/axis/Distance.jws" xmlns:intf="http://192.168.0.26:8080/axis/Distance.jws" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
- <wsdl:message name="convertMile2KilometreRequest">
  <wsdl:part name="mile" type="xsd:double" />
  </wsdl:message>
- <wsdl:message name="convertMile2KilometreResponse">
  <wsdl:part name="convertMile2KilometreReturn" type="xsd:double" />
  </wsdl:message>
- <wsdl:portType name="Distance">
- <wsdl:operation name="convertMile2Kilometre" parameterOrder="mile">
  <wsdl:input message="impl:convertMile2KilometreRequest" name="convertMile2KilometreRequest" />
  <wsdl:output message="impl:convertMile2KilometreResponse" name="convertMile2KilometreResponse" />
  </wsdl:operation>
  </wsdl:portType>
- <wsdl:binding name="DistanceSoapBinding" type="impl:Distance">
  <wsdlsoap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
- <wsdl:operation name="convertMile2Kilometre">
  <wsdlsoap:operation soapAction="" />
- <wsdl:input name="convertMile2KilometreRequest">
  <wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://DefaultNamespace" use="encoded" />
  </wsdl:input>
- <wsdl:output name="convertMile2KilometreResponse">
  <wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://192.168.0.26:8080/axis/Distance.jws" use="encoded" />
  </wsdl:output>
  </wsdl:operation>
  </wsdl:binding>
- <wsdl:service name="DistanceService">
- <wsdl:port binding="impl:DistanceSoapBinding" name="Distance">
  <wsdlsoap:address location="http://192.168.0.26:8080/axis/Distance.jws" />
  </wsdl:port>
  </wsdl:service>
  </wsdl:definitions>

需要注意的是:JWS的web服務發佈是一個很簡單的Web服務發佈方式,在頁面中你不能使用包,而且由於代碼是在運行期被編譯的,所以在部署之後,你也很難找到錯誤所在。

2. 使用定製發佈 Web Service Deployment Descriptor(WSDD)

  即時發佈是一項令人激動的技術,它使Web服務的開發變得如此簡單;然而即時發佈並不總是最好的選擇,比如有些應用系統是第三方提供的,我們沒有購買源代碼,只有.class文件,但我們又希望將這個應用系統的一些功能對外發布成Web服務,使其能夠在更大範圍內產生作用,這個時候即時發佈技術就無能爲力了。此外,即時發佈技術並不靈活,無法進行更多的服務配置,這使得它並不能滿足一些特定系統的需求。

  因此,Axis提供了另一種服務發佈方式,這就是定製發佈。

  在此給出一個從加侖到升的容積單位轉換的服務,其源碼如下:

  文件Capacity.java
    package samples.capacity;
    public class Capacity
    {
        public double convertGallon2Litre( double gallon )
 {
     return gallon * 4.546;//實現加侖到升的容積轉換
 }//convertGallon2Litre()

    }/* Capacity */
 
    將其編譯成.class文件,放置到“……/webapps/axis/samples/capacity”目錄下,即可着手進行發佈。
    定製發佈不需要構建.jws文件,但必須創建服務發佈描述文件deploy.wsdd(Web Service Deployment Descriptor的縮寫),這個文件負責描述服務的名稱、入口等信息,其內容如下:
    文件deploy.wsdd

    <deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
 <service name="Capacity" provider="java:RPC">
 <parameter name="className" value="samples.capacity.Capacity"/>
 <parameter name="allowedMethods" value="*"/>
 </service>
    </deployment>

    在這裏服務的提供者是“java:RPC”,它被內建在Axis中,而且指明瞭一個JAVA RPC服務,做這個處理的類是org.apache.axis.providers.java.RPCProvider。
    我們是通過一個<parameter>標籤告訴RPC服務應該調用的類,而另外一個<parameter>標籤則告訴引擎,它可以調用這個類中的任何的Public方法。你也可以指定通過使用名字空間或者一些可以調用的方法列表,來指明那些方法可以被調用。

  將該文件也放到“……/webapps/axis/samples/capacity”目錄下,然後可以採用Axis提供的一個客戶端管理工具——AdminClient來完成服務的定製發佈。
   在“……/webapps/axis/samples/capacity”目錄下,運行:

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

   如果運行時說沒有找到類,那麼可能是類路徑沒有配置好,建議將所有的與axis相關的jar都寫到classpath中去。這樣只要運行:

   java org.apache.axis.client.AdminClient deploy.wsdd
   可以看到以下運行結果:

 Processing file deploy.wsdd
 <Admin>Doneprocessing</Admin>

  這表明Capacity服務定製發佈完成。
 
   你也可以調用:
 java org.apache.axis.client.AdminClient undeploy.wsdd  來取消部署。

   你也可以調用:
 java org.apache.axis.client.AdminClient list 來獲得所有的已經部署的服務的列表。在這裏你會看到services, handlers, transports等等,注意這個調用只是列出了WEB-INF/server-config.wsdd的文件內容。

   一定要注意:編譯後的class文件要拷貝到web-inf/classes的目錄中,如果該文件中有包存在的話,別忘了還要在classes目錄下創建包的目錄
   通過訪問http://localhost:8080/axis/services/Capacity?wsdl可以看到這個服務的WSDL描述文件,這說明Capacity服務被成功發佈了。
   你也可以通過訪問http://localhost:8080/axis/servlet/AxisServlet查看所有定製發佈的服務。
   WDSL如下:
  <?xml version="1.0" encoding="UTF-8" ?>
- <wsdl:definitions targetNamespace="http://localhost:8080/axis/services/Capacity" xmlns="http://schemas.xmlsoap.org/wsdl/"
    xmlns:apachesoap="http://xml.apache.org/xml-soap" xmlns:impl="http://localhost:8080/axis/services/Capacity" xmlns:intf="http://localhost:8080/axis/services/Capacity" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
- <wsdl:message name="convertGallon2LitreResponse">
  <wsdl:part name="convertGallon2LitreReturn" type="xsd:double" />
  </wsdl:message>
- <wsdl:message name="convertGallon2LitreRequest">
  <wsdl:part name="in0" type="xsd:double" />
  </wsdl:message>
- <wsdl:portType name="Capacity">
- <wsdl:operation name="convertGallon2Litre" parameterOrder="in0">
  <wsdl:input message="impl:convertGallon2LitreRequest" name="convertGallon2LitreRequest" />
  <wsdl:output message="impl:convertGallon2LitreResponse" name="convertGallon2LitreResponse" />
  </wsdl:operation>
  </wsdl:portType>
- <wsdl:binding name="CapacitySoapBinding" type="impl:Capacity">
  <wsdlsoap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
- <wsdl:operation name="convertGallon2Litre">
  <wsdlsoap:operation soapAction="" />
- <wsdl:input name="convertGallon2LitreRequest">
  <wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://capacity.samples" use="encoded" />
  </wsdl:input>
- <wsdl:output name="convertGallon2LitreResponse">
  <wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://localhost:8080/axis/services/Capacity" use="encoded" />
  </wsdl:output>
  </wsdl:operation>
  </wsdl:binding>
- <wsdl:service name="CapacityService">
- <wsdl:port binding="impl:CapacitySoapBinding" name="Capacity">
  <wsdlsoap:address location="http://localhost:8080/axis/services/Capacity" />
  </wsdl:port>
  </wsdl:service>
  </wsdl:definitions>

  WSDD 的高級功能:
  (1) AXIS支持三種對象範圍:
     "request"範圍:這是默認的情況,每一次Soap請求的時候都將創建新的對象。
     "application"範圍:將會爲所有的請求生成一個單獨的共享的對象。
     "session"範圍:爲每一個session期的客戶端請求創建一個對象。
  指定方法如下:
  <service name="MyService"...>
  <parameter name="scope" value="value"/>
  ...
  </service>
  (2) 更多部署內容:Handlers and Chains
  讓我們來深入挖掘一下Axis引擎的更強大的特性。如果我們想跟蹤我們的服務被調用了多少次,那麼我們只需要包含一個簡單的handler,它存放在samples/log目錄下。要使用這個handler,你就首先應該部署這個handler,然後使用在部署服務時給它指定的名字。下面是一個wsdd文件的例子:
  <deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
   <!-- define the logging handler configuration -->
    <handler name="track" type="java:samples.userguide.example4.LogHandler">
      <parameter name="filename" value="MyService.log"/>
    </handler>
 
   <!-- define the service, using the log handler we just defined -->
    <service name="LogTestService" provider="java:RPC">
     <requestFlow>
       <handler type="track"/>
     </requestFlow>
 
     <parameter name="className" value="samples.userguide.example4.Service"/>
     <parameter name="allowedMethods" value="*"/>
    </service>
  </deployment>

  第一段指明瞭一個名爲track的handler,它是samples.userguide.example4.LogHandler類的實例。另外還指定了一個參數filename,用於指定日誌文件名稱。
  下面的那段指明瞭一個RPC服務,和我們在上面的例子中看到的一樣,所不同的是在service標籤中的<requestFlow>標籤,它指定了一些在調用服務前應該被調用的handler集。也就是由於我們在部署中插入了這個"track"的引用,所以我們確定每次調用服務的時候都將被記錄到日誌文件中去。
 
  (3)遠程管理:
  <service name="AdminService" provider="java:MSG">
 <parameter name="className" value="org.apache.axis.util.Admin"/>
 <parameter name="allowedMethods" value="*"/>
 <parameter name="enableRemoteAdmin" value="true"/>
  </service>
  WARNING: enabling remote administration may give unauthorized parties access to your machine. If you do this, please make sure to add security to your configuration!
  所以遠程管理涉及到安全問題,不建議採用。

六、服務的訪問

  GET方式的服務訪問

  一般的SOAP消息都是採用POST方式實現傳遞,但也可以通過GET方式來訪問。比如以下給出的一個服務——“HelloWorld”,其源碼如下:

文件HelloWorld.jws
public class HelloWorld
{
    public String helloWorld()
    {
          System.out.println( "Hello World!" );//在服務器端打印輸出 
          return "Hello World!";//返回相應字符串
    }
}

  這個服務給出一個名爲“helloWorld”的無入口參數的操作,返回一個內容爲“Hello World!的字符串”,同時在服務器端打印“Hello World!”,將該文件放到“……/webapps/axis”目錄下,即可通過GET方法直接訪問該服務,訪問的地址爲http://localhost:8080/axis/HelloWorld.jws?method=helloWorld,可以看到返回的SOAP信封消息,同時服務器端給出了相應的顯示信息“Hello World!”這表明HelloWorld服務被成功訪問了,生成的SOAP信封消息爲:
 <?xml version="1.0" encoding="UTF-8" ?>
- <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>
- <helloWorldResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
  <helloWorldReturn xsi:type="xsd:string">Hello World!</helloWorldReturn>
  </helloWorldResponse>
  </soapenv:Body>
  </soapenv:Envelope>


七、客戶端服務訪問編程

  Axis提供了一套API來實現SOAP,從http://localhost:8080/axis/docs/apiDocs/index.html可以看到Axis的API文檔。

  其中,org.apache.axis.client.Call和org.apache.axis.client.Service是兩個比較常用的類,一般的客戶端程序欲訪問一個Web Service時,都要生成一個客戶端的Service對象和Call對象,在訪問服務之前,首先要對Call對象設置相應的參數,包括服務的位置、操作名、入口參數、返回值類型等,最後調用Call對象的invoke方法訪問服務。

  以下給出了一個客戶端訪問Web服務的例程——AXISTest.java:

  文件AXISTest.java

package axisexercise;

import org.apache.axis.client.Call;

import org.apache.axis.client.Service;

import org.apache.axis.encoding.XMLType;

import javax.xml.rpc.ParameterMode;

public class AXISTest
{
    public static void main( String[] args ) throws Exception
    {
         創建service和call對象,這些對象是標準的JAX-RPC對象,這些對象用於存儲服務調用的數據(metadata)。

 Service service = new Service();
 Call call = ( Call ) service.createCall();
 //////////訪問即時發佈的Distance服務

 //設置訪問點
 call.setTargetEndpointAddress( "http://localhost:8080/axis/Distance.jws" );

 //設置操作名
 call.setOperationName( "convertMile2Kilometre" );

 //設置入口參數
 call.addParameter( "op1", XMLType.XSD_DOUBLE, ParameterMode.IN );

 //設置返回參數類型
 call.setReturnType( XMLType.XSD_DOUBLE );
 Double d1 = new Double( 190 );

 //調用服務,在invoke方法中傳入的是包含調用參數的數組
 System.out.println( d1 + " 英里相當於 " +
 call.invoke( new Object[] {d1} ) + " 公里!" );

 //////////訪問定製發佈的Capacity服務
 call = ( Call ) service.createCall();

 //設置訪問點
 call.setTargetEndpointAddress( "http://localhost:8080/axis/services/Capacity" );

 //設置操作名
 call.setOperationName( "convertGallon2Litre" );

 //設置入口參數
 call.addParameter( "op1", XMLType.XSD_DOUBLE, ParameterMode.IN );
 call.setReturnType( XMLType.XSD_DOUBLE );
 d1 = new Double( 10.00 );

 //調用服務
 System.out.println( d1 + " 加侖相當於 " +
 call.invoke( new Object[] {d1} ) + " 升!" );

    } //main()

}/* AXISTest */

編譯運行後運行可以看到以下的結果:

190.0英里相當於305.71公里!

10.0加侖相當於45.46升!
 
  注意程序在訪問即時發佈的Distance服務和定製發佈的Capacity服務時的不同,前者的服務訪問點地址爲http://localhost:8080/axis/HelloWorld.jws,而後者的則爲http://localhost:8080/axis/services/Capacity


八、服務類型:RPC, Document, Wrapped, and Message
在Axis中,有四種服務類型:

1. RPC服務:
PRC服務是AXIS中的默認服務,當你通過<service ... provider="java:RPC"> or <service ... style="RPC">標籤進行部署的時候,使用的就是RPC服務。RPC服務遵循SOAP RPC和其編碼規範。AXIS可以將XML反序列化成java對象,並將其傳給服務的方法。並且可以將服務的方法返回的JAVA對象序列化成XML。

2.Document / Wrapped services
Document services and wrapped services are similar in that neither uses the SOAP encoding for data; it's just plain old XML schema. In both cases, however, Axis still "binds" Java representations to the XML (see the databinding section for more), so you end up dealing with Java objects, not directly with XML constructs.

Document和Wrapped服務都不使用SOAP編碼數據,這一點是他們相似的地方。他們僅僅使用舊的XML模式。然而,在這兩種服務中,AXIS將捆綁Java的表示到XML文檔中,所以你最終處理的是java對象而不直接處理XML。

下面是包含定單的一個簡單的SOAP消息,你可以看到Document 和 Wrapped 服務的區別所在:
<soap:Envelope xmlns="http://xml.apache.org/axis/wsdd/"
   xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
  <soap:Body>
 <myNS:PurchaseOrder xmlns:myNS="http://commerce.com/PO">
   <item>SK001</item>
   <quantity>1</quantity>
   <description>Sushi Knife</description>
 </myNS:PurchaseOrder>
  </soap:Body>
</soap:Envelope>

相應的XML模式如下:

<schema targetNamespace="http://commerce.com/PO">
  <complexType name="POType">
 <sequence>
   <element name="item" type="xsd:string"/>
   <element name="quantity" type="xsd:int"/>
   <element name="description" type="xsd:string"/>
 </sequence>
  </complexType>
  <element name="PurchaseOrder" type="POType"/>
</deployment>

對於Document類型服務,他將映射成下面的方法:
public void method(PurchaseOrder po)


八、soap envolop(soap信封)
1. soap信封
在客戶端發出服務請求以及服務端返回請求結果的時候,在網絡中傳輸的是SOAP信封。首先客戶端程序將請求參數及請求的方法序列到XML的文件中(SOAP信封),並將SOAP信封傳送到服務器端。服務器端接受到SOAP信封后,將解析這個SOAP信封並反序列化調用參數及方法並將該方法的調用結果封裝成SOAP信封(序列到XML的文件中)返回給客戶端,客戶端同樣將SOAP信封中封裝的返回結果反序列化爲想要得到的結果。

我們來看下面這段客戶端程序的SOAP信封:
(1) 客戶端程序:
  import org.apache.axis.client.Call;
  import org.apache.axis.client.Service;
  import javax.xml.namespace.QName;
 
  public class TestClient
  {
     public static void main(String [] args)
     {
        try
        {
             String endpoint = "http://nagoya.apache.org:5049/axis/services/echo";
             Service  service = new Service();
             Call  call = (Call) service.createCall();
 
             call.setTargetEndpointAddress( new java.net.URL(endpoint) );
             call.setOperationName(new QName("http://soapinterop.org/", "echoString"));
 
             String ret = (String) call.invoke( new Object[] { "Hello!" } );
 
             System.out.println("Sent 'Hello!', got '" + ret + "'");
         }
  catch (Exception e)
  {
             System.err.println(e.toString());
         }
     }
  }

(2) SOAP信封:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"
       xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <SOAP-ENV:Body>
 <ns1:echoString xmlns:ns1="http://soapinterop.org/">
   <arg0 xsi:type="xsd:string">Hello!</arg0>
 </ns1:echoString>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

2. 參數命名:
在上面的代碼中,AXIS自動將在Soap消息中的函數調用參數命名爲arg0,arg1等等,如果你想按照自己定義的參數名調用方法的話,很簡單,在你調用invoke函數之前只要調用addParameter()函數即可。如下所示:

   call.addParameter("testParam",
      org.apache.axis.Constants.XSD_STRING,
      javax.xml.rpc.ParameterMode.IN);
   call.setReturnType(org.apache.axis.Constants.XSD_STRING);
將testParam定義爲調用函數的第一個參數(這裏也只有一個參數),這裏也可以同時定義該參數的類型以及該參數是輸入、輸出還是輸入輸出類型。在這裏它是一個輸入類型,現在當你運行程序,你將得到下面的消息:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"
       xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <SOAP-ENV:Body>
 <ns1:echoString xmlns:ns1="http://soapinterop.org/">
   <testParam xsi:type="xsd:string">Hello!</testParam>
 </ns1:echoString>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

3. 返回類型
在上面的代碼中我們知道echoString函數將返回一個String對象,而且我們也希望通過客戶端的調用能夠返回預期的String對象。下面是一個典型的通過調用echoString函數後獲得的Soap信封(消息)。
<?xml version="1.0" encoding="UTF-8"?>
  <SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"
     xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <SOAP-ENV:Body>
   <ns1:echoStringResponse xmlns:ns1="http://soapinterop.org/">
 <result xsi:type="xsd:string">Hello!</result>
   </ns1:echoStringResponse>
  </SOAP-ENV:Body>
 </SOAP-ENV:Envelope>
我們可以看到這裏已經聲明瞭返回類型(<result xsi:type="xsd:string">)是一個String對象。這樣Axis就可以將返回結果反序列化成我們想要的String對象了。
很多工具都會將這種確定的類型信息放到XML文件中,以生成消息的“自我描述部分”,另一方面,還有一些工具是象下面這樣返回響應的:(Many toolkits put this kind of explicit typing information in the XML to make the message "self-describing". On the other hand, some toolkits return responses that look like this:)
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"
       xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <SOAP-ENV:Body>
  <ns1:echoStringResponse xmlns:ns1="http://soapinterop.org/">
   <result>Hello, I'm a string!</result>
  </ns1:echoStringResponse>
 </SOAP-ENV:Body>
</SOAP-ENV:Envelope>
在這裏並沒有返回類型,那麼我們怎麼知道應該將返回結果反序列化成什麼類型的結果呢?答案是metadata,在這種情況下,我們需要一個描述來指明我們期望的返回類型,下面這行代碼說明了在客戶端應該如何去做:
call.setReturnType( org.apache.axis.Constants.XSD_STRING );
這個方法將會告訴Axis客戶端,如果返回的結果沒有指明類型的話,那麼Axis將會把返回類型指明爲xsi:type屬性所預定義的SOAP類型,在這裏XSD_STRING屬性所指明的是String類型。

所以也有這樣一個相似的方法,允許你指定所期望返回的Java的類。
call.setReturnClass(String.class);

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章