翻译自:http://ws.apache.org/axis/java/user-guide.html
什么是SOAP?
SOAP是一个基于xml的通信协议和应用内部通讯的编码格式。目前是1.2版,尽管1.1使用的更为广泛。
w3c负责管理这个标准
什么是axis?
axis是Apache EXtensible Interaction System的缩写。它本质上是一个soap引擎--一个用来构造soap
处理器(比如客户端,服务端,网关)的框架。目前的版本是用java来写的,用c++实现的客户端正在被
开发。但是,axis并不仅仅是一个soap引擎,他还有很多其他的功能。
axis是apache soap的第三代,它来自ibm的SOAP4J。
一些概念:
apache axis是一个开源soap服务器和客户端。soap是一个用来在网络上任意语言编写的系统之间做应用
内部通讯的机制。soap通常在http层交换消息:客户端发送一个soap请求,并且获得或者一个http成功
码和一个soap应答或者一个http错误码。开源意味着你可以得到源代码,但是当你遇到麻烦的时候没有
正式的支持组织来帮助你。
soap消息是xml消息。这些消息在soap系统中交换结构化的信息。消息由一个或多个soap包含在信封头或
者soap主体中的元素组成。soap有2种语法来描述这些元素中的信息。axis把java对性变成soap数据,在
它发送或接受的时候。soap在遇到问题的时候会发送错误码;axis把它们转化为java异常。
soap专注于连接各个独立的系统。它不是用来紧密绑定被同一个小组所开发的程序的机制。它能绑定
java程序在一起,但是不如rmi或者corba那么紧密。如果你尝试发送许多被rmi序列化的java对象,你将
会对axis大失所望。这是它设计的初衷:和语言无关.
axis实现了jax-rpc api,一个标准的java服务的途径.如果你看一下sun网站上的规范或者手册,你将明白
这些api.
axis被编译为axis.jar文件,它实现了在jaxrpc.jar和saaj.jar中声明的jax-rpc api.它需要很多辅助的
库.比如logging,wsdl相关.所有这些文件被打包成axis.war文件,可以被用来直接放在servlet容器
下.axis自带了许多soap服务的样例.你可以添加你自己的东西通过添加编译过的类文件到axis的webapp
下并注册它们.
安装axis并使用userguide
classpath设置:确保axis.jar ,jaxrpc.jar,saaj.jar ,commons-logging.jar ,commons-discovery.jar ,wsdl4j.jar ,Xerces.jar在你的classpath之中
一个最基本的例子:
来看一个 web service客户端是如何来调用apache公开的的axis服务器的。
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 "http://ws.apache.org:5049/axis/services/echo";
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("http://soapinterop.org/", echoString"));
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 }
这个代码在 samples/userguide/example1/TestClient.java中
如果你可用的网络连接,可以运行程序:
% java samples.userguide.example1.TestClient
Sent 'Hello!', got 'Hello!'
%
在11和12行,我们创建了一个Service和一个Call对象。这些是标准的用来存储被service调用的元数据JAX-RPC对象。在14行,我们建立了我们的终端url-这是我们的soap消息目的地。在15行,我们定义了web service的方法。在17行,我们真正开始调用需要的服务,传递了一个参数数组--在这个例子中只是一个string.
你可以通过查看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>
那个String的参数自动的被序列化为xml,而且服务器返回一个同样的我们想要的String。
注意:你或许需要一个tcpmon或者soap monitor工具来收集这个xml文件。
命名参数
在上面的例子中,我们注意到,axis自动命名了在soap中的xml编码的参数arg0,arg1.等等。(这个例子中只有arg0).如果你不想用这种方式,很容易,在调用invoke()方法之前对每个参数调用addParameter 而且对返回值调用setReturnType ,例如:
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>
看到了,参数按照预期被命名为testParam
在上面的例子中,我们把返回得类型强转型为了String类型。一个典型的返回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这样的元数据存在。为了确保类型能被正确识别,避免潜在的错误。我们可以这么做
call.setReturnType( org.apache.axis.Constants.XSD_STRING );
或者这样
call.setReturnClass(String.class);
他将告诉axis调用端,如果返回的元素中没有被定义类型,他将被预定义为string类型