Axis1.4+开发指南


Axis1.4 开发指南 第 1 页 共 75 页 Axis1.4Axis1.4Axis1.4 Axis1.4 开发指南 VVV V 1.01.01.0 1.0 作 者 ProdigyWitProdigyWitProdigyWit ProdigyWit (QQ:3562720) AlongAlongAlong Along (QQ:36224205) 版权说 明 版权说 明 版权说 明 版权说 明 本文档版权归原作者所有。 在免费的前提下,可在网络媒体中自由传播。 如果需要部分或者全文引用,请注明出处。 文档版 本更新 说明 文档版 本更新 说明 文档版 本更新 说明 文档版 本更新 说明 本文档 参考并 引用了以 下著作 本文档 参考并 引用了以 下著作 本文档 参考并 引用了以 下著作 本文档 参考并 引用了以 下著作 版本号 发布时间 说明 V1.0 2008-7-15 发布。 著作名 著作日期 作者 Axis Webservice 教程 未知 未知 Axis1.4 开发指南 第 2 页 共 75 页 目录 目录 目录 目录 AXIS1.4AXIS1.4AXIS1.4 AXIS1.4 开发指南... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . ... . 111 1 版权说明...................................................................................................................................................1 文档版本更新说明................................................................................................................................1 本文档参考并引用了以下著作........................................................................................................1 目录............................................................................................................................................................ 2 1.WEBSERVICE 简介.........................................................................................................3 1.1 WebService 介绍.....................................................................................................3 1.2 WebService 的开源实现.........................................................................................3 2.AXIS 使用.....................................................................................................................3 2.1 AXIS的介绍........................................................................................................... 3 2.2 AXIS的下载........................................................................................................... 3 2.3 AXIS的安装........................................................................................................... 4 2.4 开发自己的 WebService........................................................................................6 2.4.1 即时发布——JWS(Java Web Service )......................................................... 6 2.4.2 定制发布——WSDD.....................................................................................8 2.4.3 取消发布一个 WebService...........................................................................11 3.WSDD 高级特性........................................................................................................12 3.1 WSDD 的高级特性.............................................................................................. 12 3.2 高级特性 Handler...............................................................................................12 3.4 高级特性 Chain...................................................................................................16 3.5 传递复杂对象..................................................................................................... 20 3.5.1 List、Map、数组和自定义对象.................................................................. 20 3.5.2 带内部类的自定义对象................................................................................37 3.5.3 RMI 方式远程调用....................................................................................... 57 3.6 抛出异常............................................................................................................. 60 3.7 传递文件............................................................................................................. 67 4.AXIS 的常用的命令和调试工具的使用.................................................................................72 4.1 AXIS的常用命令:............................................................................................. 72 4.2 调试工具的使用................................................................................................. 72 5.后话..........................................................................................................................74 Axis1.4 开发指南 第 3 页 共 75 页 1.WebService 1.WebService 1.WebService 1.WebService 简介 简介 简介 简介 1.11.11.1 1.1 WebService WebService WebService WebService 介绍 WebService 让一个程序可以透明地调用互联网的程序,不用管具体的实现细节。只要 WebService公开了服务接口,远程客户端就可以调用服务。WebService是基于http 协议的组件 服务,WebService 是分散式应用程序的发展趋势。 1.21.21.2 1.2 WebService WebService WebService WebService 的开源实现 WebService 更多是一种标准,而不是一种具体的技术。不同的平台,不同的语言大都提供 WebService 的开发实现。在JAVA领域,WebService的框架很多,例如:Axis1&2、CXF……。其 中一个成熟实现是AXIS。AXIS应用比较广泛,而且资料相对也比较多。 2.AXIS 2.AXIS 2.AXIS 2.AXIS 使用 使用 使用 使用 2.12.12.1 2.1 AXIS AXIS AXIS AXIS 的介绍 A x is(AAA A pache eXXX X tensible III I nteraction SSS S ystem)是一款开源的 WebService 运行引擎,它是 SOAP 协议的一个实现,其本身来源于 Apache 的另一个项目 Apache SOAP。Axis 分为 1.x 系列和 2系 列,两个系列体系结构和使用上有较大的区别,相对而言,Axis1.x 更加稳定,文档也比较齐全 , 因此本文内容以 Axis 1.x 系列最新版本 1.4 为基础。 2.22.22.2 2.2 AXIS AXIS AXIS AXIS 的下载 登陆http://www.apache.org/dyn/closer.cgi/ws/axis/1_4 站点,Axis 的版本是1.4,本 文的例子都是基于该版本完成的。下载axis-bin-1_4.zip 文件,解压改文件,文件结构如下: Docs:存放Axis 的说明文档。 Lib:存放Axis 的二进制发布包。 Samples:存放利用Axis 发布的WebService 的示例代码。 Webapps:存放安装Axis 的基础应用。 Xmls:存放相关说明文档。 Axis1.4 开发指南 第 4 页 共 75 页 2.32.32.3 2.3 AXIS AXIS AXIS AXIS 的安装 安装Axis,首先必须保证系统已经正确安装web 服务器,本人使用的Tomcat5.0.28。也可 使用其他应用服务器,例如:weblogic。Webapps下的Axis路径全部复制到Tomcat的Webapps下。 然后打开浏览器:http://127.0.0.1:8080/axis。 如果出现如图所示界面则表示已经安装成功了。 然后点击上面页面的”Validation”连接,如图: Axis1.4 开发指南 第 5 页 共 75 页 该页显示Axis 的必需组件还缺少一个没有安装,两个可选组件也没有安装,单击上面的提示: 必需组件: http://java.sun.com/products/javabeans/glasgow/jaf.html 可选组件: http://java.sun.com/products/javamail/ http://xml.apache.org/security/ 分别下载:jaf-1_1-fr.zip,javamail-1_4.zip,xml-security-bin-1_2_1.zip包,然后把jaf- 1_1-fr.zip 里的Activation.jar ,javamail-1_4.zip 里的mail.jar,xml-security-bin- 1_2_1.zip里的xmlsec-1.2.1.jar,xalan.jar都放到你的axis应用的WEB-INF/lib下然后在校验 Axis,看到页面提示全部安装成功。 Axis1.4 开发指南 第 6 页 共 75 页 2.42.42.4 2.4 开发自己的 WebServiceWebServiceWebService WebService AXIS 提供了两种发布方式:  即时发布(Instant Deployment)  定制发布( Custom Deployment) 即时发布提供了一种非常简单的WebService的发布方式,但是其中限制太多,因此在实际 的开发中定制发布才是首选。这里也将会以定制发布为重点来介绍。 2.4.12.4.12.4.1 2.4.1 即 时发 布 即 时发 布 即 时发 布 即 时发 布 —————— —— JWS(JavaJWS(JavaJWS(Java JWS(Java WebWebWeb Web ServiceServiceService Service ))) ) 即时发布提供了一种非常简单发布方式,发布者只要有Java源代码(也就是.java文 件 ), 然后把其后缀名改成jws(也就是Java Web Service的缩写)拷贝到%TOMCAT_HOME%\webapps\axis 目录下即完成了所有的发布工作。AXIS的编译引擎会处理接下来的所有事情。下面是一段示例 代码: 服务端: Axis1.4 开发指南 第 7 页 共 75 页 Java代码: /** *JWS方式WebService服务类 * *@author@author@author @author Along * *@version@version@version @version $Revision$ * *@since@since@since @since 2008-7-10 */ publicpublicpublic public classclassclass class HelloWorldJWS { publicpublicpublic public String test(String a, Integer b) { String result = "a=" + a + ", b=" + b; System.out.println("Received: " + result); returnreturnreturn return "Server Response OK, you send: " + result; } } 把HelloWorldJWS.java文件改成HelloWorldJWS.jws然后拷贝到%TOMCAT_HOME%\webapps\axis 目录下,启动Tomcat 之后访问http://localhost:8080/axis/HelloWorldJWS.jws如果能看到 Click to see the WSDL这个超链接,就说明已经发布成功了。点击进去就可以看到这个 WebService的WSDL描述文件。Server端的发布已经完成了,接下来就是编写Client端测试代码 了。 客户端: Java代码: importimportimport import java.rmi.RemoteException; importimportimport import javax.xml.namespace.QName; importimportimport import javax.xml.rpc.ServiceException; importimportimport import org.apache.axis.client.Call; importimportimport import org.apache.axis.client.Service; publicpublicpublic public classclassclass class ClientJWS { /** *@param@param@param @param args Axis1.4 开发指南 第 8 页 共 75 页 */ publicpublicpublic public staticstaticstatic static voidvoidvoid void main(String[] args) { trytrytry try { String url = "http://127.0.0.1:8080/myaxis/HelloWorldJWS.jws"; Service serv = newnewnew new Service(); Call call = (Call) serv.createCall(); call.setTargetEndpointAddress(url); call.setOperationName(newnewnew new QName(url, "test")); String result = (String) call.invoke(newnewnew new Object[]{"Quahilong", 100}); System.out.println("result = " + result); } catchcatchcatch catch (ServiceException e) { e.printStackTrace(); } catchcatchcatch catch (RemoteException e) { e.printStackTrace(); } } } 测试代码很简单,如果熟悉java反射机制的朋友不用两分钟就能看明白。运行后客户端控制台 出现以下运行结果。果然很简单吧,不过在这简单背后却是以牺牲灵活性为代价的。 运行结果: 客户端: result = Server Response OK, you send: a=Quahilong, b=100 注意:假如你现在手里只有.class 或者一个 jar 包,jws 就不再能满足你的需求了,最要命的就 是即时发布不支持带包的类,这点 AXIS 的用户手册上写的也很明白。 2.4.22.4.22.4.2 2.4.2 定 制发 布 定 制发 布 定 制发 布 定 制发 布 —————— —— WSDDWSDDWSDD WSDD 比起即时发布,定制发布更加烦琐也更复杂,但是换来的却是更大的灵活性,因此在实际 项目中定制发布还是不二的选择。定制发布需要你自己编写一个WSDD(Web Service Deployment Descriptor)文件,其实就是一个XML描述文件,稍后会做出介绍。废话不多说,我们来看代码 : 服务端: Java代码: Axis1.4 开发指南 第 9 页 共 75 页 packagepackagepackage package webservice.axis.wsdd; publicpublicpublic public classclassclass class HelloWorldWSDD { privateprivateprivate private intintint int requestCount = 0; publicpublicpublic public String hello(String name) { requestCount++; System.out.println("requestCount=" + requestCount); System.out.println("Received: " + name); returnreturnreturn return "Hello " + name; } publicpublicpublic public Float add(Float a, floatfloatfloat float b) { requestCount++; String result = "a=" + a + ", b=" + b; System.out.println("requestCount=" + requestCount); System.out.println("Received: " + result); returnreturnreturn return a + b; } } 一个带包的很简单的类,在eclipse 下编译后按照包名拷到%TOMCAT_HOME%\webapps\axis\WEB- INF\classes目录下。 以这个类为例,拷贝完之后这个HelloWorldWSDD.class 的路径就是 %TOMCAT_HOME%\webapps\axis\WEBINF\classes\webservice\myaxis\wsdd。PS:如果嫌这样太 麻烦,可以另外建一个Java Web工程用myeclipse的发布工具发布到Tomcat之后,整体一次性拷 贝到WebSericve 的工程中。接下来就需要编写发布文件deploy.wsdd 。 到 %TOMCAT_HOME%\webapps\axis\WEB-INF目录下建立这个文件并在其中添加如下内容: XML代码: Axis1.4 开发指南 第 10 页 共 75 页 简单的介绍下各个节点的含义,“HelloWorldWSDD”当然是这个WebService的名字,后面紧跟的 java:RPC指的是服务类型。这里一共有有4种类型,分别是:RPC,Document,Wrapped和Message。 有兴趣可以看下org.apache.axis.providers这个包和子包下面的类的API文档。之后的 parameter节点第一个当然是指出具体的类,第二个从字面上也很好理解:允许调用的方法。这 里的配置告诉引擎可以调用所有的public方法,当然你也可以自己指定。 编写完配置发布文件之后,cmd打开windows的控制台,进入: %TOMCAT_HOME%\webapps\axis\WEB-INF 目录下键入如下命令: java -Djava.ext.dirs=lib org.apache.axis.client.AdminClient deploy.wsdd 之后控制台返回Processing file deploy.wsdd 和Done processing 这两段话即说明发布成 功。(此时会在同级目录生成一个server-config.wsdd文件)在这里的AdminClient是AXIS提供 的一个客户端管理工具。至于java.ext.dirs的含义可以去了解一下classloader和JVM类装载机 制方面的知识,在这里就不多解释。还有一点要注意的是在发布的时候Tomcat服务必须处于启 动状态,否则就会抛出一堆无法连接的异常信息。发布成功之后你可以通过访问 http://localhost:8080/axis/servlet/AxisServlet 来查看你所有的定制发布的服务。 客户端代码: Java代码: packagepackagepackage package webservice.axis.wsdd; importimportimport import java.rmi.RemoteException; importimportimport import javax.xml.namespace.QName; importimportimport import javax.xml.rpc.ServiceException; importimportimport import org.apache.axis.client.Call; importimportimport import org.apache.axis.client.Service; publicpublicpublic public classclassclass class ClientWSDD { publicpublicpublic public staticstaticstatic static voidvoidvoid void main(String[] args) { trytrytry try { String url = "http://127.0.0.1:8080/myaxis/services/HelloWorldWSDD"; Service serv = newnewnew new Service(); Call call = (Call) serv.createCall(); call.setTargetEndpointAddress(url); call.setOperationName(newnewnew new QName(url, "hello")); Axis1.4 开发指南 第 11 页 共 75 页 String result = (String) call.invoke(newnewnew new Object[]{"Quhailong"}); System.out.println("result = " + result); call.setOperationName(newnewnew new QName(url, "add")); Float returnValue = (Float) call.invoke(newnewnew new Object[]{newnewnew new Float(3.2), newnewnew new Float(2.8)}); System.out.println("returnValue = " + returnValue); } catchcatchcatch catch (ServiceException e) { e.printStackTrace(); } catchcatchcatch catch (RemoteException e) { e.printStackTrace(); } } } 运行测试代码,输出以下结果,说明发布成功。仔细观察下发现其实除了那个url之外,即时发 布和定制发布的客户端调用代码基本上都是一样的。定制发布的URL可以在WSDL文件里找到。其 实定制发布还有一些高级特性,这个就留到下一篇再说吧。 运行结果: result = Hello Quhailong returnValue = 6.0 2.4.32.4.32.4.3 2.4.3 取 消发 布一 个 取 消发 布一 个 取 消发 布一 个 取 消发 布一 个 WebServiceWebServiceWebService WebService 刚才讲了怎么发布一个WebService,但是如何取消没有却没有提。其实取消一个已经发布 的WebService也是非常简单的,我们就刚才的HelloWorld来做例子吧。发布WebService的时候 我们有一个deploy.wsdd文件,当然在取消发布的时候就会有一个undeploy.wsdd文件。这个文 件的内容也很简单,xml的代码如下。 XML代码: 编写完这个xml文件之后,把它同样copy 到%TOMCAT_HOM\webapps\axis\WEB-INF目录下,然后 CMD 打开控制台,在控制台输入一个我们很熟悉的命令: Axis1.4 开发指南 第 12 页 共 75 页 java -Djava.ext.dirs=lib org.apache.axis.client.AdminClient undeploy.wsdd 运行之后得到如下结果说明取消发布成功。 运行结果: 客户端: Processing file undeploy.wsdd Done processing 3.WSDD 3.WSDD 3.WSDD 3.WSDD 高级特 性 高级特 性 高级特 性 高级特 性 3.13.13.1 3.1 WSDD WSDD WSDD WSDD 的高级特性 说完取消发布之后就来说一下AXIS 的一些高级特性,AXIS 在编写deploy.wsdd 这个文件 时,每个节点下面会有这样一个子节点。 XML代码: 这个节点配置着你的service object 也就是你WebService服务的那个object ,在后面的value 里可以有三个选项request、session、application。熟悉 Jsp、Servlet、或者 EJB里的SessionBean 的朋友应该能很快能明白这个三个配置选项的含义。  requst:这个选项会让AXIS为每一个SOAP的请求产生一个服务对象,可以想像如果这个 webservice的对象足够复杂,而且SOAP的请求过多,这个选项是非常耗费服务器性能的。  session:如果选择了session,程序就会给每个调用这个WebService的客户端创造一个服 务对象。  application:这个选项最彪悍,程序只会在内存里new出来一个服务对象,然后为所有 WebService客户端服务。很显然这个选项不能储存客户端的一些个性化数据。所以在功能 性上很多时候不能满足要求。 3.23.23.2 3.2 高级特性 HandlerHandlerHandler Handler 接下来说一下Axis 的Handler 和Chain 机制,Handler 和Chain 是Axis 引擎提供的一个 很强大的工具。假如现在客户有这样一个需求:需要记录某一个WebService被调用的次数。这 Axis1.4 开发指南 第 13 页 共 75 页 个时候如果在service object 里去实现这个功能,不仅麻烦而且侵入了原有的程序,也会增加 原有程序的不稳定性。有了Handler我们就能很容易的解决这个问题。我们先来编写handler 的代码。 服务端: Java代码: packagepackagepackage package webservice.axis.wsddhandler; importimportimport import org.apache.axis.AxisFault; importimportimport import org.apache.axis.MessageContext; importimportimport import org.apache.axis.handlers.BasicHandler; /** * WebService的Handle类,可以在WebService每个方法被调用之前或者之后做一些事情。 * *@author@author@author @author Along * *@version@version@version @version $Revision$ * *@since@since@since @since 2008-7-10 */ publicpublicpublic public classclassclass class HelloWorldHandler extendsextendsextends extends BasicHandler { privateprivateprivate private staticstaticstatic static finalfinalfinal final longlonglong long serialVersionUID = 3562695953982109022L; privateprivateprivate private staticstaticstatic static longlonglong long COUNT = 0L; privateprivateprivate private intintint int requestCount = 0; /* *(non-Javadoc) * *@see org.apache.axis.Handler#invoke(org.apache.axis.MessageContext) */ publicpublicpublic public voidvoidvoid void invoke(MessageContext arg0) throwsthrowsthrows throws AxisFault { requestCount++; COUNT++; String status = (String) thisthisthis this .getOption("status"); System.out.println("HelloWorldHandler's status is: " + status + ", COUNT=" + COUNT + ", HandlerRequestCount=" + requestCount); } Axis1.4 开发指南 第 14 页 共 75 页 } BasicHandler是一个抽象类,Axis提供了很多Handler的具体实现,BasicHandler只是其中最简 单的一个。要实现一个自己的handler首先要从继承BasicHandler这个类开始并实现其中的 invoke(MessageContext arg)这个方法。MessageContext可以看成是一个Axis的上下文,里面 存储的是一些Axis 和WebService的基本信息。想了解的朋友可以看一下Axis的API。编写完 Handler代码之后我们连编写发布文件。 XML代码: 发布代码中有这样的一句,细心的朋友一定会发现: 看完这句代码再对比一下Handler的实现代码中的一句,相信大多数人都能明白了。 Java代码: String status = (String) thisthisthis this .getOption("status"); Handle r通过getOption(String)这个方法拿到了配置文件中我配置的属性值。而我们上述所做 的所有工作对于原来的WebSerivce来说都是透明的,不会对侵入原有的程序当中。一个Handler 可以被多个service所使用,通过这个标签来引用到某一个service中,这里还要 多提一句:既然是一个requestFlow,当然可以加多个Handler。接下来编写测试代码运行。 Axis1.4 开发指南 第 15 页 共 75 页 客户端: Java代码: packagepackagepackage package webservice.axis.wsddhandler; importimportimport import java.rmi.RemoteException; importimportimport import javax.xml.namespace.QName; importimportimport import javax.xml.rpc.ServiceException; importimportimport import org.apache.axis.client.Call; importimportimport import org.apache.axis.client.Service; publicpublicpublic public classclassclass class ClientWSDDHandler { publicpublicpublic public staticstaticstatic static voidvoidvoid void main(String[] args) { trytrytry try { String url = "http://127.0.0.1:8080/myaxis/services/HelloWorldWSDDHandler"; Service serv = newnewnew new Service(); Call call = (Call) serv.createCall(); call.setTargetEndpointAddress(url); call.setOperationName(newnewnew new QName(url, "hello")); String result = (String) call.invoke(newnewnew new Object[]{"Quhailong"}); System.out.println("result = " + result); call.setOperationName(newnewnew new QName(url, "add")); Float returnValue = (Float) call.invoke(newnewnew new Object[]{newnewnew new Float(3.2), newnewnew new Float(2.8)}); System.out.println("returnValue = " + returnValue); } catchcatchcatch catch (ServiceException e) { e.printStackTrace(); } catchcatchcatch catch (RemoteException e) { e.printStackTrace(); } } } 在本地应用服务器上会打出如下语句说明测试成功,而且handler是配置在requestFlow标签中 Axis1.4 开发指南 第 16 页 共 75 页 所以这段代码会在service代码之前先执行。如果要在service之后执行,应该配置在 标签中。 运行结果: 客户端: result = Hello Quhailong returnValue = 6.0 服务端: HelloWorldHandler's status is: success, COUNT=1, requestCount=1 requestCount=1 Received: Quhailong HelloWorldHandler's status is: success, COUNT=2, requestCount=2 HelloWorldHandler's status is: success, COUNT=3, requestCount=3 requestCount=1 Received: a=3.2, b=2.8 HelloWorldHandler's status is: success, COUNT=4, requestCount=4 3.43.43.4 3.4 高级特性 ChainChainChain Chain 介绍完了Handler再来介绍Chain。从Chain的字面意思就能猜到他实现的一连串Handler的 功能。假如某个service 需要不止一个Handler,或者要根据Client 的情况来选择需要那些 Handler。特别是后一个需求,我们无法用一个或者几个Handler来解决,这个时候我们就需要 来实现了。我们先再编写一个Handler,加上之前的那个Handler我们来组成一条锁链。 服务端: Java代码: packagepackagepackage package webservice.axis.wsddchain; importimportimport import org.apache.axis.AxisFault; importimportimport import org.apache.axis.MessageContext; importimportimport import org.apache.axis.handlers.BasicHandler; /** * WebService的Handle类,可以在WebService每个方法被调用之前或者之後做一些事情。 * *@author@author@author @author Along * *@version@version@version @version $Revision$ * Axis1.4 开发指南 第 17 页 共 75 页 *@since@since@since @since 2008-7-10 */ publicpublicpublic public classclassclass class HelloWorldHandler2 extendsextendsextends extends BasicHandler { privateprivateprivate private staticstaticstatic static finalfinalfinal final longlonglong long serialVersionUID = 772997192033702477L; privateprivateprivate private staticstaticstatic static longlonglong long COUNT = 0L; privateprivateprivate private intintint int requestCount = 0; /* *(non-Javadoc) * *@see org.apache.axis.Handler#invoke(org.apache.axis.MessageContext) */ publicpublicpublic public voidvoidvoid void invoke(MessageContext arg0) throwsthrowsthrows throws AxisFault { requestCount++; COUNT++; String status = (String) thisthisthis this .getOption("status"); System.out.println("This is an other handler. HelloWorldHandler2's status is: " + status + ", COUNT=" + COUNT + ", HandlerRequestCount=" + requestCount); } } 之后我们编写 Chain 的代码. 服务端: Java 代码: packagepackagepackage package webservice.axis.wsddchain; importimportimport import org.apache.axis.SimpleChain; importimportimport import webservice.axis.wsddhandler.HelloWorldHandler; /** * WebService的Handle链,可以在WebService每个方法被调用之前或之後执行多个 Handler。 * *@author@author@author @author Along * Axis1.4 开发指南 第 18 页 共 75 页 *@version@version@version @version $Revision$ * *@since@since@since @since 2008-7-10 */ publicpublicpublic public classclassclass class HelloWorldChain extendsextendsextends extends SimpleChain { privateprivateprivate private staticstaticstatic static finalfinalfinal final longlonglong long serialVersionUID = -510326708903517617L; publicpublicpublic public HelloWorldChain() { HelloWorldHandler handler1 = newnewnew new HelloWorldHandler(); HelloWorldHandler2 handler2 = newnewnew new HelloWorldHandler2(); thisthisthis this .addHandler(handler1); thisthisthis this .addHandler(handler2); } } 在Chain 的构造函数中,把我要的两个Handler用addHandler()方法加载进去。之后我们来编写 发布文件。元素有些许不同在这里有必要多句嘴:元素中的子元素 只允许是或者。后者也就是允许在“锁链”里再嵌套“锁链”,在这里就拿嵌 套来举例,他同样有两种方式来实现。 第一种是直接包含: 第二种是引用别的: 因为我们这里的HelloWorldChain并没有由BasicHandler来实现,而是由继承SimpleChain这 个类来实现,严格意义上讲,SimpleChain也可以算是一个Handler,因为SimpleChain也是从 BasicHandler继承而来,他同样实现了invoke()这个方法。下面回归正题,来看我们的发布代 码。 XML代码: 从新发布WebService之后,运行我们的测试代码。 客户端: Java代码: packagepackagepackage package webservice.axis.wsddchain; importimportimport import java.rmi.RemoteException; importimportimport import javax.xml.namespace.QName; importimportimport import javax.xml.rpc.ServiceException; importimportimport import org.apache.axis.client.Call; importimportimport import org.apache.axis.client.Service; publicpublicpublic public classclassclass class ClientWSDDChain { publicpublicpublic public staticstaticstatic static voidvoidvoid void main(String[] args) { trytrytry try { String url = "http://127.0.0.1:8080/myaxis/services/HelloWorldWSDDChain"; Service serv = newnewnew new Service(); Call call = (Call) serv.createCall(); call.setTargetEndpointAddress(url); call.setOperationName(newnewnew new QName(url, "hello")); String result = (String) call.invoke(newnewnew new Object[]{"Quhailong"}); System.out.println("result = " + result); Axis1.4 开发指南 第 20 页 共 75 页 call.setOperationName(newnewnew new QName(url, "add")); Float returnValue = (Float) call.invoke(newnewnew new Object[]{newnewnew new Float(3.2), newnewnew new Float(2.8)}); System.out.println("returnValue = " + returnValue); } catchcatchcatch catch (ServiceException e) { e.printStackTrace(); } catchcatchcatch catch (RemoteException e) { e.printStackTrace(); } } } 结果如下: 运行结果: 客户端: result = Hello Quhailong returnValue = 6.0 服务端: HelloWorldHandler's status is: null, COUNT=7, requestCount=3 This is an other handler. HelloWorldHandler2's status is: null, COUNT=3, requestCount=3 requestCount=1 Received: Quhailong HelloWorldHandler's status is: null, COUNT=8, requestCount=4 This is an other handler. HelloWorldHandler2's status is: null, COUNT=4, requestCount=4 requestCount=1 Received: a=3.2, b=2.8 3.53.53.5 3.5 传递复杂对象 3.5.13.5.13.5.1 3.5.1 ListListList List 、、、 、 MapMapMap Map 、 数组 和自 定 义对 象 、 数组 和自 定 义对 象 、 数组 和自 定 义对 象 、 数组 和自 定 义对 象 在上面介绍Axis的文章里,我们做了一个简单的WebService,我们client side传递了 Axis1.4 开发指南 第 21 页 共 75 页 String和int类型的数据给service object。Service 处理之后返回处理结果给Client。对于大 多数需求,那个demo显然已经足够应付了。但是如果client端需要传输一个对象给server,那 么那个demo 就显得力不从心了。Axis中提供了远程传输对象的方法,通过那些方法我们同样可 以随心的传递自己的对象。 先看下面的 JAVABEAN 这个对象是服务端的对象: Java 代码: importimportimport import java.io.Serializable; importimportimport import java.util.ArrayList; importimportimport import java.util.List; /** * 服务端的自定义类型 * *@author@author@author @author Along * *@version@version@version @version $Revision$ * *@since@since@since @since 2008-7-11 */ publicpublicpublic public classclassclass class Address implementsimplementsimplements implements Serializable{ privateprivateprivate private staticstaticstatic static finalfinalfinal final longlonglong long serialVersionUID = 5182870829593983607L; privateprivateprivate private Integer identifier; /** 地址 */ privateprivateprivate private String address; /** 城市 */ privateprivateprivate private String city; /** 省份 */ privateprivateprivate private String province; /** 国家 */ privateprivateprivate private String country; /** 邮编 */ privateprivateprivate private String postalCode; Axis1.4 开发指南 第 22 页 共 75 页 privateprivateprivate private String[] array; privateprivateprivate private List list; privateprivateprivate private booleanbooleanboolean boolean isExist; publicpublicpublic public Address() { list = newnewnew new ArrayList(); list.add(1); list.add(2); list.add(3); } publicpublicpublic public Integer getIdentifier() { returnreturnreturn return identifier; } publicpublicpublic public voidvoidvoid void setIdentifier(Integer identifier) { thisthisthis this .identifier = identifier; } publicpublicpublic public String getAddress() { returnreturnreturn return address; } publicpublicpublic public voidvoidvoid void setAddress(String address) { thisthisthis this .address = address; } publicpublicpublic public String getCity() { returnreturnreturn return city; } publicpublicpublic public voidvoidvoid void setCity(String city) { thisthisthis this .city = city; } publicpublicpublic public String getProvince() { returnreturnreturn return province; } Axis1.4 开发指南 第 23 页 共 75 页 publicpublicpublic public voidvoidvoid void setProvince(String province) { thisthisthis this .province = province; } publicpublicpublic public String getCountry() { returnreturnreturn return country; } publicpublicpublic public voidvoidvoid void setCountry(String country) { thisthisthis this .country = country; } publicpublicpublic public String getPostalCode() { returnreturnreturn return postalCode; } publicpublicpublic public voidvoidvoid void setPostalCode(String postalCode) { thisthisthis this .postalCode = postalCode; } publicpublicpublic public String[] getArray() { returnreturnreturn return array; } publicpublicpublic public voidvoidvoid void setArray(String[] array) { thisthisthis this .array = array; } publicpublicpublic public booleanbooleanboolean boolean isExist() { returnreturnreturn return isExist; } publicpublicpublic public voidvoidvoid void setExist(booleanbooleanboolean boolean isExist) { thisthisthis this .isExist = isExist; } publicpublicpublic public List getList() { returnreturnreturn return list; } Axis1.4 开发指南 第 24 页 共 75 页 publicpublicpublic public voidvoidvoid void setList(List list) { thisthisthis this .list = list; } } 注意:所有要传递的对象都要是可序化的。 服务端的业务: Java 代码: importimportimport import java.util.ArrayList; importimportimport import java.util.HashMap; importimportimport import java.util.List; importimportimport import java.util.Map; importimportimport import webservice.axis.wsddselfobj.servermodel.Address; /** * 提供List的WebService业务 * *@author@author@author @author Along * *@version@version@version @version $Revision$ * *@since@since@since @since 2008-7-11 */ publicpublicpublic public classclassclass class AddressManager { publicpublicpublic public List
getAddressList() { List
returnList = newnewnew new ArrayList
(); Address address = newnewnew new Address(); address.setIdentifier(1); address.setAddress("Haidian"); address.setCity("BeiJing"); address.setCountry("China"); address.setPostalCode("100081"); address.setProvince("Beijing"); address.setExist(falsefalsefalse false ); address.setArray(newnewnew new String[]{"1","2","3"}); Axis1.4 开发指南 第 25 页 共 75 页 returnList.add(address); address = newnewnew new Address(); address.setIdentifier(2); address.setAddress("Chaoyang"); address.setCity("BeiJing"); address.setCountry("China"); address.setPostalCode("100081"); address.setProvince("Beijing"); returnList.add(address); address.setExist(truetruetrue true ); address.setArray(newnewnew new String[]{"A","B","C"}); returnreturnreturn return returnList; } publicpublicpublic public List
setAddressList(List
list) { returnreturnreturn return list; } publicpublicpublic public Map getAddressMap() { Map returnMap = newnewnew new HashMap(); Address address = newnewnew new Address(); address.setIdentifier(1); address.setAddress("Haidian"); address.setCity("BeiJing"); address.setCountry("China"); address.setPostalCode("100081"); address.setProvince("Beijing"); address.setExist(falsefalsefalse false ); address.setArray(newnewnew new String[]{"1","2","3"}); returnMap.put(address.getIdentifier(), address); address = newnewnew new Address(); address.setIdentifier(2); address.setAddress("Chaoyang"); address.setCity("BeiJing"); address.setCountry("China"); Axis1.4 开发指南 第 26 页 共 75 页 address.setPostalCode("100081"); address.setProvince("Beijing"); address.setExist(truetruetrue true ); address.setArray(newnewnew new String[]{"A","B","C"}); returnMap.put(address.getIdentifier(), address); returnreturnreturn return returnMap; } publicpublicpublic public Map setAddressMap(Map map) { returnreturnreturn return map; } } 下面的客户端和客户端的 JAVABEAN 客户端 JAVABEAN: Java 代码: importimportimport import java.io.Serializable; importimportimport import java.util.ArrayList; importimportimport import java.util.List; /** * 客户端的自定义类型 * *@author@author@author @author Along * *@version@version@version @version $Revision$ * *@since@since@since @since 2008-7-11 */ publicpublicpublic public classclassclass class Address implementsimplementsimplements implements Serializable{ privateprivateprivate private staticstaticstatic static finalfinalfinal final longlonglong long serialVersionUID = 5182870829593983607L; privateprivateprivate private Integer identifier; /** 地址 */ privateprivateprivate private String address; Axis1.4 开发指南 第 27 页 共 75 页 /** 城市 */ privateprivateprivate private String city; /** 省份 */ privateprivateprivate private String province; /** 国家 */ privateprivateprivate private String country; /** 邮编 */ privateprivateprivate private String postalCode; privateprivateprivate private String[] array; privateprivateprivate private List list; privateprivateprivate private booleanbooleanboolean boolean isExist; publicpublicpublic public Address() { list = newnewnew new ArrayList(); list.add(1); list.add(2); list.add(3); } publicpublicpublic public Integer getIdentifier() { returnreturnreturn return identifier; } publicpublicpublic public voidvoidvoid void setIdentifier(Integer identifier) { thisthisthis this .identifier = identifier; } publicpublicpublic public String getAddress() { returnreturnreturn return address; } publicpublicpublic public voidvoidvoid void setAddress(String address) { thisthisthis this .address = address; } Axis1.4 开发指南 第 28 页 共 75 页 publicpublicpublic public String getCity() { returnreturnreturn return city; } publicpublicpublic public voidvoidvoid void setCity(String city) { thisthisthis this .city = city; } publicpublicpublic public String getProvince() { returnreturnreturn return province; } publicpublicpublic public voidvoidvoid void setProvince(String province) { thisthisthis this .province = province; } publicpublicpublic public String getCountry() { returnreturnreturn return country; } publicpublicpublic public voidvoidvoid void setCountry(String country) { thisthisthis this .country = country; } publicpublicpublic public String getPostalCode() { returnreturnreturn return postalCode; } publicpublicpublic public voidvoidvoid void setPostalCode(String postalCode) { thisthisthis this .postalCode = postalCode; } publicpublicpublic public String[] getArray() { returnreturnreturn return array; } publicpublicpublic public voidvoidvoid void setArray(String[] array) { thisthisthis this .array = array; } publicpublicpublic public booleanbooleanboolean boolean isExist() { Axis1.4 开发指南 第 29 页 共 75 页 returnreturnreturn return isExist; } publicpublicpublic public voidvoidvoid void setExist(booleanbooleanboolean boolean isExist) { thisthisthis this .isExist = isExist; } publicpublicpublic public List getList() { returnreturnreturn return list; } publicpublicpublic public voidvoidvoid void setList(List list) { thisthisthis this .list = list; } } 客户端: Java 代码: importimportimport import java.net.MalformedURLException; importimportimport import java.rmi.RemoteException; importimportimport import java.util.ArrayList; importimportimport import java.util.HashMap; importimportimport import java.util.Iterator; importimportimport import java.util.List; importimportimport import java.util.Map; importimportimport import javax.xml.namespace.QName; importimportimport import javax.xml.rpc.ParameterMode; importimportimport import javax.xml.rpc.ServiceException; importimportimport import org.apache.axis.client.Call; importimportimport import org.apache.axis.client.Service; importimportimport import org.apache.axis.encoding.XMLType; importimportimport import webservice.axis.wsddselfobj.clientmodel.Address; /** * 获得WebService的返回List/Map对象的客户端 * *@author@author@author @author Along Axis1.4 开发指南 第 30 页 共 75 页 * *@version@version@version @version $Revision$ * *@since@since@since @since 2008-7-11 */ @SuppressWarnings("unchecked") publicpublicpublic public classclassclass class ClientAddress { publicpublicpublic public staticstaticstatic static voidvoidvoid void getServerList() { String url = "http://127.0.0.1:8080/axis/services/AddressManager"; Service service = newnewnew new Service(); trytrytry try { Call call = (Call) service.createCall(); QName qn = newnewnew new QName("urn:AddressManager","Address"); call.registerTypeMapping(Address.classclassclass class , qn, newnewnew new org.apache.axis.encoding.ser.BeanSerializerFactory( Address.classclassclass class , qn), newnewnew new org.apache.axis.encoding.ser.BeanDeserializerFactory( Address.classclassclass class , qn)); call.setTargetEndpointAddress(newnewnew new java.net.URL(url)); call.setOperationName(newnewnew new QName("AddressManager", "getAddressList")); call.setReturnClass(ArrayList.classclassclass class ); Object[] sss = nullnullnull null ; List
list = (ArrayList) call.invoke(sss); System.out.println("List size: " + list.size()); forforfor for (Iterator
iter = list.iterator(); iter.hasNext();) { Address address = iter.next(); System.out.println("id号:" + address.getIdentifier() + " address:" + address.getAddress() Axis1.4 开发指南 第 31 页 共 75 页 + " city:" + address.getCity() + " country:" + address.getCountry() + " postalCode:" + address.getPostalCode() + " province:" + address.getProvince() + " array: " + address.getArray()[0] + " list: " + address.getList() + " isExist: " + address.isExist()); } } catchcatchcatch catch (ServiceException e) { e.printStackTrace(); } catchcatchcatch catch (MalformedURLException e) { e.printStackTrace(); } catchcatchcatch catch (RemoteException e) { e.printStackTrace(); } } publicpublicpublic public staticstaticstatic static voidvoidvoid void setServerList() { String url = "http://127.0.0.1:8080/axis/services/AddressManager"; Service service = newnewnew new Service(); List
list = newnewnew new ArrayList
(); Address address = newnewnew new Address(); address.setIdentifier(1); address.setAddress("Haidian"); address.setCity("BeiJing"); address.setCountry("China"); address.setPostalCode("100081"); address.setProvince("Beijing"); address.setExist(falsefalsefalse false ); address.setArray(newnewnew new String[]{"1","2","3"}); list.add(address); address = newnewnew new Address(); address.setIdentifier(2); address.setAddress("Chaoyang"); Axis1.4 开发指南 第 32 页 共 75 页 address.setCity("BeiJing"); address.setCountry("China"); address.setPostalCode("100081"); address.setProvince("Beijing"); address.setExist(truetruetrue true ); address.setArray(newnewnew new String[]{"A","B","C"}); list.add(address); trytrytry try { Call call = (Call) service.createCall(); QName qn = newnewnew new QName("urn:AddressManager","Address"); call.registerTypeMapping(Address.classclassclass class , qn, newnewnew new org.apache.axis.encoding.ser.BeanSerializerFactory( Address.classclassclass class , qn), newnewnew new org.apache.axis.encoding.ser.BeanDeserializerFactory( Address.classclassclass class , qn)); call.setTargetEndpointAddress(newnewnew new java.net.URL(url)); call.setOperationName(newnewnew new QName("AddressManager", "setAddressList")); call.setReturnClass(ArrayList.classclassclass class ); call.addParameter("list", XMLType.XSD_ANYTYPE, ParameterMode.IN); list = (ArrayList) call.invoke(newnewnew new Object[]{list}); System.out.println("List size: " + list.size()); forforfor for (Iterator
iter = list.iterator(); iter.hasNext();) { address = iter.next(); System.out.println("id号:" + address.getIdentifier() + " address:" + address.getAddress() + " city:" + address.getCity() + " country:" + address.getCountry() + " postalCode:" + address.getPostalCode() + " province:" + address.getProvince() + " array: " + address.getArray()[0] Axis1.4 开发指南 第 33 页 共 75 页 + " list: " + address.getList() + " isExist: " + address.isExist()); } } catchcatchcatch catch (ServiceException e) { e.printStackTrace(); } catchcatchcatch catch (MalformedURLException e) { e.printStackTrace(); } catchcatchcatch catch (RemoteException e) { e.printStackTrace(); } } publicpublicpublic public staticstaticstatic static voidvoidvoid void getServerMap() { String url = "http://127.0.0.1:8080/axis/services/AddressManager"; Service service = newnewnew new Service(); trytrytry try { Call call = (Call) service.createCall(); QName qn = newnewnew new QName("urn:AddressManager","Address"); call.registerTypeMapping(Address.classclassclass class , qn, newnewnew new org.apache.axis.encoding.ser.BeanSerializerFactory( Address.classclassclass class , qn), newnewnew new org.apache.axis.encoding.ser.BeanDeserializerFactory( Address.classclassclass class , qn)); call.setTargetEndpointAddress(newnewnew new java.net.URL(url)); Object[] sss = nullnullnull null ; call.setOperationName(newnewnew new QName("AddressManager", "getAddressMap")); call.setReturnClass(HashMap.classclassclass class ); Map map = (Map) call.invoke(sss); System.out.println("Map size: " + map.size()); Axis1.4 开发指南 第 34 页 共 75 页 forforfor for (Iterator iter = map.keySet().iterator(); iter.hasNext();) { Integer key = iter.next(); Address address = map.get(key); System.out.println("id号:" + address.getIdentifier() + " address:" + address.getAddress() + " city:" + address.getCity() + " country:" + address.getCountry() + " postalCode:" + address.getPostalCode() + " province:" + address.getProvince() + " array: " + address.getArray()[0] + " list: " + address.getList() + " isExist: " + address.isExist()); } } catchcatchcatch catch (ServiceException e) { e.printStackTrace(); } catchcatchcatch catch (MalformedURLException e) { e.printStackTrace(); } catchcatchcatch catch (RemoteException e) { e.printStackTrace(); } } publicpublicpublic public staticstaticstatic static voidvoidvoid void setServerMap() { String url = "http://127.0.0.1:8080/axis/services/AddressManager"; Service service = newnewnew new Service(); Map map = newnewnew new HashMap(); Address address = newnewnew new Address(); address.setIdentifier(1); address.setAddress("Haidian"); address.setCity("BeiJing"); address.setCountry("China"); address.setPostalCode("100081"); address.setProvince("Beijing"); Axis1.4 开发指南 第 35 页 共 75 页 address.setExist(falsefalsefalse false ); address.setArray(newnewnew new String[]{"1","2","3"}); map.put(address.getIdentifier(), address); address = newnewnew new Address(); address.setIdentifier(2); address.setAddress("Chaoyang"); address.setCity("BeiJing"); address.setCountry("China"); address.setPostalCode("100081"); address.setProvince("Beijing"); address.setExist(truetruetrue true ); address.setArray(newnewnew new String[]{"A","B","C"}); map.put(address.getIdentifier(), address); trytrytry try { Call call = (Call) service.createCall(); QName qn = newnewnew new QName("urn:AddressManager","Address"); call.registerTypeMapping(Address.classclassclass class , qn, newnewnew new org.apache.axis.encoding.ser.BeanSerializerFactory( Address.classclassclass class , qn), newnewnew new org.apache.axis.encoding.ser.BeanDeserializerFactory( Address.classclassclass class , qn)); call.setTargetEndpointAddress(newnewnew new java.net.URL(url)); call.setOperationName(newnewnew new QName("AddressManager", "setAddressMap")); call.setReturnClass(HashMap.classclassclass class ); call.addParameter("list", XMLType.XSD_ANYTYPE, ParameterMode.IN); map = (Map) call.invoke(newnewnew new Object[]{map}); System.out.println("Map size: " + map.size()); forforfor for (Iterator iter = map.keySet().iterator(); iter.hasNext();) { Integer key = iter.next(); Axis1.4 开发指南 第 36 页 共 75 页 address = map.get(key); System.out.println("id号:" + address.getIdentifier() + " address:" + address.getAddress() + " city:" + address.getCity() + " country:" + address.getCountry() + " postalCode:" + address.getPostalCode() + " province:" + address.getProvince() + " array: " + address.getArray()[0] + " list: " + address.getList() + " isExist: " + address.isExist()); } } catchcatchcatch catch (ServiceException e) { e.printStackTrace(); } catchcatchcatch catch (MalformedURLException e) { e.printStackTrace(); } catchcatchcatch catch (RemoteException e) { e.printStackTrace(); } } publicpublicpublic public staticstaticstatic static voidvoidvoid void main(String[] args) { getServerList(); getServerMap(); setServerList(); setServerMap(); } } 以上是客户端和服务端的代码,现在主要介绍一下关于 WSDD,代码如下: Axis1.4 开发指南 第 37 页 共 75 页 唯一不同的就是多了这个节点。QName表示XML 规范中定义的限定名称,他由名 称空间URI、本地部分和前缀组成。除了本地部分其他都不是必须的,另外QName是不可变的。 xmlns 后面的myNS是必须的。具体根据前面所指定的qname 来决定。之后可以随意命名一个 namespace。最后的languageSpecificType 指定的是你传递的对象类型。第一个属性的本地部 分和第二个节点你自定义的命名空间会组成一个新的QName,并将你要传输的对象mapping上去。 注意:在上面编写客户端的时候要注意几个问题:  如果你有返回值的话一定要设置你的返回值类型。  如果服务器上的方法有参数一定要指定你的参数类型。  一定要拷贝 wsdl4j-1.5.1.jar 否则会报错,找不到你的转换类型。 运行结果: 客户端: List size: 2 id号:1 address:Haidian city:BeiJing country:China postalCode:100081 province:Beijing array: 1 list: [1, 2, 3] isExist: false id号:2 address:Chaoyang city:BeiJing country:China postalCode:100081 province:Beijing array: A list: [1, 2, 3] isExist: true Map size: 2 id号:1 address:Haidian city:BeiJing country:China postalCode:100081 province:Beijing array: 1 list: [1, 2, 3] isExist: false id号:2 address:Chaoyang city:BeiJing country:China postalCode:100081 province:Beijing array: A list: [1, 2, 3] isExist: true List size: 2 id号:1 address:Haidian city:BeiJing country:China postalCode:100081 province:Beijing array: 1 list: [1, 2, 3] isExist: false id号:2 address:Chaoyang city:BeiJing country:China postalCode:100081 province:Beijing array: A list: [1, 2, 3] isExist: true Map size: 2 id号:1 address:Haidian city:BeiJing country:China postalCode:100081 province:Beijing array: 1 list: [1, 2, 3] isExist: false id号:2 address:Chaoyang city:BeiJing country:China postalCode:100081 province:Beijing array: A list: [1, 2, 3] isExist: true Axis1.4 开发指南 第 38 页 共 75 页 3.5.2 3.5.2 3.5.2 3.5.2 带 内部 类的 自 定义 对象 带 内部 类的 自 定义 对象 带 内部 类的 自 定义 对象 带 内部 类的 自 定义 对象 经过上面的了解我们对大部分的 JAVABEAN 对象有了了解,像对返回类型 List、Map。List 里有 JAVABEAN 等这些都有了相应的解决方案。下面介绍一下特殊的情况,就是对内部类的使 用废话少说来点代码一般就知道了: 服务端的 JAVABEAN: Java 代码: packagepackagepackage package webservice.axis.wsddselfobj.servermodel; importimportimport import java.io.Serializable; importimportimport import java.util.ArrayList; importimportimport import java.util.List; /** * 服务端的自定义类型 * *@author@author@author @author Along * *@version@version@version @version $Revision$ * *@since@since@since @since 2008-7-11 */ publicpublicpublic public classclassclass class Address implementsimplementsimplements implements Serializable{ privateprivateprivate private staticstaticstatic static finalfinalfinal final longlonglong long serialVersionUID = 5182870829593983607L; privateprivateprivate private Integer identifier; /** 地址 */ privateprivateprivate private String address; /** 城市 */ privateprivateprivate private String city; /** 省份 */ privateprivateprivate private String province; /** 国家 */ privateprivateprivate private String country; Axis1.4 开发指南 第 39 页 共 75 页 /** 邮编 */ privateprivateprivate private String postalCode; privateprivateprivate private String[] array; privateprivateprivate private List list; privateprivateprivate private booleanbooleanboolean boolean isExist; privateprivateprivate private InnerClass innC; publicpublicpublic public staticstaticstatic static classclassclass class InnerClass implementsimplementsimplements implements Serializable { privateprivateprivate private staticstaticstatic static finalfinalfinal final longlonglong long serialVersionUID = -2330738090948448510L; privateprivateprivate private String innerName; publicpublicpublic public String getInnerName() { returnreturnreturn return innerName; } publicpublicpublic public voidvoidvoid void setInnerName(String innerName) { thisthisthis this .innerName = innerName; } } publicpublicpublic public Address() { list = newnewnew new ArrayList(); list.add(1); list.add(2); list.add(3); innC = newnewnew new InnerClass(); innC.setInnerName("My Inner name"); } publicpublicpublic public InnerClass getInnC() { returnreturnreturn return innC; } Axis1.4 开发指南 第 40 页 共 75 页 publicpublicpublic public voidvoidvoid void setInnC(InnerClass innC) { thisthisthis this .innC = innC; } publicpublicpublic public Integer getIdentifier() { returnreturnreturn return identifier; } publicpublicpublic public voidvoidvoid void setIdentifier(Integer identifier) { thisthisthis this .identifier = identifier; } publicpublicpublic public String getAddress() { returnreturnreturn return address; } publicpublicpublic public voidvoidvoid void setAddress(String address) { thisthisthis this .address = address; } publicpublicpublic public String getCity() { returnreturnreturn return city; } publicpublicpublic public voidvoidvoid void setCity(String city) { thisthisthis this .city = city; } publicpublicpublic public String getProvince() { returnreturnreturn return province; } publicpublicpublic public voidvoidvoid void setProvince(String province) { thisthisthis this .province = province; } publicpublicpublic public String getCountry() { returnreturnreturn return country; } publicpublicpublic public voidvoidvoid void setCountry(String country) { Axis1.4 开发指南 第 41 页 共 75 页 thisthisthis this .country = country; } publicpublicpublic public String getPostalCode() { returnreturnreturn return postalCode; } publicpublicpublic public voidvoidvoid void setPostalCode(String postalCode) { thisthisthis this .postalCode = postalCode; } publicpublicpublic public String[] getArray() { returnreturnreturn return array; } publicpublicpublic public voidvoidvoid void setArray(String[] array) { thisthisthis this .array = array; } publicpublicpublic public booleanbooleanboolean boolean isExist() { returnreturnreturn return isExist; } publicpublicpublic public voidvoidvoid void setExist(booleanbooleanboolean boolean isExist) { thisthisthis this .isExist = isExist; } publicpublicpublic public List getList() { returnreturnreturn return list; } publicpublicpublic public voidvoidvoid void setList(List list) { thisthisthis this .list = list; } } 这个类需要值得注意的是 2点:  内部类必须是可序化的。  内部类必须是静态的,否则不能被序列化。 Axis1.4 开发指南 第 42 页 共 75 页 WebService 业务: Java 代码 packagepackagepackage package webservice.axis.wsddselfobj; importimportimport import java.util.ArrayList; importimportimport import java.util.HashMap; importimportimport import java.util.List; importimportimport import java.util.Map; importimportimport import webservice.axis.wsddselfobj.servermodel.Address; /** * 提供复杂对象的WebService业务 * *@author@author@author @author Along * *@version@version@version @version $Revision$ * *@since@since@since @since 2008-7-11 */ publicpublicpublic public classclassclass class AddressManager { publicpublicpublic public List
getAddressList() { List
returnList = newnewnew new ArrayList
(); Address address = newnewnew new Address(); address.setIdentifier(1); address.setAddress("Haidian"); address.setCity("BeiJing"); address.setCountry("China"); address.setPostalCode("100081"); address.setProvince("Beijing"); address.setExist(falsefalsefalse false ); address.setArray(newnewnew new String[]{"1","2","3"}); returnList.add(address); address = newnewnew new Address(); address.setIdentifier(2); address.setAddress("Chaoyang"); Axis1.4 开发指南 第 43 页 共 75 页 address.setCity("BeiJing"); address.setCountry("China"); address.setPostalCode("100081"); address.setProvince("Beijing"); returnList.add(address); address.setExist(truetruetrue true ); address.setArray(newnewnew new String[]{"A","B","C"}); returnreturnreturn return returnList; } publicpublicpublic public List
setAddressList(List
list) { returnreturnreturn return list; } publicpublicpublic public Map getAddressMap() { Map returnMap = newnewnew new HashMap(); Address address = newnewnew new Address(); address.setIdentifier(1); address.setAddress("Haidian"); address.setCity("BeiJing"); address.setCountry("China"); address.setPostalCode("100081"); address.setProvince("Beijing"); address.setExist(falsefalsefalse false ); address.setArray(newnewnew new String[]{"1","2","3"}); returnMap.put(address.getIdentifier(), address); address = newnewnew new Address(); address.setIdentifier(2); address.setAddress("Chaoyang"); address.setCity("BeiJing"); address.setCountry("China"); address.setPostalCode("100081"); address.setProvince("Beijing"); address.setExist(truetruetrue true ); address.setArray(newnewnew new String[]{"A","B","C"}); returnMap.put(address.getIdentifier(), address); Axis1.4 开发指南 第 44 页 共 75 页 returnreturnreturn return returnMap; } publicpublicpublic public Map setAddressMap(Map map) { returnreturnreturn return map; } } 上面的业务写法就不在说任何说明了。 客户端的 JAVABEAN Java 代码: packagepackagepackage package webservice.axis.wsddselfobj.clientmodel; importimportimport import java.io.Serializable; importimportimport import java.util.ArrayList; importimportimport import java.util.List; /** * 客户端的自定义类型 * *@author@author@author @author Along * *@version@version@version @version $Revision$ * *@since@since@since @since 2008-7-11 */ publicpublicpublic public classclassclass class Address implementsimplementsimplements implements Serializable{ privateprivateprivate private staticstaticstatic static finalfinalfinal final longlonglong long serialVersionUID = 5182870829593983607L; privateprivateprivate private Integer identifier; /** 地址 */ privateprivateprivate private String address; /** 城市 */ privateprivateprivate private String city; Axis1.4 开发指南 第 45 页 共 75 页 /** 省份 */ privateprivateprivate private String province; /** 国家 */ privateprivateprivate private String country; /** 邮编 */ privateprivateprivate private String postalCode; privateprivateprivate private String[] array; privateprivateprivate private List list; privateprivateprivate private booleanbooleanboolean boolean isExist; privateprivateprivate private InnerClass innC; publicpublicpublic public staticstaticstatic static classclassclass class InnerClass implementsimplementsimplements implements Serializable { privateprivateprivate private staticstaticstatic static finalfinalfinal final longlonglong long serialVersionUID = -2330738090948448510L; privateprivateprivate private String innerName; publicpublicpublic public String getInnerName() { returnreturnreturn return innerName; } publicpublicpublic public voidvoidvoid void setInnerName(String innerName) { thisthisthis this .innerName = innerName; } } publicpublicpublic public Address() { list = newnewnew new ArrayList(); list.add(1); list.add(2); list.add(3); innC = newnewnew new InnerClass(); innC.setInnerName("My Inner name"); } Axis1.4 开发指南 第 46 页 共 75 页 publicpublicpublic public InnerClass getInnC() { returnreturnreturn return innC; } publicpublicpublic public voidvoidvoid void setInnC(InnerClass innC) { thisthisthis this .innC = innC; } publicpublicpublic public Integer getIdentifier() { returnreturnreturn return identifier; } publicpublicpublic public voidvoidvoid void setIdentifier(Integer identifier) { thisthisthis this .identifier = identifier; } publicpublicpublic public String getAddress() { returnreturnreturn return address; } publicpublicpublic public voidvoidvoid void setAddress(String address) { thisthisthis this .address = address; } publicpublicpublic public String getCity() { returnreturnreturn return city; } publicpublicpublic public voidvoidvoid void setCity(String city) { thisthisthis this .city = city; } publicpublicpublic public String getProvince() { returnreturnreturn return province; } publicpublicpublic public voidvoidvoid void setProvince(String province) { thisthisthis this .province = province; } Axis1.4 开发指南 第 47 页 共 75 页 publicpublicpublic public String getCountry() { returnreturnreturn return country; } publicpublicpublic public voidvoidvoid void setCountry(String country) { thisthisthis this .country = country; } publicpublicpublic public String getPostalCode() { returnreturnreturn return postalCode; } publicpublicpublic public voidvoidvoid void setPostalCode(String postalCode) { thisthisthis this .postalCode = postalCode; } publicpublicpublic public String[] getArray() { returnreturnreturn return array; } publicpublicpublic public voidvoidvoid void setArray(String[] array) { thisthisthis this .array = array; } publicpublicpublic public booleanbooleanboolean boolean isExist() { returnreturnreturn return isExist; } publicpublicpublic public voidvoidvoid void setExist(booleanbooleanboolean boolean isExist) { thisthisthis this .isExist = isExist; } publicpublicpublic public List getList() { returnreturnreturn return list; } publicpublicpublic public voidvoidvoid void setList(List list) { thisthisthis this .list = list; } } Axis1.4 开发指南 第 48 页 共 75 页 客户端调用: Java 代码: packagepackagepackage package webservice.axis.wsddselfobj; importimportimport import java.net.MalformedURLException; importimportimport import java.rmi.RemoteException; importimportimport import java.util.ArrayList; importimportimport import java.util.HashMap; importimportimport import java.util.Iterator; importimportimport import java.util.List; importimportimport import java.util.Map; importimportimport import javax.xml.namespace.QName; importimportimport import javax.xml.rpc.ParameterMode; importimportimport import javax.xml.rpc.ServiceException; importimportimport import org.apache.axis.client.Call; importimportimport import org.apache.axis.client.Service; importimportimport import org.apache.axis.encoding.XMLType; importimportimport import org.apache.axis.encoding.ser.BeanDeserializerFactory; importimportimport import org.apache.axis.encoding.ser.BeanSerializerFactory; importimportimport import webservice.axis.wsddselfobj.clientmodel.Address; /** * 获得WebService的返回List/Map等负责对象的客户端 * *@author@author@author @author Along * *@version@version@version @version $Revision$ * *@since@since@since @since 2008-7-11 */ @SuppressWarnings("unchecked") publicpublicpublic public classclassclass class ClientAddress { publicpublicpublic public staticstaticstatic static voidvoidvoid void getServerList() { String url = "http://127.0.0.1:8080/myaxis/services/AddressManager"; Service service = newnewnew new Service(); Axis1.4 开发指南 第 49 页 共 75 页 trytrytry try { Call call = (Call) service.createCall(); QName qn = newnewnew new QName("urn:AddressManager","Address"); QName qn1 = newnewnew new QName("urn:AddressInnerClass", "myNSD:InnerClass"); call.registerTypeMapping(Address.classclassclass class , qn, BeanSerializerFactory.classclassclass class , BeanDeserializerFactory.classclassclass class ); call.registerTypeMapping(Address.InnerClass.classclassclass class , qn1, BeanSerializerFactory.classclassclass class , BeanDeserializerFactory.classclassclass class ); call.setTargetEndpointAddress(newnewnew new java.net.URL(url)); call.setOperationName(newnewnew new QName("AddressManager", "getAddressList")); call.setReturnClass(ArrayList.classclassclass class ); Object[] sss = nullnullnull null ; List
list = (ArrayList) call.invoke(sss); System.out.println("List size: " + list.size()); forforfor for (Iterator
iter = list.iterator(); iter.hasNext();) { Address address = iter.next(); System.out.println("id号:" + address.getIdentifier() + " address:" + address.getAddress() + " city:" + address.getCity() + " country:" + address.getCountry() + " postalCode:" + address.getPostalCode() + " province:" + address.getProvince() + " array: " + address.getArray()[0] + " list: " + address.getList() + " isExist: " + address.isExist() + " innerClass.name: " + address.getInnC().getInnerName()); } } catchcatchcatch catch (ServiceException e) { Axis1.4 开发指南 第 50 页 共 75 页 e.printStackTrace(); } catchcatchcatch catch (MalformedURLException e) { e.printStackTrace(); } catchcatchcatch catch (RemoteException e) { e.printStackTrace(); } } publicpublicpublic public staticstaticstatic static voidvoidvoid void setServerList() { String url = "http://127.0.0.1:8080/myaxis/services/AddressManager"; Service service = newnewnew new Service(); List
list = newnewnew new ArrayList
(); Address address = newnewnew new Address(); address.setIdentifier(1); address.setAddress("Haidian"); address.setCity("BeiJing"); address.setCountry("China"); address.setPostalCode("100081"); address.setProvince("Beijing"); address.setExist(falsefalsefalse false ); address.setArray(newnewnew new String[]{"1","2","3"}); list.add(address); address = newnewnew new Address(); address.setIdentifier(2); address.setAddress("Chaoyang"); address.setCity("BeiJing"); address.setCountry("China"); address.setPostalCode("100081"); address.setProvince("Beijing"); address.setExist(truetruetrue true ); address.setArray(newnewnew new String[]{"A","B","C"}); list.add(address); trytrytry try { Call call = (Call) service.createCall(); Axis1.4 开发指南 第 51 页 共 75 页 QName qn = newnewnew new QName("urn:AddressManager","Address"); QName qn1 = newnewnew new QName("urn:AddressInnerClass", "myNSD:InnerClass"); call.registerTypeMapping(Address.classclassclass class , qn, BeanSerializerFactory.classclassclass class , BeanDeserializerFactory.classclassclass class ); call.registerTypeMapping(Address.InnerClass.classclassclass class , qn1, BeanSerializerFactory.classclassclass class , BeanDeserializerFactory.classclassclass class ); call.setTargetEndpointAddress(newnewnew new java.net.URL(url)); call.setOperationName(newnewnew new QName("AddressManager", "setAddressList")); call.setReturnClass(ArrayList.classclassclass class ); call.addParameter("list", XMLType.XSD_ANYTYPE, ParameterMode.IN); list = (ArrayList) call.invoke(newnewnew new Object[]{list}); System.out.println("List size: " + list.size()); forforfor for (Iterator
iter = list.iterator(); iter.hasNext();) { address = iter.next(); System.out.println("id号:" + address.getIdentifier() + " address:" + address.getAddress() + " city:" + address.getCity() + " country:" + address.getCountry() + " postalCode:" + address.getPostalCode() + " province:" + address.getProvince() + " array: " + address.getArray()[0] + " list: " + address.getList() + " isExist: " + address.isExist() + " innerClass.name: " + address.getInnC().getInnerName()); } } catchcatchcatch catch (ServiceException e) { e.printStackTrace(); } catchcatchcatch catch (MalformedURLException e) { Axis1.4 开发指南 第 52 页 共 75 页 e.printStackTrace(); } catchcatchcatch catch (RemoteException e) { e.printStackTrace(); } } publicpublicpublic public staticstaticstatic static voidvoidvoid void getServerMap() { String url = "http://127.0.0.1:8080/myaxis/services/AddressManager"; Service service = newnewnew new Service(); trytrytry try { Call call = (Call) service.createCall(); QName qn = newnewnew new QName("urn:AddressManager","Address"); QName qn1 = newnewnew new QName("urn:AddressInnerClass", "myNSD:InnerClass"); call.registerTypeMapping(Address.classclassclass class , qn, BeanSerializerFactory.classclassclass class , BeanDeserializerFactory.classclassclass class ); call.registerTypeMapping(Address.InnerClass.classclassclass class , qn1, BeanSerializerFactory.classclassclass class , BeanDeserializerFactory.classclassclass class ); call.setTargetEndpointAddress(newnewnew new java.net.URL(url)); Object[] sss = nullnullnull null ; call.setOperationName(newnewnew new QName("AddressManager", "getAddressMap")); call.setReturnClass(HashMap.classclassclass class ); Map map = (Map) call.invoke(sss); System.out.println("Map size: " + map.size()); forforfor for (Iterator iter = map.keySet().iterator(); iter.hasNext();) { Integer key = iter.next(); Address address = map.get(key); System.out.println("id号:" + address.getIdentifier() + " address:" + address.getAddress() + " city:" + address.getCity() Axis1.4 开发指南 第 53 页 共 75 页 + " country:" + address.getCountry() + " postalCode:" + address.getPostalCode() + " province:" + address.getProvince() + " array: " + address.getArray()[0] + " list: " + address.getList() + " isExist: " + address.isExist() + " innerClass.name: " + address.getInnC().getInnerName()); } } catchcatchcatch catch (ServiceException e) { e.printStackTrace(); } catchcatchcatch catch (MalformedURLException e) { e.printStackTrace(); } catchcatchcatch catch (RemoteException e) { e.printStackTrace(); } } publicpublicpublic public staticstaticstatic static voidvoidvoid void setServerMap() { String url = "http://127.0.0.1:8080/myaxis/services/AddressManager"; Service service = newnewnew new Service(); Map map = newnewnew new HashMap(); Address address = newnewnew new Address(); address.setIdentifier(1); address.setAddress("Haidian"); address.setCity("BeiJing"); address.setCountry("China"); address.setPostalCode("100081"); address.setProvince("Beijing"); address.setExist(falsefalsefalse false ); address.setArray(newnewnew new String[]{"1","2","3"}); map.put(address.getIdentifier(), address); address = newnewnew new Address(); address.setIdentifier(2); Axis1.4 开发指南 第 54 页 共 75 页 address.setAddress("Chaoyang"); address.setCity("BeiJing"); address.setCountry("China"); address.setPostalCode("100081"); address.setProvince("Beijing"); address.setExist(truetruetrue true ); address.setArray(newnewnew new String[]{"A","B","C"}); map.put(address.getIdentifier(), address); trytrytry try { Call call = (Call) service.createCall(); QName qn = newnewnew new QName("urn:AddressManager","Address"); QName qn1 = newnewnew new QName("urn:AddressInnerClass", "myNSD:InnerClass"); call.registerTypeMapping(Address.classclassclass class , qn, BeanSerializerFactory.classclassclass class , BeanDeserializerFactory.classclassclass class ); call.registerTypeMapping(Address.InnerClass.classclassclass class , qn1, BeanSerializerFactory.classclassclass class , BeanDeserializerFactory.classclassclass class ); call.setTargetEndpointAddress(newnewnew new java.net.URL(url)); call.setOperationName(newnewnew new QName("AddressManager", "setAddressMap")); call.setReturnClass(HashMap.classclassclass class ); call.addParameter("list", XMLType.XSD_ANYTYPE, ParameterMode.IN); map = (Map) call.invoke(newnewnew new Object[]{map}); System.out.println("Map size: " + map.size()); forforfor for (Iterator iter = map.keySet().iterator(); iter.hasNext();) { Integer key = iter.next(); address = map.get(key); System.out.println("id号:" + address.getIdentifier() + " address:" + address.getAddress() + " city:" + address.getCity() + " country:" + address.getCountry() + " postalCode:" + address.getPostalCode() Axis1.4 开发指南 第 55 页 共 75 页 + " province:" + address.getProvince() + " array: " + address.getArray()[0] + " list: " + address.getList() + " isExist: " + address.isExist() + " innerClass.name: " + address.getInnC().getInnerName()); } } catchcatchcatch catch (ServiceException e) { e.printStackTrace(); } catchcatchcatch catch (MalformedURLException e) { e.printStackTrace(); } catchcatchcatch catch (RemoteException e) { e.printStackTrace(); } } publicpublicpublic public staticstaticstatic static voidvoidvoid void main(String[] args) { getServerList(); getServerMap(); setServerList(); setServerMap(); } } 这个地方需要啰嗦几句: 关于 Address 这个类由于他里面有一个内部类,但是这个内部类里并不是 JAVA的基本类型,所 以在你客户端调用的时候你需要注册一下,如: QName qn = newnewnew new QName("urn:AddressManager","Address"); QName qn1 = newnewnew new QName("urn:AddressInnerClass","myNSD:InnerClass"); call.registerTypeMapping(Address.classclassclass class , qn, BeanSerializerFactory.classclassclass class , BeanDeserializerFactory.classclassclass class ); call.registerTypeMapping(Address.InnerClass.classclassclass class , qn1, Axis1.4 开发指南 第 56 页 共 75 页 BeanSerializerFactory.classclassclass class , BeanDeserializerFactory.classclassclass class ); 大家在这里看见的写法和上面的写法有点区别,其实这是一个简易写法,所表达的意思是相同 的,都是表示这个类可以序列化和反序列化。 最后就是关于 WSDD 的部署代码如下: 这里可以看书 Address 里的内部类也需要做映射。 运行结果: 客户端: List size: 2 id号:1 address:Haidian city:BeiJing country:China postalCode:100081 province:Beijing array: 1 list: [1, 2, 3] isExist: false innerClass.name: My Inner name id号:2 address:Chaoyang city:BeiJing country:China postalCode:100081 province:Beijing array: A list: [1, 2, 3] isExist: true innerClass.name: My Inner name Map size: 2 id号:1 address:Haidian city:BeiJing country:China postalCode:100081 province:Beijing array: 1 list: [1, 2, 3] isExist: false innerClass.name: My Inner name Axis1.4 开发指南 第 57 页 共 75 页 id号:2 address:Chaoyang city:BeiJing country:China postalCode:100081 province:Beijing array: A list: [1, 2, 3] isExist: true innerClass.name: My Inner name List size: 2 id号:1 address:Haidian city:BeiJing country:China postalCode:100081 province:Beijing array: 1 list: [1, 2, 3] isExist: false innerClass.name: My Inner name id号:2 address:Chaoyang city:BeiJing country:China postalCode:100081 province:Beijing array: A list: [1, 2, 3] isExist: true innerClass.name: My Inner name Map size: 2 id号:1 address:Haidian city:BeiJing country:China postalCode:100081 province:Beijing array: 1 list: [1, 2, 3] isExist: false innerClass.name: My Inner name id号:2 address:Chaoyang city:BeiJing country:China postalCode:100081 province:Beijing array: A list: [1, 2, 3] isExist: true innerClass.name: My Inner name 3.5.33.5.33.5.3 3.5.3 RMI RMI RMI RMI 方 式远 程调 用 方 式远 程调 用 方 式远 程调 用 方 式远 程调 用 到目前为止所有例子都是先提供一个类然后在给出对应的实现,下面介绍一种类似 RMI 的 实现例子给大家参考,来看代码: 提供服务的接口: Java 代码: packagepackagepackage package webservice.axis.wsdd; /** * 本地实现一个Remote接口,其中包含远程WS的方法(同名、同返回类型、同参数类型), * 则通过Service可以获得一个对远程WS对象的引用。用该引用可以直接像调用本地方法一样调 用远程方法。 * 服务端不用做任何设置和调整。 * *@author@author@author @author Along * *@version@version@version @version $Revision$ * *@since@since@since @since 2008-7-14 */ Axis1.4 开发指南 第 58 页 共 75 页 publicpublicpublic public interfaceinterfaceinterface interface IHelloWorldWSDD extendsextendsextends extends java.rmi.Remote { publicpublicpublic public String hello(String name); publicpublicpublic public Float add(Float a, floatfloatfloat float b); } WebService 服务端: Java 代码: packagepackagepackage package webservice.axis.wsdd; publicpublicpublic public classclassclass class HelloWorldWSDD { privateprivateprivate private intintint int requestCount = 0; publicpublicpublic public String hello(String name) { requestCount++; System.out.println("requestCount=" + requestCount); System.out.println("Received: " + name); returnreturnreturn return "Hello " + name; } publicpublicpublic public Float add(Float a, floatfloatfloat float b) { requestCount++; String result = "a=" + a + ", b=" + b; System.out.println("requestCount=" + requestCount); System.out.println("Received: " + result); returnreturnreturn return a + b; } } 通过上面的代码可以看出服务端和之前我们写的代码是一样的,没有任何变化。客户端接口提 供方法和参数完全和服务端提供的一样,这样你可以根据接口的方法来操作服务端的方法(服 务端不需要实现这个接口,这个接口对服务端是透明的)。这样可以给你带来更方便的开发,当 你要提供 WebService 服务的时候你可以不用修改你的服务端代码直接以接口形式提供就可以 了。 客户端的实现: Axis1.4 开发指南 第 59 页 共 75 页 Java 代码: packagepackagepackage package webservice.axis.wsdd; importimportimport import java.rmi.RemoteException; importimportimport import javax.xml.namespace.QName; importimportimport import javax.xml.rpc.ServiceException; importimportimport import org.apache.axis.client.Call; importimportimport import org.apache.axis.client.Service; publicpublicpublic public classclassclass class ClientWSDD { publicpublicpublic public staticstaticstatic static voidvoidvoid void main(String[] args) { trytrytry try { String url = "http://127.0.0.1:8080/myaxis/services/HelloWorldWSDD"; Service serv = newnewnew new Service(); Call call = (Call) serv.createCall(); call.setTargetEndpointAddress(url); call.setOperationName(newnewnew new QName(url, "hello")); //String result = (String) call.invoke(new Object[]{"Quhailong"}); //System.out.println("result = " + result); IHelloWorldWSDD remoteRef = (IHelloWorldWSDD) serv.getPort(url, IHelloWorldWSDD.classclassclass class ); String result = remoteRef.hello("Quhailong"); System.out.println("result = " + result); result = remoteRef.hello("Quhailong"); System.out.println("result = " + result); call.setOperationName(newnewnew new QName(url, "add")); Float returnValue = (Float) call.invoke(newnewnew new Object[]{newnewnew new Float(3.2), newnewnew new Float(2.8)}); System.out.println("returnValue = " + returnValue); } catchcatchcatch catch (ServiceException e) { e.printStackTrace(); } catchcatchcatch catch (RemoteException e) { e.printStackTrace(); } Axis1.4 开发指南 第 60 页 共 75 页 } } WSDD 代码: 在这里顺便提一下如果要是 HelloWorldWSDD 只想暴露 2个方法而不是全部,可以使用 这样来达到效果(其中方 法1&2 是用英文的逗号隔开的)。 3.63.63.6 3.6 抛出异常 上一篇介绍了如果在Server 和Client端传递一个自己的对象。有些人也许会问传递异常行 不行?答案是可以。只不过传递异常的配置要稍微复杂一些。下面我用代码来说明下: 服务端的异常类: Java代码: packagepackagepackage package webservice.axis.wsddexception; importimportimport import java.rmi.RemoteException; /** * 服务器端的异常 * *@author@author@author @author Along * *@version@version@version @version $Revision$ * *@since@since@since @since 2008-7-11 */ publicpublicpublic public classclassclass class ServerException extendsextendsextends extends RemoteException { Axis1.4 开发指南 第 61 页 共 75 页 privateprivateprivate private staticstaticstatic static finalfinalfinal final longlonglong long serialVersionUID = -8703656417727568771L; privateprivateprivate private String errMSG = ""; publicpublicpublic public ServerException() { System.out.println("Server Exception!"); } publicpublicpublic public voidvoidvoid void printErrorDescription() { System.out.println(errMSG); } publicpublicpublic public String getErrMSG() { returnreturnreturn return errMSG; } publicpublicpublic public voidvoidvoid void setErrMSG(String errMSG) { thisthisthis this .errMSG = errMSG; } } 提供的WebService代码: Java代码 packagepackagepackage package webservice.axis.wsddexception; /** * 产生异常的方法测试 * *@author@author@author @author Along * *@version@version@version @version $Revision$ * *@since@since@since @since 2008-7-11 */ publicpublicpublic public classclassclass class ExceptionCreater { publicpublicpublic public voidvoidvoid void getException() throwsthrowsthrows throws ServerException { ServerException se = newnewnew new ServerException(); se.setErrMSG("Server Side Self Exception!"); throwthrowthrow throw se; Axis1.4 开发指南 第 62 页 共 75 页 } } 客户端的异常: Java代码: packagepackagepackage package webservice.axis.wsddexception; importimportimport import java.rmi.RemoteException; /** * 客户器端的异常 * *@author@author@author @author Along * *@version@version@version @version $Revision$ * *@since@since@since @since 2008-7-11 */ publicpublicpublic public classclassclass class ClientException extendsextendsextends extends RemoteException { privateprivateprivate private staticstaticstatic static finalfinalfinal final longlonglong long serialVersionUID = -8703656417727568771L; privateprivateprivate private String errMSG = "Client Side Self Exception!"; publicpublicpublic public ClientException() { System.out.println("Client Exception!"); } publicpublicpublic public voidvoidvoid void printErrorDescription() { System.out.println(errMSG); } publicpublicpublic public String getErrMSG() { returnreturnreturn return errMSG; } publicpublicpublic public voidvoidvoid void setErrMSG(String errMSG) { thisthisthis this .errMSG = errMSG; } } Axis1.4 开发指南 第 63 页 共 75 页 客户端代码 Java 代码: packagepackagepackage package webservice.axis.wsddexception; importimportimport import java.rmi.RemoteException; importimportimport import javax.xml.namespace.QName; importimportimport import javax.xml.rpc.ServiceException; importimportimport import org.apache.axis.client.Call; importimportimport import org.apache.axis.client.Service; /** * 获得WebService的返回异常的客户端 * *@author@author@author @author Along * *@version@version@version @version $Revision$ * *@since@since@since @since 2008-7-11 */ publicpublicpublic public classclassclass class ClientExceptionReceiver { publicpublicpublic public staticstaticstatic static voidvoidvoid void main(String[] args) { trytrytry try { String url = "http://127.0.0.1:8080/myaxis/services/ExceptionCreater"; Service serv = newnewnew new Service(); Call call = (Call) serv.createCall(); QName qn = newnewnew new QName("urn:CustomerFault","ServerException"); call.registerTypeMapping(ClientException.classclassclass class , qn, newnewnew new org.apache.axis.encoding.ser.BeanSerializerFactory( ClientException.classclassclass class , qn), newnewnew new org.apache.axis.encoding.ser.BeanDeserializerFactory( ClientException.classclassclass class , qn)); call.setTargetEndpointAddress(url); Axis1.4 开发指南 第 64 页 共 75 页 Object[] param = nullnullnull null ; call.setOperationName(newnewnew new QName(url, "getException")); System.out.println("Will Catch Exception"); String result = (String) call.invoke(param); System.out.println("result = " + result); } catchcatchcatch catch (ServiceException e) { e.printStackTrace(); } catchcatchcatch catch (ClientException e) { System.out.println("Catch Exception"); e.printErrorDescription(); e.printStackTrace(); } catchcatchcatch catch (RemoteException e) { e.printStackTrace(); } } } WSDD 的文件描述: 首先不同的是多了个命名空间也就是namespace节点,等会测试代码中会看到用途。除了 namespace之外还有operation这个节点和里面的fault子节点。先来介绍operation这个节点的 属性。  name:操作名称或者方法名称,这个值会和你server发布的相关方法名匹配,所以要和方 法名相同。  qname:针对这个operation的限定名。  xmlns:针对这个qname 的命名空间也就是namespace。  Fault:节点代表要这个方法要抛出的异常。  namenamename name :随便起的名字。  type="tns:ServerException"type="tns:ServerException"type="tns:ServerException" type="tns:ServerException" ::这里的一定要写出你要抛出的异常的类型。 运行结果: 客户端: Will Catch Exception Client Exception! Catch Exception Server Side Self Exception! webservice.axis.wsddexception.ClientException at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) at java.lang.reflect.Constructor.newInstance(Unknown Source) at java.lang.Class.newInstance0(Unknown Source) Axis1.4 开发指南 第 66 页 共 75 页 at java.lang.Class.newInstance(Unknown Source) at org.apache.axis.encoding.ser.BeanDeserializer.(BeanDeserializer.j ava:104) at org.apache.axis.encoding.ser.BeanDeserializerFactory.getGeneralPurpose( BeanDeserializerFactory.java:89) at org.apache.axis.encoding.ser.BaseDeserializerFactory.getDeserializerAs( BaseDeserializerFactory.java:89) at org.apache.axis.encoding.DeserializationContext.getDeserializer(Deseria lizationContext.java:464) at org.apache.axis.encoding.DeserializationContext.getDeserializerForType( DeserializationContext.java:547) at org.apache.axis.message.SOAPFaultDetailsBuilder.onStartChild(SOAPFaultD etailsBuilder.java:157) at org.apache.axis.encoding.DeserializationContext.startElement(Deserializ ationContext.java:1035) at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startEleme nt(Unknown Source) at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanSt artElement(Unknown Source) at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$ FragmentContentDriver.next(Unknown Source) at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(Unk nown Source) at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(U nknown Source) at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl. scanDocument(Unknown Source) at Axis1.4 开发指南 第 67 页 共 75 页 com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unk nown Source) at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unk nown Source) at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown Source) at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(Unkn own Source) at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.par se(Unknown Source) at javax.xml.parsers.SAXParser.parse(Unknown Source) at org.apache.axis.encoding.DeserializationContext.parse(DeserializationCo ntext.java:227) at org.apache.axis.SOAPPart.getAsSOAPEnvelope(SOAPPart.java:696) at org.apache.axis.Message.getSOAPEnvelope(Message.java:435) at org.apache.axis.handlers.soap.MustUnderstandChecker.invoke(MustUndersta ndChecker.java:62) at org.apache.axis.client.AxisClient.invoke(AxisClient.java:206) at org.apache.axis.client.Call.invokeEngine(Call.java:2784) at org.apache.axis.client.Call.invoke(Call.java:2767) at org.apache.axis.client.Call.invoke(Call.java:2443) at org.apache.axis.client.Call.invoke(Call.java:2366) at org.apache.axis.client.Call.invoke(Call.java:1812) at webservice.axis.wsddexception.ClientExceptionReceiver.main(ClientExcept ionReceiver.java:54) 服务端: Server Exception! 3.73.73.7 3.7 传递文件 服务端 Axis1.4 开发指南 第 68 页 共 75 页 Java 代码: packagepackagepackage package webservice.axis.wsddfiletranspot; importimportimport import java.io.File; importimportimport import java.io.FileOutputStream; importimportimport import java.io.IOException; importimportimport import java.io.InputStream; importimportimport import javax.activation.DataHandler; /** * 接收文件的服务端 * *@author@author@author @author Along * *@version@version@version @version $Revision$ * *@since@since@since @since 2008-7-11 */ publicpublicpublic public classclassclass class FileReceiverServer { publicpublicpublic public String receive(DataHandler handler, String fileName) { File file = newnewnew new File(fileName); ififif if (handler == nullnullnull null || fileName == nullnullnull null || fileName.equals("")) { returnreturnreturn return "failure"; } InputStream input = nullnullnull null ; FileOutputStream fos = nullnullnull null ; trytrytry try { input = handler.getInputStream(); fos = newnewnew new FileOutputStream(file); bytebytebyte byte [] buffer = newnewnew new bytebytebyte byte [1024]; whilewhilewhile while (input.read(buffer) != -1) { fos.write(buffer); } } catchcatchcatch catch (IOException e) { Axis1.4 开发指南 第 69 页 共 75 页 e.printStackTrace(); } finallyfinallyfinally finally { ififif if (input != nullnullnull null ){ trytrytry try { input.close(); } catchcatchcatch catch (IOException e) { e.printStackTrace(); } } ififif if (fos != nullnullnull null ){ trytrytry try { fos.close(); } catchcatchcatch catch (IOException e) { e.printStackTrace(); } } } returnreturnreturn return "Success file saved on server. At: " + file.getAbsolutePath(); } } 在这个服务端代码里我们主要介绍一个类就是 DataHandler 其实这个类是一个专门的传送器,通 过他可以把文件进行序列化。这个方法从 DataHandler 得到一个输入流,从这个流里读出数据 然后写到一个新文件里。这些都是一些基本的 Java I/O 操作。 Axis1.4 开发指南 第 70 页 共 75 页 在这个地方有必要说一下就是大家在以前看见的地方都是用 beanMapping 来配置的,其实用 typeMapping 也是一样的,这里就不多说了。我主要说一下就是关于 org.apache.axis.encoding.ser.JAFDataHandlerSerializerFactory 和 org.apache.axis.encoding.ser.JAFDataHandlerDeserializerFactory 其实这两个类也是很简单的,因为我们要序列化不同的对象所以我们要用到不同的工厂类,同 样当你要序列化文件的时候也要用到文件的工厂类。 最后来让我们看看客户端的代码实现: Java 代码: importimportimport import java.rmi.RemoteException; importimportimport import javax.activation.DataHandler; importimportimport import javax.activation.FileDataSource; importimportimport import javax.xml.namespace.QName; importimportimport import javax.xml.rpc.ParameterMode; importimportimport import javax.xml.rpc.ServiceException; importimportimport import javax.xml.rpc.encoding.XMLType; importimportimport import org.apache.axis.client.Call; importimportimport import org.apache.axis.client.Service; Axis1.4 开发指南 第 71 页 共 75 页 importimportimport import org.apache.axis.encoding.ser.JAFDataHandlerDeserializerFactory; importimportimport import org.apache.axis.encoding.ser.JAFDataHandlerSerializerFactory; /** * 传输文件的客户端 * *@author@author@author @author Along * *@version@version@version @version $Revision$ * *@since@since@since @since 2008-7-11 */ publicpublicpublic public classclassclass class FileSenderClient { publicpublicpublic public staticstaticstatic static voidvoidvoid void main(String[] args) { trytrytry try { String fileName = "readme.txt"; DataHandler dh = newnewnew new DataHandler(newnewnew new FileDataSource(FileSenderClient.classclassclass class .getResource(fileName).getPath())); String url = "http://127.0.0.1:8080/myaxis/services/FileReceiverServer"; Service serv = newnewnew new Service(); Call call = (Call) serv.createCall(); call.setTargetEndpointAddress(url); call.setOperationName(newnewnew new QName(url, "receive")); QName qn = newnewnew new QName("DataHandler","myNs:DataHandler"); call.registerTypeMapping(DataHandler.classclassclass class , qn, JAFDataHandlerSerializerFactory.classclassclass class , JAFDataHandlerDeserializerFactory.classclassclass class ); call.addParameter("s1", qn, ParameterMode.IN); call.addParameter("s2", XMLType.XSD_STRING, ParameterMode.IN); call.setReturnClass(String.classclassclass class ); String returnStr = (String)call.invoke(newnewnew new Object[]{dh, "server.txt"}); System.out.println("Server response: " + returnStr); } catchcatchcatch catch (ServiceException e) { e.printStackTrace(); } catchcatchcatch catch (RemoteException e) { Axis1.4 开发指南 第 72 页 共 75 页 e.printStackTrace(); } } } 然后进行测试。 输出结果: 客户端: Server response: Success file saved on server. At: D:\Tomcat\bin\server.txt 上面的列子都是经过测试而且完全跑通的,我们希望大家能够自己动手完成这些列子提高 自己的水平。在下一章我们将会简单介绍一下关于 AXIS 的调试工具和相关的命令使用。 4.AXIS 4.AXIS 4.AXIS 4.AXIS 的常用的命令和调试工具 的使用 的常用的命令和调试工具 的使用 的常用的命令和调试工具 的使用 的常用的命令和调试工具 的使用 4.14.14.1 4.1 AXIS AXIS AXIS AXIS 的常用命令: 部署你的WSDD 的命令是到AXIS 的web-inf 下然后运行java org.apache.axis.client.AdminClient 你的部署文件。例如: java org.apache.axis.client.AdminClient e:\deploy.wsdd 上面的部署只是简单的部署,其实关于 AdminClient 有很多参数命令,感兴趣的朋友可以自己 看看只要在 AdminClient -help 就可以看到相关的参数命令。在这里我们主要讲解 2个重要的 和比较常用的,-l和-p一般有的时候我们不是使用 8080 这个端口,但是当你部署的时候你没有 指定端口这样 AXIS 会默认使用 8080 所以就会导致部署失败,遇见这种情况就要使用参数-p来 解决。 例如:你的 TOMCAT 使用的是 8089 端口,当你部署的时候要如下代码: java org.apache.axis.client.AdminClient e:\deploy.wsdd -p8089 注意:-p后面直接加端口。 还有一种就是关于-l 的使用,由于 AXIS 默认部署的时候使用的虚拟路径是 axis,但是有 的人不喜欢这个虚拟路径往往在 TOMCAT 里面就修改 server.xml 文件,创建自己的服务这个时 候当你部署的时候你就需要使用-l 命令了,例如你的虚拟路径是 myaxis 那么你在部署的时候 Axis1.4 开发指南 第 73 页 共 75 页 就要如下代码: java org.apache.axis.client.AdminClient e:\deploy.wsdd -lhttp://127.0.0.1:8080/myaxis/services/AdminService 4.24.24.2 4.2 调试工具的使用 关于调试工具的使用在这里我简单的说明一下,代码如下: 运行java org.apache.axis.utils.Tcpmon就会出现调试工具如图: Axis1.4 开发指南 第 74 页 共 75 页 这样你就可以填写本地的地址和端口,还有你要监听的端口然后点Add这样你就可以看到一些 传递的详细信息了,如图: 555 5 .后 话 .后 话 .后 话 .后 话 以上就是我们对 AXIS1.4 的全部理解。写这篇文档的目的是分享我们的知识,希望能给大 家提供方便。以上代码是全部经过我们测试成功的,如果有那些不对的地方希望朋友们能够指 出,也可以直接加 QQ群:3961326 来一起探讨关于 WebService 方面的问题。 Axis1.4 开发指南 第 75 页 共 75 页 发现什么错误或者愿意一起丰富书中内容的朋友,可以加作者的 QQ来一起为中国开发力 量做贡献。
还剩74页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 20 金币 [ 分享pdf获得金币 ] 7 人已下载

下载pdf

pdf贡献者

shiqiang

贡献于2010-10-23

下载需要 20 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf