`
yydcj
  • 浏览: 61588 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

axis1.4 使用笔记

阅读更多

引自http://ytsho.spaces.live.com/blog/cns!A3DC45268A88C509!215.entry

 

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时才会在

分享到:
评论

相关推荐

    axis1.4学习文档

    axis1.4 webservice个人学习笔记

    Axis + tomcate

    标题 "Axis + tomcat" 指涉的是在Apache Axis1.4版本与Tomcat应用服务器上部署和使用Web服务的技术。Apache Axis是Java平台上一个流行的开源工具,用于创建和部署Web服务,而Tomcat则是一款轻量级的Java应用服务器,...

    OracleEBS-WebService开发笔记.pdf

    - **Axis 1.4 在 EBS 11i 中的应用**:描述如何在 EBS 11i 中部署和使用 Axis 1.4。 - **Oracle Call-in WebService**:从外部调用 EBS 的 WebService。 - **Oracle Call-out WebService**:从 EBS 内部调用外部 ...

    Axis2版本学习笔记

    本笔记将深入探讨Axis2的核心概念、版本差异、安装配置以及在实际项目中的应用。 1. **核心概念** - **SOAP**: Axis2是基于SOAP(Simple Object Access Protocol)协议的,它允许应用程序通过HTTP进行通信,实现跨...

    axis学习资料汇总

    axis学习资料汇总: Axis实例与分析详解; Axis学习笔记.pdf; Tomcat5.0.28下AXIS完全安装手册.doc; Axis1.4 开发指南_V1.0.pdf; AXIS入门及应用.rar; Axis开发Web+Services.doc 等等

    Axis2_1.X学习笔记

    标题"Axis2_1.X学习笔记"指的是关于Axis2的一个学习资源,其中1.X代表可能是1.4或者1.5等版本,Axis2是Apache软件基金会开发的一个开放源代码Web服务平台,主要用于构建和部署Web服务。这个学习笔记可能是对Axis2在1...

    AXIS摄像机调试培训PPT学习教案.pptx

    1. **AXIS IP Utility的使用**:这是一个用于扫描并识别网络中物理连接的AXIS摄像机的工具。在使用前,需要将笔记本电脑的本地连接IP设置为与摄像机在同一网段,以确保通信。 2. **摄像机初始化设置**:当摄像机是...

    AXIS摄像机调试培训PPT教学课件.pptx

    - 使用AXIS IP Utility扫描物理连接中的摄像机IP,确保笔记本电脑的本地连接IP与摄像机在同一网段。 - 在设置IP时,需避免笔记本电脑使用169.254开头的DHCP地址,否则摄像机会学习到这个地址。 2. **初始配置**:...

    webservices 资源

    “Apache Axis 1.4.zip”和“103244826axis.zip”是Apache Axis的版本,Axis是一个流行的Java Web服务框架,用于生成和部署Web服务。它简化了SOAP通信,并提供了自动代码生成工具。 “axis文档.zip”很可能是Apache...

    卡耐基梅陇大学 计算机图形学 PPT 4-transform

    **N1.4. 给出一个用于刚体平移的变换矩阵,如第一页图所示。** 对于刚体平移,我们可以使用一个4x4的变换矩阵来表示。假设平移向量为 \(\mathbf{d} = [d_x, d_y, d_z]^T\),则变换矩阵可以表示为: \[ T(d_x, d_y,...

Global site tag (gtag.js) - Google Analytics