axis1.4 使用笔记

axis1.4 使用笔记(1)

实验室想把原来做的一些东西打包成web服务的形式供别人调用,因此趁此机会学习了下axis1.4。现在把学习过程中碰到的一些问题记录下来。

1.axis简介:

          Axis(Apache eXtensible Interaction System)是一款开源的WebService 运行引擎,它是SOAP 协议的一个实现,其本身来源于Apache 的另一个项目Apache SOAP。Axis 分为1.x系列和2 系列,两个系列体系结构和使用上有较大的区别,相对而言,Axis1.x 更加稳定,文档也比较齐全,因此本文内容以Axis 1.x 系列最新版本1.4 为基础。

2.axis的安装配置:

      可以从官方网页http://ws.apache.org/axis/index.html下载到1.x系列的最终版1.4,建议大家把axis-bin-1_4.zip  和axis-src-1_4.zip 都下下来。

2.1安装到本地:

     安装到本地主要是为了应用axis自带的一些小工具。很简单把axis-bin-1_4.zip解压到某个目录即可,我电脑里是D:\JavaTools\axis-1_4,这个目录就是所谓的axis安装目录.

为了这些工具的方便使用,需要设置些环境变量:

AXIS_HOME:D:\JavaTools\axis-1_4

AXIS_LIB:%AXIS_HOME%\lib

AXISCLASSPATH:%AXIS_LIB%\axis.jar;%AXIS_LIB%\commons-discovery-0.2.jar;%AXIS_LIB%\commons-logging-1.0.4.jar;%AXIS_LIB%\jaxrpc.jar;%AXIS_LIB%\saaj.jar;%AXIS_LIB%\log4j-1.2.8.jar;%AXIS_LIB%\wsdl4j-1.5.1.jar;

前两个我用到了,后面那个一直没用到  

2.2安装到Tomcat中:

axis要运行必须有web容器,我使用的是Tomcat。很简单,

1)在axis安装目录中找到webapps文件,打开,然后把里面的axis文件夹及其内容复制到Tomcat的webapps目录下,在我电脑里即有这么个目录D:\JavaTools\Tomcat 6.0\webapps\axis

2)检验是否安装成功:首先启动Tomcat,然后在浏览器里输入http://127.0.0.1:8080/axis/,如果看到下面这个图则说明在Tomcat下安装成功了


注意,axis安装包中少几个jar包,需要单独下载:

必需组件:
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.jarxalan.jar都放到你的axis应用的WEB-INF/lib下然后在校验Axis,看到页面提示全部安装成功。

 

2.3安装到Eclipse

如果你在项目中要用到axis,则你的项目应该包含axis的一些包。这里主要是在客户端编程中要用到。

         首先创建一个WEB项目,名称随便,    再把axis安装目录中的lib目录下的所有jar包都导入该项目,这样eclipse中的axis就安装好了,开发webservice就只要在这个项目里开发就行了,如果你在其他项目里开发的话,只要把jar都导过去就行了,简单吧!

安装就讲这么多。。基本上就没什么问题了。

 

3.开发web service

axis中发布服务主要有两种方式

  • 即时发布JWS
  • 定制发布WSDD

即时发布虽然很方便,但限制过大,一般不会用。最大限制就是不支持带包的类,这是初学者容易犯的一个错。具体就不讲了,下面通过讲解如何把我们项目的一个算法发布成web service来详细讲解定制发布。

 

axis1.4 使用笔记(2)

3. 定制发布WSDD

        web服务的开发主要分两部分,一部分是服务的提供者,主要要做两件事情,一是完成服务的业务逻辑,也就是完成这个服务真正要做的事,二是完成服务的配制,也就是如何描述你的服务,以使别人能够调用,这一步是重点。另一部分就是服务的使用者,也就是客户端如何调用发布好的服务。因此在学习axis的过程中,一定要分清哪些事是服务器端要做的事,哪些事是客户端要做的事,而网上大部分资料为了讲述方便都放一起讲,让初学者迷惑不已。下面我就分别从这两部分来详细讲述。

       首先还是讲述下任务吧,我们的项目SN中有很多好而且实用的算法,这些算法还总要调用服务器中的数据库读取数据,这个项目是BS模式的,现在还需要开发一个CS模式的系统,很多要做的事BS模式中已经做完了,因此,很自然的想法就是直接复用这些算法。一开始是导入jar包的形式,后来发现这样很累,不但jar包很大,更重要的是BS一改,CS就得重导jar包。耦合性太紧。因此就有了把这些算法以web service的形式发布出去的 想法,让CS程序以web 服务的形式调用这些算法!这些天做的事情就是这些,下面以一个具体的算法如何发布出去为例讲述axis中服务的定制发布。

具体任务:SemanticQueryOperate这个类中有一个方法getAdvancedSearchList()用于高级搜索,通过语义匹配从数据库中找到相应的服务。

类加上包名为:cn.edu.tju.ikse.sn.advancedSearch.SemanticQueryOperate

方法:public List<Serviceinfo> getAdvancedSearchList(AdvanceSearch advanceSearch),其中AdvanceSearch 是一个javabean,用于封装用户的查询条件,Serviceinfo也是一个javabean,用于封装服务信息。

任务就是把这个方法接口发布出去。

 

3.1 Web Service服务端开发

对于服务端,第一件事已经做好了,即已经把业务相关的代码写好了。。下面要做的事就是把这个服务发布出去,也就是如何写描述文件wsdd。

具体语法就不讲了,直接看写好的:snAdvancedSearch.wsdd

Java代码 复制代码
  1. <deployment xmlns="http://xml.apache.org/axis/wsdd/"  
  2.     xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">   
  3.     <service name="SN_AdvanceSearch" provider="java:RPC">   
  4.         <parameter name="className" value="cn.edu.tju.ikse.sn.advancedSearch.SemanticQueryOperate"/>   
  5.         <parameter name="allowedMethods" value="getAdvancedSearchList"/>   
  6.         <beanMapping qname="myNSD:AdvanceSearch"     xmlns:myNSD="urn:BeanService"  
  7.             languageSpecificType="java:cn.edu.tju.ikse.sn.advancedSearch.AdvanceSearch"/>   
  8.         <beanMapping qname="myNSD:Serviceinfo"  xmlns:myNSD="urn:BeanService"  
  9.             languageSpecificType="java:cn.edu.tju.ikse.sn.hibernate.Serviceinfo"/>   
  10.     </service>   
  11. </deployment>  
<deployment xmlns="http://xml.apache.org/axis/wsdd/"
	xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
	<service name="SN_AdvanceSearch" provider="java:RPC">
		<parameter name="className" value="cn.edu.tju.ikse.sn.advancedSearch.SemanticQueryOperate"/>
		<parameter name="allowedMethods" value="getAdvancedSearchList"/>
		<beanMapping qname="myNSD:AdvanceSearch" 	xmlns:myNSD="urn:BeanService"
			languageSpecificType="java:cn.edu.tju.ikse.sn.advancedSearch.AdvanceSearch"/>
		<beanMapping qname="myNSD:Serviceinfo"  xmlns:myNSD="urn:BeanService"
			languageSpecificType="java:cn.edu.tju.ikse.sn.hibernate.Serviceinfo"/>
	</service>
</deployment>

 

第三行,就是给这个服务取一个名字,这样别人就能按照名字来获取服务了。这里我们取名为SN_AdvanceSearch

第四行,指定这个服务代表的具体类,要包括包名

第五行,指定这个服务允许别人访问的方法名,这里只让访问getAdvancedSearchList,如果改成*号,则这个类所有    public的方法都能被客户端调用。

第六行,是重点,完成类型的映射,因为用到了用户自己定义的两个javaBean,因此需要映射。格式如第六行和第七行所示,qname="myNSD:AdvanceSearch" ,注意红色部分应该和你的javabean名一致,languageSpecificType也得注意下格式,java:表示这是一个java语言写的类,后面再加上具体的类。其它自定义类完全可以参考这个写法。

写完后我把这文档放在了D:\JavaTools\Tomcat 6.0\webapps\axis\WEB-INF目录下,下一步是如何把这个wsdd文档加到axis自己的配制文档server-config.wsdd里。

编写完配置发布文件之后,cmd打开windows的控制台,进入:%TOMCAT_HOME%\webapps\axis\WEB-INF 目录下键入如下命令:
java -Djava.ext.dirs=lib org.apache.axis.client.AdminClient snAdvancedSearch.wsdd

之后控制台返回Processing file deploy.wsdd 和Done processing 这两段话即说明发布成功。(注意tomcat得开着)。

当然了为了操作方便也可以写个批处理文件wsdd.bat:

 

Java代码 复制代码
  1. set Axis_Lib=D:\JavaTools\axis-1_4\lib       
  2. set Java_Cmd=java -Djava.ext.dirs=%Axis_Lib%       
  3. set Axis_Servlet=http://localhost:8080/axis/servlet/AxisServlet       
  4. %Java_Cmd% org.apache.axis.client.AdminClient -l%Axis_Servlet% snAdvancedSearch.wsdd    
  5. pause  
set Axis_Lib=D:\JavaTools\axis-1_4\lib    
set Java_Cmd=java -Djava.ext.dirs=%Axis_Lib%    
set Axis_Servlet=http://localhost:8080/axis/servlet/AxisServlet    
%Java_Cmd% org.apache.axis.client.AdminClient -l%Axis_Servlet% snAdvancedSearch.wsdd 
pause

 

最终效果都是一样的,此时在server-config.wsdd会有如下代码段:

Java代码 复制代码
  1. <service name="SN_AdvanceSearch" provider="java:RPC">   
  2.  <parameter name="allowedMethods" value="getAdvancedSearchList"/>   
  3.  <parameter name="className" value="cn.edu.tju.ikse.sn.advancedSearch.SemanticQueryOperate"/>   
  4.  <beanMapping languageSpecificType="java:cn.edu.tju.ikse.sn.advancedSearch.AdvanceSearch" qname="ns2:AdvanceSearch" xmlns:ns2="urn:BeanService"/>   
  5.  <beanMapping languageSpecificType="java:cn.edu.tju.ikse.sn.hibernate.Serviceinfo" qname="ns3:Serviceinfo" xmlns:ns3="urn:BeanService"/>   
  6. </service>  
 <service name="SN_AdvanceSearch" provider="java:RPC">
  <parameter name="allowedMethods" value="getAdvancedSearchList"/>
  <parameter name="className" value="cn.edu.tju.ikse.sn.advancedSearch.SemanticQueryOperate"/>
  <beanMapping languageSpecificType="java:cn.edu.tju.ikse.sn.advancedSearch.AdvanceSearch" qname="ns2:AdvanceSearch" xmlns:ns2="urn:BeanService"/>
  <beanMapping languageSpecificType="java:cn.edu.tju.ikse.sn.hibernate.Serviceinfo" qname="ns3:Serviceinfo" xmlns:ns3="urn:BeanService"/>
 </service>

 

和原来的wsdd文件差不多。对着看就明白了。。如果熟悉了可以直接在server-config.wsdd中加上上面这段代码就行了。此时访问http://localhost:8080/axis/servlet/AxisServlet就能看到你发布的服务了,可以查看对应的wsdl文档。

服务端任务基本就完成了。。最后别忘记把服务端对应的class文件拷到D:\JavaTools\Tomcat 6.0\webapps\axis\WEB-INF\classes目录下。由于我们这是一个web工程也是发布在Tomcat中,我是直接把发布的工程中的WEB-INF下的classes文件夹全部拷到axis下对应目录。(似乎还要把lib下的jar包也拷到axis对应的lib目录下)

 

3.2 客户端的开发

客户端就是写程序怎么调用这个web服务了。留到下一节讲吧。。写得太多了。

 

axis1.4 使用笔记(3)

3.2客户端程序的开发

3.2.1 java2WSDL 

 

这个工具应该是服务器端的人应该用的,放在这里主要是为了讲述方便。调用这个工具可以根据java类生成对应的wsdl文件发布出去。下面是一个批处理文件,大家可以保存下来,稍微改改就能用了。

Java代码 复制代码
  1. set Axis_Lib=D:\JavaTools\axis-1_4\lib       
  2. set Java_Cmd=java -Djava.ext.dirs=%Axis_Lib%   
  3. %Java_Cmd% org.apache.axis.wsdl.Java2WSDL     
  4.    -osn_advanceSearch.wsdl    
  5.    -lhttp://localhost:8080/axis/services/SN_AdvanceSearch    
  6.    -n"urn:BeanService"    
  7.    -p"cn.edu.tju.ikse.sn.advancedSearch" "urn:BeanService"    cn.edu.tju.ikse.sn.advancedSearch.SemanticQueryOperate   
  8. pause  
set Axis_Lib=D:\JavaTools\axis-1_4\lib    
set Java_Cmd=java -Djava.ext.dirs=%Axis_Lib%
%Java_Cmd% org.apache.axis.wsdl.Java2WSDL  
   -osn_advanceSearch.wsdl 
   -lhttp://localhost:8080/axis/services/SN_AdvanceSearch 
   -n"urn:BeanService" 
   -p"cn.edu.tju.ikse.sn.advancedSearch" "urn:BeanService"    cn.edu.tju.ikse.sn.advancedSearch.SemanticQueryOperate
pause

 -O:指定生成的wsdl文件名

-l:指定生成服务的访问地址

-n:指定名字空间

-p:指定名字空间与包的对应关系

最后指定具体的java类即你要发布的类。

这个工具最适用的环境:服务端根据业务需要写完暴露的接口后就可以用这个工具生成wsdl文件了,而不必要自己动手写wsdl文件,理论上就可以根据这个wsdl文档发布这个服务了。客户端一般是不会调用这个方法的。。因为客户端一般拿不到类文件~~放在这里讲是告诉大家有这么一个好用的工具。

 

3.2.2 WSDL2java

 

      这个工具是根据wsdl文件生成对应的调用类。这个在客户端是很有用的。当你只能从服务端拿到wsdl文档而不能拿到任何的代码或类文件时就得靠它了!这个工具会根据wsdl文档的定义生成一些对应的类,如复杂类型定义就会生成对应的javaBean..

编辑一个WSDL2Java.bat,Axis_Lib为axis.jar路径。内容如下:

Java代码 复制代码
  1. set Axis_Lib=D:\JavaTools\axis-1_4\lib       
  2. set Java_Cmd=java -Djava.ext.dirs=%Axis_Lib%       
  3. set Output_Path=D:\JavaTools\eclipse3.2\workplace\axisTest\src      
  4. set Package=cn.edu.tju.ikse.sn.advancedSearch     
  5. %Java_Cmd% org.apache.axis.wsdl.WSDL2Java -o%Output_Path% -p%Package% http://localhost:8080/axis/services/SN_AdvanceSearch?wsdl   
  6. pause  
set Axis_Lib=D:\JavaTools\axis-1_4\lib    
set Java_Cmd=java -Djava.ext.dirs=%Axis_Lib%    
set Output_Path=D:\JavaTools\eclipse3.2\workplace\axisTest\src   
set Package=cn.edu.tju.ikse.sn.advancedSearch  
%Java_Cmd% org.apache.axis.wsdl.WSDL2Java -o%Output_Path% -p%Package% http://localhost:8080/axis/services/SN_AdvanceSearch?wsdl
pause

 

应该不用解释吧。。很容易看懂,主要是调用WSDL2Java 根据服务端发布的服务生成对应的接口。

      倒数第二行是应用wsdl2java这个工具,最后是指定wsdl文件的位置,这个文件可以是本地的wsdl文件,也可以是网络上的wsdl文件。

      再解释下第三行,第三行是我客户端项目的源文件路径,这样通过工具生成的代码直接加到项目里了,省些复制粘贴的麻烦。刷新下项目,在包cn.edu.tju.ikse.sn.advancedSearch  下就能看到六个java文件:

AdvanceSearch.java//自定义类型,wsdl中的复杂类型定义都会生成对应的javaBean

Serviceinfo.java//这也是一个自定义类型。。一开始没生成这们。。后面的注意事项里会讲到原因。

SemanticQueryOperate.java,//这是一个接口,描述服务器端能干什么。对应于wsdl中的wsdl:portType

SemanticQueryOperateService.java,//这是一个接口.相当于wsdl中的wsdl:service结点

SemanticQueryOperateServiceLocator.java,实现了SemanticQueryOperateService接口.
这个类的作用是直接与服务器端通信,建立与服务器端的连接,实例化stub.然后客户端就可以通过stub与服务器通信了.

SN_AdvanceSearchSoapBindingStub.java.这个类实现了SemanticQueryOperate接口,作为服务器在客户端的存根,也就是一个stub.在客户端,对服务器的所有调用,本质上都是对stub的调用

 

3.2.3 客户端编码

 

客户端编码主要有两种方式:

  • 第一种方法是利用wsdl2java生成的stub类来进行调用,这种方式的好处是调用简单,不需要服务端的支持
  • 第二种方法是不通过stub类来进行调用,这种方式完全由用户控制调用的所有参数。

实际使用中应该多用第一种方式,代码写起来简单。下面分别进行讲述。

先讲第二种方式吧,看代码:

Java代码 复制代码
  1. public static void testadvancesearch() {   
  2.         //设置服务连接路径   
  3.         String url = "http://127.0.0.1:8989/axis/services/SN_AdvanceSearch";   
  4.         //下面是构建服务的输入参数   
  5.         AdvanceSearch search = new AdvanceSearch();   
  6.         search.setDomain("Biology");   
  7.         search.setServiceName("getENTRYbyScientificName");//getENTRYbyScientificName   
  8.   
  9.         try {   
  10.             Service service = new Service();//构建一个服务   
  11.             Call call = (Call) service.createCall();   
  12.             //注册javaBean 注意和server-config.wsdd保持一致   
  13.             QName qn = new QName("urn:BeanService""Serviceinfo");   
  14.             call.registerTypeMapping(Serviceinfo.class, qn,   
  15.                     new org.apache.axis.encoding.ser.BeanSerializerFactory(   
  16.                             Serviceinfo.class, qn),   
  17.                     new org.apache.axis.encoding.ser.BeanDeserializerFactory(   
  18.                             Serviceinfo.class, qn));   
  19.             //创建调用*/               
  20.             call.setTargetEndpointAddress(new java.net.URL(url));   
  21.             //调用服务器的方法   
  22.             call.setOperationName(new QName("SemanticQueryOperate",   
  23.                     "getAdvancedSearchArrayList"));   
  24.             //设定返回类型   
  25.             //call.setReturnClass(ArrayList.class); //call.invoke(new Object[]{"haha"});   
  26.             //设定传入参数   
  27.             //call.addParameter("userpara", XMLType.XSD_ANYTYPE, ParameterMode.IN);            
  28.             //System.out.println(new Object[]{userPar});   
  29.             //接受结果   
  30.             Object[] result = (Object[]) call.invoke(new Object[] { search });   
  31.             if (result != null && result.length > 0) {   
  32.                 for (int i = 0; i < result.length; i++) {   
  33.                     Serviceinfo serviceinfo = (Serviceinfo) result[i];   
  34.                     System.out.println(serviceinfo.getCatagoryName()   
  35.                             + serviceinfo.getAffiliation());   
  36.                 }   
  37.             }   
  38.   
  39.         } catch (ServiceException e) {   
  40.             e.printStackTrace();   
  41.         } catch (MalformedURLException e) {   
  42.             e.printStackTrace();   
  43.         } catch (RemoteException e) {   
  44.             e.printStackTrace();   
  45.         }   
  46.     }  
public static void testadvancesearch() {
		//设置服务连接路径
		String url = "http://127.0.0.1:8989/axis/services/SN_AdvanceSearch";
		//下面是构建服务的输入参数
		AdvanceSearch search = new AdvanceSearch();
		search.setDomain("Biology");
		search.setServiceName("getENTRYbyScientificName");//getENTRYbyScientificName

		try {
			Service service = new Service();//构建一个服务
			Call call = (Call) service.createCall();
			//注册javaBean 注意和server-config.wsdd保持一致
			QName qn = new QName("urn:BeanService", "Serviceinfo");
			call.registerTypeMapping(Serviceinfo.class, qn,
					new org.apache.axis.encoding.ser.BeanSerializerFactory(
							Serviceinfo.class, qn),
					new org.apache.axis.encoding.ser.BeanDeserializerFactory(
							Serviceinfo.class, qn));
			//创建调用*/			
			call.setTargetEndpointAddress(new java.net.URL(url));
			//调用服务器的方法
			call.setOperationName(new QName("SemanticQueryOperate",
					"getAdvancedSearchArrayList"));
			//设定返回类型
			//call.setReturnClass(ArrayList.class);	//call.invoke(new Object[]{"haha"});
			//设定传入参数
			//call.addParameter("userpara", XMLType.XSD_ANYTYPE, ParameterMode.IN);			
			//System.out.println(new Object[]{userPar});
			//接受结果
			Object[] result = (Object[]) call.invoke(new Object[] { search });
			if (result != null && result.length > 0) {
				for (int i = 0; i < result.length; i++) {
					Serviceinfo serviceinfo = (Serviceinfo) result[i];
					System.out.println(serviceinfo.getCatagoryName()
							+ serviceinfo.getAffiliation());
				}
			}

		} catch (ServiceException e) {
			e.printStackTrace();
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (RemoteException e) {
			e.printStackTrace();
		}
	}

 

 上面代码已经注释得差不多了。就不具体解释了。

再看第一种方式的调用:

Java代码 复制代码
  1. public static void testadvancesearchstub() throws ServiceException {   
  2.         // 创建你要对话的服务   
  3.         SemanticQueryOperateService service = new SemanticQueryOperateServiceLocator();   
  4.            
  5.         SemanticQueryOperate client = service.getSN_AdvanceSearch();   
  6.         //构建服务的输入参数   
  7.         AdvanceSearch search = new AdvanceSearch();   
  8.         search.setDomain("Biology");   
  9.         search.setServiceName("dna");//getENTRYbyScientificName        
  10.         Object[] retValue = null;   
  11.         try {   
  12.             //调用服务,获得结果   
  13.             retValue = client.getAdvancedSearchArrayList(search);   
  14.             System.out.println("start");   
  15.             if (retValue != null && retValue.length > 0) {   
  16.                 for (int i = 0; i < retValue.length; i++) {   
  17.                     Serviceinfo serviceinfo = (Serviceinfo) retValue[i];   
  18.                     System.out.println(serviceinfo.getCatagoryName()   
  19.                             + serviceinfo.getAffiliation());   
  20.                 }   
  21.             }   
  22.         } catch (RemoteException e) {   
  23.             // TODO Auto-generated catch block   
  24.             e.printStackTrace();   
  25.         }   
  26.     }  
public static void testadvancesearchstub() throws ServiceException {
		// 创建你要对话的服务
		SemanticQueryOperateService service = new SemanticQueryOperateServiceLocator();
		
		SemanticQueryOperate client = service.getSN_AdvanceSearch();
		//构建服务的输入参数
		AdvanceSearch search = new AdvanceSearch();
		search.setDomain("Biology");
		search.setServiceName("dna");//getENTRYbyScientificName		
		Object[] retValue = null;
		try {
			//调用服务,获得结果
			retValue = client.getAdvancedSearchArrayList(search);
			System.out.println("start");
			if (retValue != null && retValue.length > 0) {
				for (int i = 0; i < retValue.length; i++) {
					Serviceinfo serviceinfo = (Serviceinfo) retValue[i];
					System.out.println(serviceinfo.getCatagoryName()
							+ serviceinfo.getAffiliation());
				}
			}
		} catch (RemoteException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

 通过代码可以看出第一种方式比较简单,把配置和调用分开了。也不具体讲了,基本上看着代码就知道是什么意思。下一小节再讲这种方式的好处和需要注意的地方。

 

axis1.4 使用笔记(4)

4 服务发布需要注意的地方(包括客户端和服务端)

       axis的用法可以说简单,也可以说难。有很多细节方面不注意的话会让你花费很多时间。很多答案在网上是没有答案的,只能靠自己琢磨。在这一节中我就把一些常见的问题或建议总结下:

 

1.自定义类型的映射。

 

Java代码 复制代码
  1. QName qn = new QName("urn:BeanService""AbstractServiceinfo");   
  2. _call.registerTypeMapping(AbstractServiceinfo.class, qn,   
  3.                 new org.apache.axis.encoding.ser.BeanSerializerFactory(   
  4.                         AbstractServiceinfo.class, qn),   
  5.                 new org.apache.axis.encoding.ser.BeanDeserializerFactory(   
  6.                         AbstractServiceinfo.class, qn));  
QName qn = new QName("urn:BeanService", "AbstractServiceinfo");
_call.registerTypeMapping(AbstractServiceinfo.class, qn,
				new org.apache.axis.encoding.ser.BeanSerializerFactory(
						AbstractServiceinfo.class, qn),
				new org.apache.axis.encoding.ser.BeanDeserializerFactory(
						AbstractServiceinfo.class, qn));

 格式基本如上所示。

要记住当你的方法需要传入自定义类型的参数或返回自定义类型时,一定要在wsdd文档中注册,在客户端编程时也要注册。 

客户端采取第二种方式时的映射注册可以看3.2.3的代码,采取第一种方式时也要注册,需要找到服务对应的存根类SN_AdvanceSearchSoapBindingStub,在这个类里有各个方法对应的调用配置,找到需要注册的方法,加上上面的映射就行了。格式都是一样的!

 

2.当返回类型类似于ArrayList<Serviceinfo>时

对于这样的返回类型,axis都会把返回值转成Object[],别想着直接把结果转成ArrayList,有时会出问题

下面是一个典型的用法:方法的返回值是ArrayList<Serviceinfo>,用下面的方法遍历就行了。

Java代码 复制代码
  1. Object[] result = (Object[]) call.invoke(new Object[] { search });   
  2.             if (result != null && result.length > 0) {   
  3.                 for (int i = 0; i < result.length; i++) {   
  4.                     Serviceinfo serviceinfo = (Serviceinfo) result[i];   
  5.                     System.out.println(serviceinfo.getCatagoryName()   
  6.                             + serviceinfo.getAffiliation());   
  7.                 }   
  8.             }  
Object[] result = (Object[]) call.invoke(new Object[] { search });
			if (result != null && result.length > 0) {
				for (int i = 0; i < result.length; i++) {
					Serviceinfo serviceinfo = (Serviceinfo) result[i];
					System.out.println(serviceinfo.getCatagoryName()
							+ serviceinfo.getAffiliation());
				}
			}

 对于java中的set也一样,都会转成Object[],如下面的方法:

Map<Integer, Set<Integer>> composition(UserParameter userparameter)得到返回值时就应该这样处理:

Java代码 复制代码
  1. Map<Integer, Object[]> result=(Map) call.invoke(new Object[]{userPar});   
  2.                    
  3.             for (Iterator<Integer> iter = result.keySet().iterator(); iter   
  4.                     .hasNext();) {   
  5.                 Integer key = iter.next();   
  6.                 Object[] obj = result.get(key);   
  7.                 if(obj != null && obj.length > 0) {    
  8.                       for(int i = 0; i < obj.length; i ++) {    
  9.                           Integer serviceinfo = (Integer) obj[i];    
  10.                         System.out.println(serviceinfo);                     
  11.                         }    
  12.                 }         
Map<Integer, Object[]> result=(Map) call.invoke(new Object[]{userPar});
				
			for (Iterator<Integer> iter = result.keySet().iterator(); iter
					.hasNext();) {
				Integer key = iter.next();
				Object[] obj = result.get(key);
				if(obj != null && obj.length > 0) { 
					  for(int i = 0; i < obj.length; i ++) { 
						  Integer serviceinfo = (Integer) obj[i]; 
					    System.out.println(serviceinfo);				  
						} 
				}		

 注意对应于Set<Integer>的返回值是Object[]类型,通过循环来遍历,如果直接转型就会出现异常

 

3.自定义类型一定要可以序列化,也就是要实现java.io.Serializable接口。如果你的方法准备发布成web服务最好把输入和输出都打包成javaBean,axis对javaBean的处理还是很自动的。

 

4.需要在服务端和客户端传递的javaBean当然在两端的工程里都应该有相似的代码,否则就会出现一方不能解析!如果客户端不能直接拿到javaBean的代码,可以借助wsdl2java生成的类中就应该会有对应的javaBean,直接拿过来用就行,当然,下一步采取哪种方式调用服务都是随意的。可见wsdl2java还是很有用的。

 

5.这点一定要看:血的教训

如果你的服务中返回值都是类似于List<Serviceinfo> getServiceinfoList(...)这样的集合类型,而没有一个类似于Serviceinfo getServiceinfo(..)这样的方法,发布成服务后,在对应的wsdl中就不会出现Serviceinfo的复杂类型对应的,也就是说你用wsdl2java是不能生成Serviceinfo对应的javaBean的。。调用的时候也就会出错。解决方法是在服务端可以加上一个什么也不做的public方法,如:

Java代码 复制代码
  1. public Serviceinfo doNothing(){   
  2.         Serviceinfo info=new Serviceinfo();    
  3.         return info;   
  4.     }  
public Serviceinfo doNothing(){
		Serviceinfo info=new Serviceinfo();	
		return info;
	}

 这样。wsdl文档中就会有对Serviceinfo的类型定义了。

这一步很重要啊。。当时在这徘徊了好久。。一定不要以为你在wsdd中有了beanMapping定义,就会在wsdl中出现对应类型定义,一定要在你的public方法的输入或返回值用到这个bean时才会在

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要实现Spring Boot整合Axis1.4实现WebService服务端,可以按照以下步骤进行: 1. 在pom.xml文件中添加Axis1.4依赖: ``` <dependency> <groupId>org.apache.axis</groupId> <artifactId>axis</artifactId> <version>1.4</version> </dependency> ``` 2. 创建一个WebService接口,并在接口上添加@WebService注解: ``` @WebService public interface UserService { String sayHello(String name); } ``` 3. 创建一个WebService接口的实现类,并在实现类上添加@WebService(endpointInterface = "com.example.demo.UserService")注解: ``` @WebService(endpointInterface = "com.example.demo.UserService") public class UserServiceImpl implements UserService { @Override public String sayHello(String name) { return "Hello, " + name + "!"; } } ``` 4. 在Spring Boot的配置文件application.properties中添加Axis1.4的配置: ``` # Axis1.4配置 axis.servletPath=/services/* ``` 5. 创建一个AxisServlet的注册类,并在类上添加@Configuration和@EnableWebMvc注解: ``` @Configuration @EnableWebMvc public class AxisServletRegistration { @Bean public ServletRegistrationBean<AxisServlet> axisServlet() { ServletRegistrationBean<AxisServlet> registration = new ServletRegistrationBean<>(new AxisServlet(), "/services/*"); registration.addInitParameter("axis.servicesPath", "/WEB-INF/services"); registration.addInitParameter("axis.wsddPath", "/WEB-INF/server-config.wsdd"); return registration; } } ``` 6. 启动Spring Boot应用程序,访问http://localhost:8080/services/UserService?wsdl,可以看到WebService服务端已经成功启动。 以上就是Spring Boot整合Axis1.4实现WebService服务端的全部步骤。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值