在Axis2对Web Services的众多实现方式中,POJOs方式很明显是最简单的一种了。对于Axis2的相关配置,由于我在此前专题(
http://danlley.iteye.com/blog/101975)中已经进行过相关的说明,因此,这里我就不再重复阐述了。
为了能够很快进入状态,我们立即开始一个简单的工程,用来说明POJOs的发布和使用,该例子程序用于完成一个简单的更新和查询操作。
定义服务类
xml 代码
- package samples.quickstart.service.pojo;
- import java.util.HashMap;
- public class StockQuoteService {
- private HashMap map = new HashMap();
- public double getPrice(String symbol) {
- Double price = (Double) map.get(symbol);
- if(price != null){
- return price.doubleValue();
- }
- return 42.00;
- }
- public void update(String symbol, double price) {
- map.put(symbol, new Double(price));
- }
- }
给工程编写Ant脚本:
xml 代码
- <project basedir="." default="generate.service">
- <property name="build.dir" value="build" />
- <target name="compile.service">
- <mkdir dir="${build.dir}" />
- <mkdir dir="${build.dir}/classes" />
- <javac debug="on" fork="true" destdir="${build.dir}/classes" srcdir="${basedir}/src/main/java">
- javac>
- target>
- <target name="generate.service" depends="compile.service">
- <copy toDir="${build.dir}/classes" failonerror="false">
- <fileset dir="${basedir}/src/main/resources">
- <include name="**/*.xml" />
- fileset>
- copy>
- <jar destfile="${build.dir}/StockQuoteService.aar">
- <fileset excludes="**/Test.class" dir="${build.dir}/classes" />
- jar>
- target>
- project>
从Ant脚本的配置可以看出我们的工程相关配置:
工程源代码路径:src/main/java
资源文件路径:src/main/resources
编译路径:build
在src/main/resources路径下新建一个META-INF路径,在该路径下定义services.xml,内容如下:
xml 代码
- <service name="StockQuoteService" scope="application" targetNamespace="http://quickstart.samples/">
- <description>Stock Quote Servicedescription>
- <messageReceivers>
- <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-only"
- class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver"/>
- <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out"
- class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
- messageReceivers>
- <schema schemaNamespace="http://quickstart.samples/xsd"/>
- <parameter name="ServiceClass">samples.quickstart.service.pojo.StockQuoteServiceparameter>
- service>
这样所有的事情都已经准备好了,好像没有引用AXIS2的资源文件呀!?需要吗!呵呵呵呵,当然不需要!谁让我是POJOs呢。
从上面的配置可以看出,工程中除了多出一个services.xml文件外,工程几乎与普通工程没什么两样。这也是POJOs中很值得称道的一点——简单!services.xml中对MEP(Message Exchange Pattern)的声明中也是格外的粗粒度。它笼统的告诉Web Services容器,我这里的方法需要支持in模式和in-out模式两种方式,至于是哪个方法支持哪一种模式,我不告诉你,自己去猜吧。呵呵呵呵。我只告诉你,我的ServiceClass是samples.quickstart.service.pojo.StockQuoteService
我需要在这里做一点申明:services.xml的粗粒度声明,纯粹属于我个人的“偷懒”行为,而实际上在实际的应用当中,为了明确期间,一般是不会采取我这种处理方式的。通常都需要对每个方法说明MEP方式
很明显Axis2最后需要的发布文件是一个
aar包。但是我要说明的一点就是,我们这里的aar包的包名必须与ServiceClass的名称(在我们这个工程当中,也就是StockQuoteService)完全一致(包括大小写)。
在工程根目录下打开命令行运行ant脚本(前提是你已经配置了Ant环境变量),执行结果如下:
D:\eclipse\workspace\axis2pojoslab>ant
Buildfile: build.xml
Buildfile: build.xml
compile.service:
[mkdir] Created dir: D:\eclipse\workspace\axis2pojoslab\build
[mkdir] Created dir: D:\eclipse\workspace\axis2pojoslab\build\classes
[javac] Compiling 1 source file to D:\eclipse\workspace\axis2pojoslab\build\
classes
[javac] 注意: D:\eclipse\workspace\axis2pojoslab\src\main\java\samples\quic
kstart\service\pojo\StockQuoteService.java 使用了未经检查或不安全的操作。
[javac] 注意: 要了解详细信息,请使用 -Xlint:unchecked 重新编译。
[mkdir] Created dir: D:\eclipse\workspace\axis2pojoslab\build
[mkdir] Created dir: D:\eclipse\workspace\axis2pojoslab\build\classes
[javac] Compiling 1 source file to D:\eclipse\workspace\axis2pojoslab\build\
classes
[javac] 注意: D:\eclipse\workspace\axis2pojoslab\src\main\java\samples\quic
kstart\service\pojo\StockQuoteService.java 使用了未经检查或不安全的操作。
[javac] 注意: 要了解详细信息,请使用 -Xlint:unchecked 重新编译。
generate.service:
[copy] Copying 1 file to D:\eclipse\workspace\axis2pojoslab\build\classes
[jar] Building jar: D:\eclipse\workspace\axis2pojoslab\build\StockQuoteSer
vice.aar
[copy] Copying 1 file to D:\eclipse\workspace\axis2pojoslab\build\classes
[jar] Building jar: D:\eclipse\workspace\axis2pojoslab\build\StockQuoteSer
vice.aar
BUILD SUCCESSFUL
Total time: 2 seconds
Total time: 2 seconds
这时,在工程的build路径下就会出现已经打包成功的aar包:StockQuoteService.aar。打开此aar包,看看META-INF路径,是否在该路径存在services.xml。确定存在后将其copy到服务器中,本人用的是tomcat6:D:\tomcat6\webapps\axis2\WEB-INF\services启动服务!在IE中访问以下地址:
http://localhost/axis2/services/StockQuoteService?wsdl
我们得到以下内容:
xml 代码
- <wsdl:definitions xmlns:axis2="http://quickstart.samples/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:ns0="http://quickstart.samples/xsd" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:ns1="http://org.apache.axis2/xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://quickstart.samples/">
- <wsdl:documentation>Stock Quote Servicewsdl:documentation>
- - <wsdl:types>
- - <xs:schema xmlns:ns="http://quickstart.samples/xsd" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://quickstart.samples/xsd">
- - <xs:element name="getPrice">
- - <xs:complexType>
- - <xs:sequence>
- <xs:element name="symbol" nillable="true" type="xs:string" />
- xs:sequence>
- xs:complexType>
- xs:element>
- - <xs:element name="getPriceResponse">
- - <xs:complexType>
- - <xs:sequence>
- <xs:element name="return" nillable="true" type="xs:double" />
- xs:sequence>
- xs:complexType>
- xs:element>
- - <xs:element name="update">
- - <xs:complexType>
- - <xs:sequence>
- <xs:element name="symbol" nillable="true" type="xs:string" />
- <xs:element name="price" nillable="true" type="xs:double" />
- xs:sequence>
- xs:complexType>
- xs:element>
- xs:schema>
- wsdl:types>
- - <wsdl:message name="updateMessage">
- <wsdl:part name="part1" element="ns0:update" />
- wsdl:message>
- - <wsdl:message name="getPriceMessage">
- <wsdl:part name="part1" element="ns0:getPrice" />
- wsdl:message>
- - <wsdl:message name="getPriceResponse">
- <wsdl:part name="part1" element="ns0:getPriceResponse" />
- wsdl:message>
- - <wsdl:portType name="StockQuoteServicePortType">
- - <wsdl:operation name="update">
- <wsdl:input xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" message="axis2:updateMessage" wsaw:Action="urn:update" />
- wsdl:operation>
- - <wsdl:operation name="getPrice">
- <wsdl:input xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" message="axis2:getPriceMessage" wsaw:Action="urn:getPrice" />
- <wsdl:output message="axis2:getPriceResponse" />
- wsdl:operation>
- wsdl:portType>
- - <wsdl:binding name="StockQuoteServiceSOAP11Binding" type="axis2:StockQuoteServicePortType">
- <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" />
- - <wsdl:operation name="update">
- <soap:operation soapAction="urn:update" style="document" />
- - <wsdl:input>
- <soap:body use="literal" />
- wsdl:input>
- wsdl:operation>
- - <wsdl:operation name="getPrice">
- <soap:operation soapAction="urn:getPrice" style="document" />
- - <wsdl:input>
- <soap:body use="literal" />
- wsdl:input>
- - <wsdl:output>
- <soap:body use="literal" />
- wsdl:output>
- wsdl:operation>
- wsdl:binding>
- - <wsdl:binding name="StockQuoteServiceSOAP12Binding" type="axis2:StockQuoteServicePortType">
- <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" />
- - <wsdl:operation name="update">
- <soap12:operation soapAction="urn:update" style="document" />
- - <wsdl:input>
- <soap12:body use="literal" />
- wsdl:input>
- wsdl:operation>
- - <wsdl:operation name="getPrice">
- <soap12:operation soapAction="urn:getPrice" style="document" />
- - <wsdl:input>
- <soap12:body use="literal" />
- wsdl:input>
- - <wsdl:output>
- <soap12:body use="literal" />
- wsdl:output>
- wsdl:operation>
- wsdl:binding>
- - <wsdl:binding name="StockQuoteServiceHttpBinding" type="axis2:StockQuoteServicePortType">
- <http:binding verb="POST" />
- - <wsdl:operation name="update">
- <http:operation location="update" />
- - <wsdl:input>
- <mime:content type="text/xml" />
- wsdl:input>
- wsdl:operation>
- - <wsdl:operation name="getPrice">
- <http:operation location="getPrice" />
- - <wsdl:input>
- <mime:content type="text/xml" />
- wsdl:input>
- - <wsdl:output>
- <mime:content type="text/xml" />
- wsdl:output>
- wsdl:operation>
- wsdl:binding>
- - <wsdl:service name="StockQuoteService">
- - <wsdl:port name="StockQuoteServiceSOAP11port_http" binding="axis2:StockQuoteServiceSOAP11Binding">
- <soap:address location="http://localhost:80/axis2/services/StockQuoteService" />
- wsdl:port>
- - <wsdl:port name="StockQuoteServiceSOAP12port_http" binding="axis2:StockQuoteServiceSOAP12Binding">
- <soap12:address location="http://localhost:80/axis2/services/StockQuoteService" />
- wsdl:port>
- - <wsdl:port name="StockQuoteServiceHttpport1" binding="axis2:StockQuoteServiceHttpBinding">
- <http:address location="http://localhost:80/axis2/rest/StockQuoteService" />
- wsdl:port>
- wsdl:service>
- wsdl:definitions>
这就是大名鼎鼎的WSDL了,我们当初没有定义这个文件的原因就是容器在运行过程中会自动根据你的services.xml中的配置信息生成我们所必需的WSDL。
任何信息人们总会要求他详细点,然后可以了解更多,但是有时候详细也会带来很多不便,到目前为止,我看到WSDL的时候还是有点晕,呵呵呵呵,尤其是当其中的方法较多的情况下,简直能够让人崩溃。怎么办?访问这个地址吧:
http://localhost/axis2/services/StockQuoteService?xsd
(tomcat在默认情况下的端口为8080,本人一向比较懒惰为了访问时少输入点东西在地址栏,我把端口改成了80)
xml 代码
- <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:axis2="http://quickstart.samples/" xmlns:ns="http://quickstart.samples/xsd" xmlns:ns0="http://quickstart.samples/xsd" xmlns:ns1="http://org.apache.axis2/xsd" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://quickstart.samples/xsd">
- <xs:element name="getPrice">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="symbol" nillable="true" type="xs:string" />
- xs:sequence>
- xs:complexType>
- xs:element>
- <xs:element name="getPriceResponse">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="return" nillable="true" type="xs:double" />
- xs:sequence>
- xs:complexType>
- xs:element>
- <xs:element name="update">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="symbol" nillable="true" type="xs:string" />
- <xs:element name="price" nillable="true" type="xs:double" />
- xs:sequence>
- xs:complexType>
- xs:element>
- xs:schema>
这些信息已经足够满足我们编写客户端程序的需要了。其中的
symbol是我们在调用
getPrice过程中需要传入的参数,而
return是返回的参数。由于
update方法不需要返回值,因此只有传入的参数
symbol和
price。这些信息是我们在下面的操作中都需要用到的。
不过在这个例子中,我们甚至根本就不需要编写客户端程序。仅仅通过访问就可以执行服务提供的接口。
xml 代码
- <ns:getPriceResponse xmlns:ns="http://quickstart.samples/xsd">
- <ns:return>42.0ns:return>
- ns:getPriceResponse>
这个是我们的程序在没有任何数据的情况下返回的默认值。
接下来让我们来更新数据:
你会发现执行完后没有任何反应,没关系让我们继续回过来在访问地址
http://localhost/axis2/rest/StockQuoteService/getPrice?symbol=danlley
xml 代码
- <ns:getPriceResponse xmlns:ns="http://quickstart.samples/xsd">
- <ns:return>100.0ns:return>
- ns:getPriceResponse>
是不是数据已经成功得到修改了?!