当前位置: 首页 > >

用axis1.3开发soap

发布时间:

【前言】发现我没有压力的时候就会懒,一直想总结一下之前用axis1.3开发时学到的知识,但是这件事情一直被我推到了今天。如果再不记录一下的话,我想不过多久自己都不记得怎么做了,更何况本来axis用的就不深入。目前soap的开发已经告一段落,估计以后也没有机会在做这方面了,我要去学*项目中一个高深的模块,到目前为止还是雾水。。。


???? 其实axis1中我还是有很多没有搞懂的地方,这个总结中应该很多地方没有讲清楚甚至是错误的,希望各位批判着看,有错误还望指出。还是老样子,总结中的图没有贴上来,贴图太繁琐了。


?


?


一 安装

1. 下载axis-bin-1_3.zip,解压后放在tomcat下的webapps目录下


C:/Program Files/Apache Software Foundation/Tomcat 5.5/webapps/


可以访问到axis的界面:



可以点击Validation验证一下axis安装是否正确:




2. 设置环境变量如下。其实并不一定非要按照这个设置,只要在CLASSPATH中找到相关的包就可以。


设置AXIS_HOME:%TOMCAT_HOME%/webapps/axis


设置AXIS_LIB:%AXIS_HOME%/WEB-INF/lib


设置AXISCLASSPATH:%AXIS_LIB%/activation.jar;%AXIS_LIB%/axis.jar;%AXIS_LIB%/axis-ant.jar;%AXIS_LIB%/commons-discovery-0.2.jar;%AXIS_LIB%/commons-httpclient-3.1.jar;%AXIS_LIB%/commons-logging-1.0.4.jar;%AXIS_LIB%/jaxrpc.jar;%AXIS_LIB%/log4j-1.2.8.jar;%AXIS_LIB%/mailapi.jar;%AXIS_LIB%/saaj.jar;%AXIS_LIB%/wsdl4j-1.5.1.jar;%AXIS_LIB%/xercesImpl.jar???


设置CLASSPATH


.;%TOMCAT_HOME%/common/lib/soap.jar;%TOMCAT_HOME%/common/lib/mail.jar;%TOMCAT_HOME%/common/lib/activation.jar;%TOMCAT_HOME%/common/lib/xercesImpl.jar;%TOMCAT_HOME%/common/lib/xml-apis.jar;C:/Sun/SDK/lib;%TOMCAT_HOME%/common/lib/servlet-api.jar;D:/software_work/ICP/ICP_CI_Windows_Master/tools/ant/lib;%AXIS_LIB%/activation-1.1.jar;%AXIS_LIB%/axis-1.3.jar;%AXIS_LIB%/axis-jaxrpc-1.3.jar;%AXIS_LIB%/axis-saaj-1.3.jar;%AXIS_LIB%/axis-wsdl4j-1.3.jar;%AXIS_LIB%/commons-discovery-0.2.jar;%AXIS_LIB%/commons-el.jar;%AXIS_LIB%/commons-logging-1.0.4.jar;%AXIS_LIB%/jasper-compiler.jar;%AXIS_LIB%/jasper-compiler-jdt.jar;%AXIS_LIB%/jasper-runtime.jar;%AXIS_LIB%/jsp-api.jar;%AXIS_LIB%/junit-3.8.1.jar;%AXIS_LIB%/mail-1.4.jar;%AXIS_LIB%/naming-factory.jar;%AXIS_LIB%/naming-factory-dbcp.jar;%AXIS_LIB%/naming-resources.jar;%AXIS_LIB%/opensaml-1.0.1.jar;%AXIS_LIB%/servlet-api.jar;%AXIS_LIB%/spring-1.2.7.jar;%AXIS_LIB%/wimssecurity-client.jar;%AXIS_LIB%/wss4j-1.1.0.jar;%AXIS_LIB%/xercesImpl-2.6.0.jar;%AXIS_LIB%/xml-apis-1.0.b2.jar;%AXIS_LIB%/xmlsec-1.3.0.jar;


二 根据wsdl生成代码

1. WSDL2Java常用的参数如下:


-s ?? server-side


-p??? package


-c ?? implementationClassName


想了解更多,使用java org.apache.axis.wsdl.WSDL2Java ?h查看帮助。


2. 在wsdl所在的目录,用WSDL2Java根据wsdl生成代码,命令如下:


java -cp "%CLASSPATH%" org.apache.axis.wsdl.WSDL2Java -s -p webservices.test.DeviceNotification -c webservices.test.DeviceNotification.TestServiceSkeleton new_Test.wsdl




如果生成代码成功,则不报任何信息。这样就生成了下面的代码和文件:


[D:/eclipse_workspace/eclipse_fromwebdev/AAAtoOMA_axis1.3/src/webservices/test/DeviceNotification/]


?├-[TestServiceSkeleton.java]


?├-[deploy.wsdd]


?├-[DeviceObject.java]


?├-[NewNotifyStatusCode.java]


?├-[undeploy.wsdd]


?├-[DeviceManagementBindingStub.java]


?├-[DeviceManagementService.java]


?├-[DeviceManagementServiceLocator.java]


?└-[DeviceManagement_PortType.java]



下面是对上面文件的介绍:



l???????? TestServiceSkeleton.java


这个类是服务器业务代码的实现类。类中的方法名称和wsdl中定义的是portType中operation是一致的。其实在porttype中定义的就是各个消息以及它的request/response。在TestServiceSkeleton.java中正是来实现这个消息在服务器端的代码,函数入参是在porttype中定义的input,函数出参就是在porttype中定义的output。



注意:有关这个类中各个消息函数的入参和出参的名称,在axis1.3和axis2.1.4中定义是不同。在aixs2.1.4生成的代码中,这个函数的入参和出参名称就是wsdl中porttype的input/output之后的message之后的内容,如下图:



而在用axis1.3生成的代码中,这个函数的入参和出参名称是input/output中message对应的type,如下图。我想,这个可能也是axis1.3的封装性不如axis2吧




l???????? DeviceObject.java,NewNotifyStatusCode.java


对于在wsdl中定义的类型,axis1(axis2也是)都会生成一个相应的封装类。自定义类型,wsdl中的复杂类型定义都会生成对应的javaBean。



l???????? DeviceManagementBindingStub.java


这个类实现了DeviceManagementService接口,作为服务器在客户端的存根,也就是一个stub。在客户端,对服务器的所有调用,本质上都是对stub的调用。这个类中也有一个portType中operation定义一致的函数DeviceNotification,这个函数中实现向server发送request消息:


//发送消息给server


java.lang.Object _resp = _call.invoke(new java.lang.Object[] { deviceObject });


1)可以在这个函数中设置client端等待消息的超时时长:


// 从配置文件中读取超时时间并设置


CfgData cfgData = CfgData.getInstance();


Integer timeout = new Integer(cfgData.getDeviceServer().getTimout());


_call.setTimeout(timeout);


2)可以在这个函数中增加soap request的soap header:在setRequestHeaders(_call);之前拼接好soap header,然后设置_call.addHeader(head);


3)有的时候,对端不使用soap header中的验证方式,而是采用http验证方式,那么可以在该函数中使用http验证方式:


// 从配置文件中读出http验证的用户名和密码


_call.getMessageContext().setUsername(cfgData.getReturnIPServer().getUserName());


_call.getMessageContext().setPassword(cfgData.getReturnIPServer().getPassword());



l???????? DeviceManagementService.java


该类是一个接口,相当于wsdl中的wsdl:service结点,定义了得到这个服务的信息的函数。



l???????? DeviceManagementServiceLocator


该类实现了DeviceManagementService接口,这个类的作用是直接与服务器端通信,建立与服务器端的连接,实例化stub。然后客户端就可以通过stub与服务器通信了。从字面意思是指定服务所在的locator,包括url和服务名称。


可以直接在这个类中指定服务所在的url如下,也可以从配置文件中读出对端的url:


private java.lang.String DeviceManagement_address = http://202.54.48.26:8280/services/DeviceManagement;



l???????? DeviceManagement_PortType.java


这个也是一个接口,描述服务器端能干什么,对应于wsdl中的wsdl:portType。该接口中定义了DeviceNotification函数,DeviceManagementBindingStub.java实现了这个接口。



三 修改代码

1. 修改服务器端的代码,以实现业务逻辑:这个主要是修改TestServiceSkeleton.java。在相应的函数中实现具体的服务器端代码,同时给客户端回response。


2. 修改客户端的代码,给服务器端发送request。


?????? DeviceManagementService service = new DeviceManagementServiceLocator();


?????????????????? DeviceManagement_PortType client;


?????????????????? try {


??????????????????????????? URL portAddress = new URL(url);


??????????????????????????? client = service.getDeviceManagement(portAddress);


??????????????????????????? NewNotifyStatusCode statusCode;


??????????????????????????? // 发送消息并得到返回值


??????????????????????????? statusCode = client.DeviceNotification(newDeviceObject);


??????????????????????????? log.debug("Get DeviceNotification Response(statuscode) is:" + statusCode.getStatusCode());


??????????????????????????? return statusCode.getStatusCode();


?????????????????? } catch (ServiceException e) {


??????????????????????????? // TODO Auto-generated catch block


??????????????????????????? e.printStackTrace();


??????????????????????????? return -1;


?????????????????? } catch (RemoteException e) {


??????????????????????????? // TODO Auto-generated catch block


??????????????????????????? e.printStackTrace();


??????????????????????????? return -1;


?????????????????? } catch(Exception e){


??????????????????????????? e.printStackTrace();


??????????????????????????? return -1;


?????????????????? }


四 发布工程

1. 发布工程时,首先要启动tomcat


2. 发布命令为java -cp "%CLASSPATH%" org.apache.axis.client.AdminClient deploy.wsdd


3. 发布成功后,会在C:/Program Files/Apache Software Foundation/Tomcat 5.5/webapps/axis/WEB-INF/目录下自动生成server端的部署文件server-config.wsdd,从这个文件中可以看到相关的部署信息:



// 定义了将来部署的服务名称为OmadmToAaa,这样访问这个服务时url为:http://localhost:8080/AAAtoOMA_axis1.3/services/ OmadmToAaa。下面的两组消息registerIPNotification和provisionComplete都是定义在这个服务中的


?


??


?


// returnQName和returnType定义了registerIPNotification消息出参为MacIpAddr。parameter这个元素是定义registerIPNotification消息的出参为registerIPNotification


??


??


?


// 同样,这段定义了provisionComplete消息的入参和出参


?


// 定义了在这个服务中允许调用的消息方法


?


?


?


// 指定了服务实现的类


?


?


?


?


?


// 定义了按照什么方法解析消息中的CommandStatusCode,其中type为axis专门对该数据类型实现的类


?


// 定义了按照什么方法解析消息中的MacIpAddr


?


// 定义了按照什么方法解析消息中的RegisterIPNotification


?


// 定义了按照什么方法解析消息中的ProvisionData


?


4. 如果之前在WEB-INF目录下有一个server-config.wsdd,在发布一个另外的服务时,原来的server-config.wsdd并不会被完全覆盖,而是会在原来的基础上,将新发布的内容追加进去,真好。


五 借用axis1发布工程的方法

有时候不使用axis1.3产生的代码框架,但是想借用axis1.3来发布业务代码,可以采用下面偷懒的方法:


1. 首先用wsdl文件,用wsdl2java来生成代码和deploy.wsdd


2. 用deploy.wsdd发布服务,同时生成server-config.wsdd


3. 按照实际的代码,修改server-config.wsdd。


六 在eclipse中启动tomcat,发布axis1.3工程的方法

发布工程目录如下图:


1. 把server-config.wsdd放在工程的WEB-INF下,server-config.wsdd可以用delpoy.wsdd发布时自动产生的那个


2. 用axis安装目录下web.xml覆盖WEB-INF目录下的web.xml



如果WEB_INF目录下没有server-config.wsdd会报错。delpoy.wsdd和server-config.wsdd是两回事,单单把delpoy.wsdd放在WEB-INF下,是不能发布该工程,仍然会报下面的错误:



另外,并不用将class专门放到WEB_INF目录下,也不用将axis的lib专门copy到WEB_INF/lib下。


注意:axis1和axis2部署的方式是不用的。


七 axis1和axis2的区别

为了适应对端,我们从axis2降为axis1。在前期开发过程中,


1. multiref:


Axis1支持multiref,发出去的soap消息中的数据就用multiref表示(当server-config.wsdd中的sendMultiRefs为true)。但是axis2不支持multiref,如果非要axis2能够支持解析multiref的消息,可以利用MultiRefTestSOAPBindingImpl这个类自己手工解析。



2. axis2目前还不支持rpc/encoded


3. axis1和axis2生成的代码框架上也有很大的不同。


八 日志中有个奇怪的目录

启动tomcat并部署后,发现在tomcat的log目录下出现了一个很奇怪的目录。


-rw-r----- 1 webadm web??? 0 2010-05-02 18:52 admin.2010-05-02.log


-rw-r----- 1 webadm web 1054 2010-05-02 18:52 catalina.2010-05-02.log


-rw-r----- 1 webadm web 1556 2010-05-02 18:52 catalina.out


drwxr-x--- 2 webadm web 4096 2010-05-02 18:52 C:/Program Files/Apache Software Foundation/Tomcat 5.5/webapps/axis/WEB-INF/attachments


-rw-r----- 1 webadm web??? 0 2010-05-02 18:52 host-manager.2010-05-02.log


-rw-r----- 1 webadm web??? 0 2010-05-02 18:52 localhost.2010-05-02.log


-rw-r----- 1 webadm web??? 0 2010-05-02 18:52 manager.2010-05-02.log


后来看了server-config.wsdd,这个应该是axis1指定的消息附件存放的目录。


value="C:/Program Files/Apache Software Foundation/Tomcat 5.5/webapps/axis/WEB-INF/attachments" />


我还没有试过,是否可以将server-config.wsdd的这个参数去掉,来控制是否产生这个附件目录。


九 参考资料

1. 最*刚发现的一个介绍WSDL2Java的文档《WSDL2Java操作指南》


http://blog.csdn.net/wjwwgh/archive/2009/07/07/4325559.aspx


2. Axis1.3生成的代码分别是什么作用?


http://zhongkem.javaeye.com/blog/514130


3. apache官方网站讲解wsdd


http://ws.apache.org/axis/java/reference.html#DeploymentWSDDReference


?



友情链接: