构建一个新的Web Services服务,会有很多种不同的方法,你即可以用pojo结合rpc模式来写,也可以用axis2自己的axiom api从底层写,也可以从wsdl生成相应框架,然后填写相应逻辑。
对于wsdl生成框架代码这种形式,又有不同的数据绑定可以使用。axis2 1.1 可以使用adb(axis2自己的data binding)、xmlbeans、jibx、jaxme、jaxbri。其中常用的还是前两种,axis2官方是极力推荐自己的data binding的,因为速度快,架构相对简单,而且有一些独有的特性。xmlbeans,是对模式支持最好的data binding,一些特别复杂的模式只能在xmlbeans下才能正确生成框架代码。其他几种代码wsdl2java目前都不是支持得很好,都还在实验改进阶段。
面对这么多数据绑定模式,很多人都无从选择。官方maillist上也有好多人问该用哪个。查了一些资料,据说,adb很好用,而且速度快,如果只是简单的模式,那么使用这种数据绑定就可以了。xmlbeans的强力模式支持,可以支持足够负责的模式,但是速度上也只是比adb低5%左右。
axis2的wsdl2java工具对于adb以及xmlbeans支持都已经很好了,可以直接从wsdl2java生成相应的绑定类
Axis2 还提供自己的简单数据绑定框架,称为 Axis2 Data Binding (ADB)。这就允许用户下载 Axis2 并使用它,而不用太多考虑数据绑定框架。由于 ADB 和 Axis2 内部元素之间实现了紧密的集成,可以预见,与其他框架相比,此框架的性能和生成代码维护方面都更具优势。
为了充分利用资源,我们用上一个有关AXIOM专题的例子中生成的WSDL文件来为这个例子服务
1.生成ADB服务框架。使用的WSDL文件如下:
- <wsdl:definitions xmlns:axis2="http://service.util.danlley.org" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
- xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
- xmlns:ns="http://service.util.danlley.org/xsd" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
- targetNamespace="http://service.util.danlley.org">
- <wsdl:types>
- <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" attributeFormDefault="qualified" elementFormDefault="qualified"
- targetNamespace="http://service.util.danlley.org/xsd">
- <xs:element name="getHelloMessageFault">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="getHelloMessageFault" type="xs:anyType" />
- xs:sequence>
- xs:complexType>
- xs:element>
- <xs:element name="getHelloMessage">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="element" nillable="true" type="xs:anyType" />
- xs:sequence>
- xs:complexType>
- xs:element>
- <xs:element name="getHelloMessageResponse">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="return" nillable="true" type="xs:anyType" />
- xs:sequence>
- xs:complexType>
- xs:element>
- <xs:element name="getMoreMessageFault">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="getMoreMessageFault" type="xs:anyType" />
- xs:sequence>
- xs:complexType>
- xs:element>
- <xs:element name="getMoreMessage">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="element" nillable="true" type="xs:anyType" />
- xs:sequence>
- xs:complexType>
- xs:element>
- <xs:element name="getMoreMessageResponse">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="return" nillable="true" type="xs:anyType" />
- xs:sequence>
- xs:complexType>
- xs:element>
- xs:schema>
- wsdl:types>
- <wsdl:message name="getHelloMessageMessage">
- <wsdl:part name="part1" element="ns:getHelloMessage" />
- wsdl:message>
- <wsdl:message name="getHelloMessageResponseMessage">
- <wsdl:part name="part1" element="ns:getHelloMessageResponse" />
- wsdl:message>
- <wsdl:message name="getHelloMessageFault">
- <wsdl:part name="part1" element="ns:getHelloMessageFault" />
- wsdl:message>
- <wsdl:message name="getMoreMessageMessage">
- <wsdl:part name="part1" element="ns:getMoreMessage" />
- wsdl:message>
- <wsdl:message name="getMoreMessageResponseMessage">
- <wsdl:part name="part1" element="ns:getMoreMessageResponse" />
- wsdl:message>
- <wsdl:message name="getMoreMessageFault">
- <wsdl:part name="part1" element="ns:getMoreMessageFault" />
- wsdl:message>
- <wsdl:portType name="HelloWorldAxiomPortType">
- <wsdl:operation name="getHelloMessage">
- <wsdl:input message="axis2:getHelloMessageMessage" />
- <wsdl:output message="axis2:getHelloMessageResponseMessage" />
- <wsdl:fault message="axis2:getHelloMessageFault" name="getHelloMessageFault" />
- wsdl:operation>
- <wsdl:operation name="getMoreMessage">
- <wsdl:input message="axis2:getMoreMessageMessage" />
- <wsdl:output message="axis2:getMoreMessageResponseMessage" />
- <wsdl:fault message="axis2:getMoreMessageFault" name="getMoreMessageFault" />
- wsdl:operation>
- wsdl:portType>
- <wsdl:binding name="HelloWorldAxiomSOAP11Binding" type="axis2:HelloWorldAxiomPortType">
- <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" />
- <wsdl:operation name="getHelloMessage">
- <soap:operation soapAction="urn:getHelloMessage" style="document" />
- <wsdl:input>
- <soap:body use="literal" namespace="http://service.util.danlley.org" />
- wsdl:input>
- <wsdl:output>
- <soap:body use="literal" namespace="http://service.util.danlley.org" />
- wsdl:output>
- <wsdl:fault name="getHelloMessageFault">
- <soap:body use="literal" namespace="http://service.util.danlley.org" />
- wsdl:fault>
- wsdl:operation>
- <wsdl:operation name="getMoreMessage">
- <soap:operation soapAction="urn:getMoreMessage" style="document" />
- <wsdl:input>
- <soap:body use="literal" namespace="http://service.util.danlley.org" />
- wsdl:input>
- <wsdl:output>
- <soap:body use="literal" namespace="http://service.util.danlley.org" />
- wsdl:output>
- <wsdl:fault name="getMoreMessageFault">
- <soap:body use="literal" namespace="http://service.util.danlley.org" />
- wsdl:fault>
- wsdl:operation>
- wsdl:binding>
- <wsdl:binding name="HelloWorldAxiomSOAP12Binding" type="axis2:HelloWorldAxiomPortType">
- <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" />
- <wsdl:operation name="getHelloMessage">
- <soap12:operation soapAction="urn:getHelloMessage" style="document" />
- <wsdl:input>
- <soap12:body use="literal" namespace="http://service.util.danlley.org" />
- wsdl:input>
- <wsdl:output>
- <soap12:body use="literal" namespace="http://service.util.danlley.org" />
- wsdl:output>
- <wsdl:fault name="getHelloMessageFault">
- <soap12:body use="literal" namespace="http://service.util.danlley.org" />
- wsdl:fault>
- wsdl:operation>
- <wsdl:operation name="getMoreMessage">
- <soap12:operation soapAction="urn:getMoreMessage" style="document" />
- <wsdl:input>
- <soap12:body use="literal" namespace="http://service.util.danlley.org" />
- wsdl:input>
- <wsdl:output>
- <soap12:body use="literal" namespace="http://service.util.danlley.org" />
- wsdl:output>
- <wsdl:fault name="getMoreMessageFault">
- <soap12:body use="literal" namespace="http://service.util.danlley.org" />
- wsdl:fault>
- wsdl:operation>
- wsdl:binding>
- <wsdl:service name="HelloWorldAxiom">
- <wsdl:port name="HelloWorldAxiomSOAP11port" binding="axis2:HelloWorldAxiomSOAP11Binding">
- <soap:address location="http://localhost:8080/axis2/services/HelloWorldAxiom" />
- wsdl:port>
- <wsdl:port name="HelloWorldAxiomSOAP12port" binding="axis2:HelloWorldAxiomSOAP12Binding">
- <soap12:address location="http://localhost:8080/axis2/services/HelloWorldAxiom" />
- wsdl:port>
- wsdl:service>
- wsdl:definitions>
2.生成工程框架
运行命令如下:WSDL2Java -uri resources/META-INF/HelloWorldAxiom.wsdl -p org.danlley.service.adb -d adb -s -ss -sd -ssi -o build/service
如果得到以下结果则说明执行成功:
--------------------------------------------------------------------------------
D:\eclipse\workspace\axis2adblab>WSDL2Java -uri resources/META-INF/HelloWorldAxi
om.wsdl -p org.danlley.service.adb -d adb -s -ss -sd -ssi -o build/service
Using AXIS2_HOME: D:\axis2-1.1.1
Using JAVA_HOME: C:\Program Files\Java\jdk1.5.0_06
D:\eclipse\workspace\axis2adblab>
--------------------------------------------------------------------------------
执行成功后在工程中出现的路径如下:
--------------------------------------------------------------------------------
./build/service/build.xml
./build/service/resources/HelloWorldAxiom.wsdl
services.xml
./build/service/src/org/danlley/service/adb/GetHelloMessageFaultException.java
GetMoreMessageFaultException.java
HelloWorldAxiomMessageReceiverInOut.java
HelloWorldAxiomSkeleton.java
HelloWorldAxiomSkeletonInterface.java
./build/service/src/org/danlley/util/service/xsd/ExtensionMapper.java
GetHelloMessage.java
GetHelloMessageFault.java
GetHelloMessageResponse.java
GetMoreMessage.java
GetMoreMessageFault.java
GetMoreMessageResponse.java
--------------------------------------------------------------------------------
3.分析框架结构
Axis·2的服务确实够周到的,不仅仅给我们把整个服务的框架都搭建好了,而且,还给我们顺便连编译工程所需用的Ant脚本都生成好了。真是不得不让人感叹一句"Apache办事,我放心!"呵呵呵。
让我们先大体看看生成的这些Java代码的作用,GetHelloMessageFaultException和GetMoreMessageFaultException是用来做异常处理的。关于这个话题我以纪在以前的专题中已经有过提及(也就是跟Fault相关的话题)。
说到Fault就不得不再提提SOAP 处理模型,Axis2 体系结构定义了两个管道(或流),分别称为 InPipe (InFlow) 和 OutPipe (OutFlow),用于处理服务器端的请求消息和响应消息。在客户端,这两个管道是反向的——换句话说,SOAP 请求消息流经 OutPipe,而响应消息流经 InPipe。管道或流包含一系列分为阶段的处理程序。除预先定义的阶段和处理程序集外,用户还可以在操作级别、服务级别或全局级别配置用户阶段和相关处理程序。处理程序充当 SOAP 消息的拦截器,可以处理 SOAP 消息的 Header 或 Body。InPipe 是通过以下阶段进行配置的:
--------------------------------------------------------------------------------
TransportIn
PreDispatch
Dispatch
PostDispatch
PolicyDetermination
User phases
Message validation
--------------------------------------------------------------------------------
请求消息在通过 Inpipe 中配置的所有阶段后,到达 MessageReceiver,然后由 MessageReceiver 调用实际服务实现。服务器的 OutPipe 包含以下阶段:
--------------------------------------------------------------------------------
Message initialization
Policy determination
User phases
MessageOut
--------------------------------------------------------------------------------
用户配置的阶段位于这两个管道的用户阶段(User phases) 部分。如果在执行这些管道的过程中发生错误,则这些错误将通过 InFaultPipe 或 OutFaultPipe 管道。收到 Fault 消息后,在客户端调用 InFaultPipe;如果某个调用导致将错误发送到客户端,则在服务器端调用 OutFaultPipe。用户可以将处理程序添加到预先定义的阶段,并且按照这些处理程序运行的顺序进行配置。
那么既然ADB pattern为我们提供了GetHelloMessageFaultException、GetMoreMessageFaultException、GetHelloMessageFault和GetMoreMessageFault类。那也就意味着我们可以对这些类进行扩充,以满足我们在实际当中的应用需求。由于我们Axiom的专题中举例时,两个实例均采用了in-Out模式,因此通过此工程的WSDL生成的ADB框架也就只有HelloWorldAxiomMessageReceiverInOut类来处理In-Out模式。GetHelloMessage和GetMoreMessage用来对接口HelloWorldAxiomSkeletonInterface的收取的数据进行封装,而GetHelloMessageResponse和GetMoreMessageResponse类则用于封装由HelloWorldAxiomSkeleton类处理后的结果。也就是说,真正的服务提供者就是HelloWorldAxiomSkeleton类。现在思路已经整理清楚,ADB生成的框架也基本上相当清楚了。那么剩下就是为我们新生成的框架动点小外科手术的时候了。
4.构建工程
根据我个人喜好,我的工程目录结构整理后如下:
--------------------------------------------------------------------------------
./build.xml
./resources/HelloWorldAxiom.wsdl
services.xml
./src/main/java/org/danlley/service/adb/GetHelloMessageFaultException.java
GetMoreMessageFaultException.java
HelloWorldAxiomMessageReceiverInOut.java
HelloWorldAxiomSkeleton.java
HelloWorldAxiomSkeletonInterface.java
./src/main/java/org/danlley/util/service/xsd/ExtensionMapper.java
GetHelloMessage.java
GetHelloMessageFault.java
GetHelloMessageResponse.java
GetMoreMessage.java
GetMoreMessageFault.java
GetMoreMessageResponse.java
--------------------------------------------------------------------------------
工程目录改变也就意味着我们需要修改Ant脚本,修改后的脚步如下: