用axis1.3开发soap

来源:互联网 发布:看耽美小说的软件 编辑:程序博客网 时间:2024/05/01 22:20

【前言】发现我没有压力的时候就会懒,一直想总结一下之前用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 <argument>

-c    implementationClassName <argument>

想了解更多,使用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中定义的是portTypeoperation是一致的。其实在porttype中定义的就是各个消息以及它的request/response。在TestServiceSkeleton.java中正是来实现这个消息在服务器端的代码,函数入参是在porttype中定义的input,函数出参就是在porttype中定义的output

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

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

l         DeviceObject.javaNewNotifyStatusCode.java

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

l         DeviceManagementBindingStub.java

这个类实现了DeviceManagementService接口,作为服务器在客户端的存根,也就是一个stub。在客户端,对服务器的所有调用,本质上都是对stub的调用。这个类中也有一个portTypeoperation定义一致的函数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 requestsoap 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,从这个文件中可以看到相关的部署信息:

<service name="OmadmToAaa" provider="java:RPC">

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

  <operation name="registerIPNotification" qname="ns1:registerIPNotification" returnQName="macIpAddr" returnType="ns1:MacIpAddr" soapAction="http://services.mformation.com/MFServices/registerIPNotification" xmlns:ns1="http://services.mformation.com/MFServices/">

   <parameter name="registerIPNotification" type="ns1:RegisterIPNotification"/>

  </operation>

// returnQNamereturnType定义了registerIPNotification消息出参为MacIpAddrparameter这个元素是定义registerIPNotification消息的出参为registerIPNotification

  <operation name="provisionComplete" qname="ns2:provisionComplete" soapAction="http://services.mformation.com/MFServices/provisionComplete" xmlns:ns2="http://services.mformation.com/MFServices/">

   <parameter name="provisionData" type="ns2:ProvisionData"/>

  </operation>

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

  <parameter name="allowedMethods" value="provisionComplete registerIPNotification"/>

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

  <parameter name="typeMappingVersion" value="1.2"/>

  <parameter name="wsdlPortType" value="OmadmToAaaPort"/>

  <parameter name="className" value="webservices.omadmtoaaa.OmadmToAaaServiceSkeleton"/>

// 指定了服务实现的类

  <parameter name="wsdlServicePort" value="OmadmToAaa"/>

  <parameter name="schemaQualified" value="http://services.mformation.com/MFServices/"/>

  <parameter name="wsdlTargetNamespace" value="http://services.mformation.com/MFServices/"/>

  <parameter name="wsdlServiceElement" value="OmadmToAaaService"/>

  <typeMapping deserializer="org.apache.axis.encoding.ser.EnumDeserializerFactory" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" qname="ns3:CommandStatusCode" serializer="org.apache.axis.encoding.ser.EnumSerializerFactory" type="java:webservices.omadmtoaaa.CommandStatusCode" xmlns:ns3="http://services.mformation.com/MFServices/"/>

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

  <typeMapping deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" qname="ns4:MacIpAddr" serializer="org.apache.axis.encoding.ser.BeanSerializerFactory" type="java:webservices.omadmtoaaa.MacIpAddr" xmlns:ns4="http://services.mformation.com/MFServices/"/>

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

  <typeMapping deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" qname="ns5:RegisterIPNotification" serializer="org.apache.axis.encoding.ser.BeanSerializerFactory" type="java:webservices.omadmtoaaa.RegisterIPNotification" xmlns:ns5="http://services.mformation.com/MFServices/"/>

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

  <typeMapping deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" qname="ns6:ProvisionData" serializer="org.apache.axis.encoding.ser.BeanSerializerFactory" type="java:webservices.omadmtoaaa.ProvisionData" xmlns:ns6="http://services.mformation.com/MFServices/"/>

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

 </service>

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.wsddserver-config.wsdd是两回事,单单把delpoy.wsdd放在WEB-INF下,是不能发布该工程,仍然会报下面的错误:

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

注意:axis1axis2部署的方式是不用的。

axis1axis2的区别

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

1. multiref

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

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

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

日志中有个奇怪的目录

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

-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指定的消息附件存放的目录。

<parameter name="attachments.Directory" 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

 

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 补过的牙齿变黑怎么办 受伤牙齿脱落后怎么办 一岁多宝宝牙齿脱落怎么办 老年人门牙掉了怎么办 老年人磨牙掉了怎么办 种植牙牙龈发炎怎么办 种植牙牙龈红肿怎么办 种植牙后牙龈怎么办 种植牙牙龈感染怎么办 种植牙牙龈向上怎么办 上门牙有点突出怎么办 电脑语音电流声怎么办 麦克风说不了话怎么办 耳机说不了话怎么办 饿了么小休超时怎么办 美团清退代理商怎么办 小孩龟头肿很大怎么办 16岁不想上学怎么办 宜宾南门桥逆行怎么办 去加拿大探亲签证怎么办 重庆两路口到菜坝园怎么办 摄像头uid忘了怎么办 电梯钢丝绳断了怎么办 在小区车被砸了怎么办 甲米天气下雨怎么办 电影院不开空调怎么办 电脑总弹广告怎么办 下雨天了怎么办神接 天下雨了怎么办套路 下雨天了怎么办 新套路 万达兑换券过期怎么办 直播间没一个人怎么办 快手直播人少怎么办 快手直播人气少怎么办 被火山主播踢出房间怎么办 遇到同事的排挤怎么办 交警处理事故不公平怎么办 派出所处理事情不公平怎么办 淘宝号不健康了怎么办 作业盒子忘记密码怎么办 一起作业忘记密码怎么办