翻譯自:http://ws.apache.org/axis/java/user-guide.html
什么是SOAP?
SOAP是一個(gè)基于xml的通信協(xié)議和應(yīng)用內(nèi)部通訊的編碼格式。目前是1.2版,盡管1.1使用的更為廣泛。
w3c負(fù)責(zé)管理這個(gè)標(biāo)準(zhǔn)
什么是axis?
axis是Apache EXtensible Interaction System的縮寫(xiě)。它本質(zhì)上是一個(gè)soap引擎--一個(gè)用來(lái)構(gòu)造soap
處理器(比如客戶端,服務(wù)端,網(wǎng)關(guān))的框架。目前的版本是用java來(lái)寫(xiě)的,用c++實(shí)現(xiàn)的客戶端正在被
開(kāi)發(fā)。但是,axis并不僅僅是一個(gè)soap引擎,他還有很多其他的功能。
axis是apache soap的第三代,它來(lái)自ibm的SOAP4J。
一些概念:
apache axis是一個(gè)開(kāi)源soap服務(wù)器和客戶端。soap是一個(gè)用來(lái)在網(wǎng)絡(luò)上任意語(yǔ)言編寫(xiě)的系統(tǒng)之間做應(yīng)用
內(nèi)部通訊的機(jī)制。soap通常在http層交換消息:客戶端發(fā)送一個(gè)soap請(qǐng)求,并且獲得或者一個(gè)http成功
碼和一個(gè)soap應(yīng)答或者一個(gè)http錯(cuò)誤碼。開(kāi)源意味著你可以得到源代碼,但是當(dāng)你遇到麻煩的時(shí)候沒(méi)有
正式的支持組織來(lái)幫助你。
soap消息是xml消息。這些消息在soap系統(tǒng)中交換結(jié)構(gòu)化的信息。消息由一個(gè)或多個(gè)soap包含在信封頭或
者soap主體中的元素組成。soap有2種語(yǔ)法來(lái)描述這些元素中的信息。axis把java對(duì)性變成soap數(shù)據(jù),在
它發(fā)送或接受的時(shí)候。soap在遇到問(wèn)題的時(shí)候會(huì)發(fā)送錯(cuò)誤碼;axis把它們轉(zhuǎn)化為java異常。
soap專(zhuān)注于連接各個(gè)獨(dú)立的系統(tǒng)。它不是用來(lái)緊密綁定被同一個(gè)小組所開(kāi)發(fā)的程序的機(jī)制。它能綁定
java程序在一起,但是不如rmi或者corba那么緊密。如果你嘗試發(fā)送許多被rmi序列化的java對(duì)象,你將
會(huì)對(duì)axis大失所望。這是它設(shè)計(jì)的初衷:和語(yǔ)言無(wú)關(guān).
axis實(shí)現(xiàn)了jax-rpc api,一個(gè)標(biāo)準(zhǔn)的java服務(wù)的途徑.如果你看一下sun網(wǎng)站上的規(guī)范或者手冊(cè),你將明白
這些api.
axis被編譯為axis.jar文件,它實(shí)現(xiàn)了在jaxrpc.jar和saaj.jar中聲明的jax-rpc api.它需要很多輔助的
庫(kù).比如logging,wsdl相關(guān).所有這些文件被打包成axis.war文件,可以被用來(lái)直接放在servlet容器
下.axis自帶了許多soap服務(wù)的樣例.你可以添加你自己的東西通過(guò)添加編譯過(guò)的類(lèi)文件到axis的webapp
下并注冊(cè)它們.
安裝axis并使用userguide
classpath設(shè)置:確保axis.jar ,jaxrpc.jar,saaj.jar ,commons-logging.jar ,commons-discovery.jar ,wsdl4j.jar ,Xerces.jar在你的classpath之中
一個(gè)最基本的例子:
來(lái)看一個(gè) web service客戶端是如何來(lái)調(diào)用apache公開(kāi)的的axis服務(wù)器的。
1 import org.apache.axis.client.Call;
2 import org.apache.axis.client.Service;
3 import javax.xml.namespace.QName;
4
5 public class TestClient {
6 public static void main(String [] args) {
7 try {
8 String endpoint =
9 "
10
11 Service service = new Service();
12 Call call = (Call) service.createCall();
13
14 call.setTargetEndpointAddress( new java.net.URL(endpoint) );
15 call.setOperationName(new QName("
16
17 String ret = (String) call.invoke( new Object[] { "Hello!" } );
18
19 System.out.println("Sent 'Hello!', got '" + ret + "'");
20 } catch (Exception e) {
21 System.err.println(e.toString());
22 }
23 }
24 }
這個(gè)代碼在 samples/userguide/example1/TestClient.java中
如果你可用的網(wǎng)絡(luò)連接,可以運(yùn)行程序:
% java samples.userguide.example1.TestClient
Sent 'Hello!', got 'Hello!'
%
在11和12行,我們創(chuàng)建了一個(gè)Service和一個(gè)Call對(duì)象。這些是標(biāo)準(zhǔn)的用來(lái)存儲(chǔ)被service調(diào)用的元數(shù)據(jù)JAX-RPC對(duì)象。在14行,我們建立了我們的終端url-這是我們的soap消息目的地。在15行,我們定義了web service的方法。在17行,我們真正開(kāi)始調(diào)用需要的服務(wù),傳遞了一個(gè)參數(shù)數(shù)組--在這個(gè)例子中只是一個(gè)string.
你可以通過(guò)查看soap的請(qǐng)求來(lái)了解發(fā)生在參數(shù)上的一切。
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:xsd="
xmlns:SOAP-ENV="
xmlns:xsi="
<SOAP-ENV:Body>
<ns1:echoString xmlns:ns1="
<arg0 xsi:type="xsd:string">Hello!</arg0>
</ns1:echoString>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
那個(gè)String的參數(shù)自動(dòng)的被序列化為xml,而且服務(wù)器返回一個(gè)同樣的我們想要的String。
注意:你或許需要一個(gè)tcpmon或者soap monitor工具來(lái)收集這個(gè)xml文件。
命名參數(shù)
在上面的例子中,我們注意到,axis自動(dòng)命名了在soap中的xml編碼的參數(shù)arg0,arg1.等等。(這個(gè)例子中只有arg0).如果你不想用這種方式,很容易,在調(diào)用invoke()方法之前對(duì)每個(gè)參數(shù)調(diào)用addParameter 而且對(duì)返回值調(diào)用setReturnType ,例如:
call.addParameter("testParam",
org.apache.axis.Constants.XSD_STRING,
javax.xml.rpc.ParameterMode.IN);
call.setReturnType(org.apache.axis.Constants.XSD_STRING);
例子中,就會(huì)把testParam賦給調(diào)用函數(shù)的第一個(gè)參數(shù).它也定義了參數(shù)的類(lèi)型以及是否是輸入,輸出或者輸入?yún)?shù)---這個(gè)例子中是輸入?yún)?shù).
現(xiàn)在,如果你運(yùn)行這個(gè)程序,你將得到下面的消息:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:xsd="
xmlns:SOAP-ENV="
xmlns:xsi="
<SOAP-ENV:Body>
<ns1:echoString xmlns:ns1="
<testParam xsi:type="xsd:string">Hello!</testParam>
</ns1:echoString>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
看到了,參數(shù)按照預(yù)期被命名為testParam
在上面的例子中,我們把返回得類(lèi)型強(qiáng)轉(zhuǎn)型為了String類(lèi)型。一個(gè)典型的返回xml是這樣的
<?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這樣的元數(shù)據(jù)存在。為了確保類(lèi)型能被正確識(shí)別,避免潛在的錯(cuò)誤。我們可以這么做
call.setReturnType( org.apache.axis.Constants.XSD_STRING );
或者這樣
call.setReturnClass(String.class);
他將告訴axis調(diào)用端,如果返回的元素中沒(méi)有被定義類(lèi)型,他將被預(yù)定義為string類(lèi)型