[b]Axis2快速应用指南[/b]
http://tech.surfcareer.com/axis2/quickstartguide.html#introduction
这片指南的目的是让你尽可能快的开始用Axis2建立服务和客户端。我们将学习一个简单的“StockQuote”服务,并向你展示用不同的方法来建立和部署他,也会看一下Axis2带来的一到两个功能。接下来我们可以看到建立客户端来访问这些服务。
目录介绍
开始
Axis2服务
建立服务
部署POJOs
用AXIOM创建服务
用ADB生成服务
用XML Beans生成服务
用JiBX生成服务
生成客户端
用AXIOM建立客户端
用ADB生成客户端
用XML Beans生成客户端
用JiBX生成客户端
小结
进一步的学习
快速安装笔记:
--------------------------------------------------------------------------------
文档中的代码可以在被解开的标准二进制发行包中找到, 更具体的说是在Axis2_HOME/samples/下的quickstart, quickstartadb, quickstartaxiom, quickstartjibx和quickstartxmlbeans目录中。(考虑现在就获得它对你后面的学习是有益的。)代码包括了Ant创建文件(build.xml),我们将在学习的例子中使用这种文件,它使编译更方便。
介绍
让我们从服务本身开始。我们将使之简化,以使你可以看到在搭建和部署服务时到底发生了什么?一个“StockQuoteService”的例子在类似的场合是必须的,所以让我们使用下面的代码(参见代码列表1)。代码列表1:StockQuoteService类
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));
}
}
它是一个有两个可能调用的服务。一个是输入/输出消息,另一个是只读服务。最后,我们将会把这个服务压缩打包,然后用四种不同的方法来部署它。首先,让我们看一下这个简单的Java类是怎么关联到一个服务的。
开始
在用Axis2搭建任何东西前,我们必须关心一些小家务。首先,你要准备好Axis2的工作环境。幸运的是,它只是涉及到一些简单的步骤:
下载安装Java(最低JDK 1.4)。将JAVA_HOME环境变量设置到你安装JDK发行包的目录路径。
下载Axis2,并解压到一个目标目录。
复制axis2.war文件到你Servlet引擎的webapps目录。
将AXIS2_HOME环境变量指向步骤2中的目标目录。注意,Axis2所有的脚本和搭建文件依赖这个值,所以不要跳过这一步。Linux用户也可以运行AXIS2_HOME/bin目录下的setenv.sh文件,这样就可以将AXIS2_HOME环境变量设置到Axis2的解压目录路径。
在大多数情况下,我们的服务也需要一个WSDL文件。Axis2的Java2WSDL可以用来产生一个WSDL。从一个Java类生成一个WSDL文件,执行一下步骤:
建立并编译Java类。
用这个命令生成WSDL: %AXIS2_HOME%/bin/java2wsdl -cp . -cn samples.quickstart.service.pojo.StockQuoteService -of StockQuoteService.wsdl
一旦你生成了WSDL文件,你可以做你需要的修改。例如,你可以加入你的定制错误或者改变生成的元素名称。例如:这个StockQuoteService.wsdl 文件存放在%AXIS2_HOME%/samples/quickstartadb/resources/META-INF 文件夹中,我们会在整个文档中使用它,替换那些用生成程序建立的普通参数。
Axis2服务
在我们搭建前,理解完成成果是什么样的是很有帮助的。Axis2的服务端可以在任何Servlet引擎上部署,它的结构如下面的代码列表2所示。代码列表2:axis2.war的目录结构
axis2-web
META-INF
WEB-INF
classes
conf
axis2.xml
lib
activation.jar
...
xmlSchema.jar
modules
modules.list
addressing.mar
...
soapmonitor.mar
services
services.list
aservice.aar
...
version.aar
web.xml
从最上面开始,axis2-web是组成管理员应用的JSP文件集合,通过它你可以执行诸如添加服务和生效或者撤销模块。WEB-INF目录包含了实际的Java类和其他支持文件,用它们来运行任何部署到服务目录的服务。这其中最主要的是axis2.xml,它控制应用程序如何处理接收到的消息,决定Axis2是否需要用模块目录中定义的模块。象你在这里看到的一样,服务可以用aar后缀的文件来部署,但是它们的内容必须按照特定的方式安排。例如,服务结构如下:
- StockQuoteService
- META-INF
- services.xml
- lib
- samples
- quickstart
- service
- pojo
- StockQuoteService.class
这里,服务名称是StockQuoteService,它是在services.xml文件中指定以及和这个服务的顶层文件夹相对应。编译过的Java类根据包的名字被放在这个目录下的合适位置。除了已经放在Axis2 WAR文件中和Servlet容器common JAR目录下的,lib目录包含了运行这个服务所需要的特定的JAR文件(本例中没有)。最后,META-INF目录包含了其他关于Axis2需要正确执行这个服务的信息。services.xml文件定义了服务本身并且将Java类链接到服务上来(参见代码列表3)。代码列表3:服务定义文件
<service name="StockQuoteService" scope="application">
<description>
Stock Quote Sample Service
</description>
<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>
<parameter name="ServiceClass">
samples.quickstart.service.pojo.StockQuoteService
</parameter>
</service>
在这里,根据messageReceiver中不同消息交换模式的相关类型,定义了服务。META-INF目录也是你想放置在此应用中任何客户化WSDL文件的位置。你可以通过复制这个简单文件层次结构到你Servlet引擎的webapps/axis2/WEB-INF/services目录来部署这个服务。(注意,Axis2 WAR必须先安装在Servlet引擎中。)这就是分解模式。你也可以将你文档压缩为一个类似jar文件的aar文件,直接把这个aar文件放到Servlet引擎的webapps/axis2/WEB-INF/services目录下。现在你知道我们要完成什么了,我们就要准备开始搭建了。首先,下载并解压合适的Axis2标准二进制发行包。确认你把AXIS2_HOME变量值设置为你解压这个发行包的目录路径。让我们看一些建立客户端和服务的不同方法。
建立服务
在这一部分里,我们将看到用五种方法来创建基于StockQuoteService类的服务:部署Plain Old Java Objects (POJO),用AXIOM's OMElement 搭建服务,用Axis2 Databinding Framework (ADB)生成服务,用XMLBeans 生成服务,用JiBX生成服务。
部署POJOs
--------------------------------------------------------------------------------
要用POJOs(Plain Old Java Objects)部署服务,执行以下步骤。
注意<AXIS2_HOME>/samples/quickstart 中的目录结构(services.xml可以参见本文的第一部分):
- quickstart
- README.txt
- build.xml
- resources
- META-INF
- services.xml
- src
- samples
- quickstart
- service
- pojo
- StockQuoteService.java
注意你可以在quickstart目录下通过输入以下命令来生成一个WSDL文件:
ant generate.wsdl
然而,创建StockQuoteService.wsdl是可选的。它可以是从Java类直接生成的版本,也可以是这个文件的一个定制版本,而且,和前面文档中引用的services.xml是同一个文件。
现在在quickstart目录下输入ant generate.service,这样就能创建如下目录结构:
- quickstart/build/classes
- META-INF
- services.xml
- samples
- quickstart
- service
- pojo
- StockQuoteService.class
如果你想要在一个分解开的目录格式下部署服务,将classes目录更名为,并把它复制到你的Servlet引擎的webapps/axis2/WEB-INF/services 目录。否则,复制build/StockQuoteService.aar文件到你Servlet引擎的webapps/axis2/WEB-INF/services目录。要检查确认服务被正确部署,可以访问服务列表:
http://localhost:8080/axis2/services/listServices你也可以检验WSDL文件:
http://localhost:8080/axis2/services/StockQuoteService?wsdl检验Schema:
http://localhost:8080/axis2/services/StockQuoteService?xsd一旦这些URL工作正常,马上测试这个服务。试着在浏览器中输入以下URL:
http://localhost:8080/axis2/services/StockQuoteService/getPrice?symbol=IBM你将得到以下反馈:
<ns:getPriceResponse xmlns:ns="http://pojo.service.quickstart.samples/xsd"><ns:return>42</ns:return></ns:getPriceResponse>如果你象下面这样调用update方法,
http://localhost:8080/axis2/services/StockQuoteService/update?symbol=IBM&price=100然后运行前面的getPrice URL,你将看到价格变化了。
用AXIOM搭建服务
--------------------------------------------------------------------------------
要使用AXIOM从头建立服务,执行以下步骤。
注意包含在/samples/quickstartaxiom 下的目录结构:
- quickstartaxiom
- README.txt
- build.xml
- resources
- META-INF
- services.xml
- StockQuoteService.wsdl
- src
- samples
- quickstart
- service
- axiom
- StockQuoteService.java
- clients
- AXIOMClient.java
因为AXIOM有一点不同,你需要一个与POJO中使用的不同的services.xml文件。像代码列表4中所示定义这个文件。
代码列表4:服务定义文件。
<service name="StockQuoteService" scope="application">
<description>
Stock Quote Service
</description>
<operation name="getPrice">
<messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/>
</operation>
<operation name="update">
<messageReceiver class="org.apache.axis2.receivers.RawXMLINOnlyMessageReceiver"/>
</operation>
<parameter name="ServiceClass">samples.quickstart.service.axiom.StockQuoteService</parameter>
</service>
注意大部分是一样的,除了在services.xml文件中明确定义的操作,以及现在的MessageReceivers用的是RawXML。
现在,在上面引用的StockQuoteService.java类在代码列表5中定义,这个类使用了来自Axis2库中的类。
代码列表类5:使用AXIOM的StockQuoteService类
package samples.quickstart.service.axiom;
import javax.xml.stream.XMLStreamException;
import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNamespace;
import java.util.HashMap;
public class StockQuoteService {
private HashMap map = new HashMap();
public OMElement getPrice(OMElement element) throws XMLStreamException {
element.build();
element.detach();
OMElement symbolElement = element.getFirstElement();
String symbol = symbolElement.getText();
String returnText = "42";
Double price = (Double) map.get(symbol);
if(price != null){
returnText = "" + price.doubleValue();
}
OMFactory fac = OMAbstractFactory.getOMFactory();
OMNamespace omNs =
fac.createOMNamespace("http://axiom.service.quickstart.samples/xsd", "tns");
OMElement method = fac.createOMElement("getPriceResponse", omNs);
OMElement value = fac.createOMElement("price", omNs);
value.addChild(fac.createOMText(value, returnText));
method.addChild(value);
return method;
}
public void update(OMElement element) throws XMLStreamException {
element.build();
element.detach();
OMElement symbolElement = element.getFirstElement();
String symbol = symbolElement.getText();
OMElement priceElement = (OMElement)symbolElement.getNextOMSibling();
String price = priceElement.getText();
map.put(symbol, new Double(price));
}
}
Axis2使用AXIOM,或者说AXIs对象模型,是一个基于StAX API(Streaming API for XML)接口的类DOM(Document Object Model)结构。作为服务的方法必须接受一个OMElement作为它的参数,OMElement代表一个XML Element,在这个例子中,它碰巧是一个输入SOAP消息承载的内容。例如,方法getPrice(OMElement)解开负载的第一个子参数的内容,它代表了股票代号,并用这个代号来查询这个股票的当前价格。除非这是一个“纯输入”服务,这个方法必须返回一个OMElement,因为它会变成返回SOAP消息的承载内容。
现在在Axis2_HOME/samples/quickstartaxiom 目录中输入ant generate.service来搭建项目。
将StockQuoteService.aar文件放到Servlet引擎的webapps/axis2/WEB-INF/services 目录下,要检查确认服务被正确部署,可以访问服务列表,
http://localhost:8080/axis2/services/listServices你还可以检查定制的WSDL,
http://localhost:8080/axis2/services/StockQuoteService?wsdl和schema,
http://localhost:8080/axis2/services/StockQuoteService?xsd
用ADB生成服务
--------------------------------------------------------------------------------
要用Axis2 Databinding Framework(ADB)生成和部署服务,执行以下步骤。
在Axis2_HOME/samples/quickstartadb目录下输入下列命令,就可以用WSDL2Java功能生成主要框架:
%AXIS2_HOME%/bin/WSDL2Java -uri resources/META-INF/StockQuoteService.wsdl -p samples.quickstart.service.adb -d adb -s -ss -sd -ssi -o build/service或者在Axis2_HOME/samples/quickstartadb 目录下简单输入ant generate.service也可以。
选项-d adb指定了Axis Data Binding (ADB) 。-s开关指定了同步还是阻塞方式。-ss开关建立了服务端代码(框架和相关文件)。-sd开关建立了一个服务描述(services.xml file)。-ssi开关建立了服务框架的接口。服务文件现在应该位于build/service目录。
如果你直接用WSDL2Java生成代码,下一步你不得不为了实现服务而修改生成的框架(如果你用了“ant generate.service”,一个完整的框架将会覆盖自动生成的那个代码)。
打开并修改文件 build/service/src/samples/quickstart/adb/service/StockQuoteServiceSkeleton.java,加入你服务的功能到生成方法中,如代码列表6所示。
代码列表6:定义服务框架文件
package samples.quickstart.service.adb;
import samples.quickstart.service.adb.xsd.GetPriceResponse;
import samples.quickstart.service.adb.xsd.Update;
import samples.quickstart.service.adb.xsd.GetPrice;
import java.util.HashMap;
public class StockQuoteServiceSkeleton {
private static HashMap map;
static{ map = new HashMap(); }
public void update(Update param0) {
map.put(param0.getSymbol(), new Double(param0.getPrice()));
}
public GetPriceResponse getPrice(GetPrice param1) {
Double price = (Double) map.get(param1.getSymbol());
double ret = 42;
if(price != null){
ret = price.doubleValue();
}
GetPriceResponse res =
new GetPriceResponse();
res.set_return(ret);
return res;
}
}
现在你可以在build/service 目录下输入下面的命令来搭建项目:
ant jar.server如果所有都运行正常,你将在窗口中看到BUILD SUCCESSFUL的消息,以及在build/service/build/lib目录中看到文件StockQuoteService.aar。复制这个文件到你Servlet引擎的webapps/axis2/WEB-INF/services目录下。
要检查确认服务被正确部署,可以访问服务列表,
http://localhost:8080/axis2/services/listServices你还可以检查定制的WSDL,
http://localhost:8080/axis2/services/StockQuoteService?wsdl和schema,
http://localhost:8080/axis2/services/StockQuoteService?xsd
用XMLBeans生成服务
--------------------------------------------------------------------------------
要使用XMLBeans生成一个服务,执行以下步骤。
在Axis2_HOME/samples/quickstartxmlbeans目录里输入以下命令,就可以用WSDL2Java功能生成框架。
%AXIS2_HOME%/bin/WSDL2Java -uri resources/META-INF/StockQuoteService.wsdl -p samples.quickstart.service.xmlbeans -d xmlbeans -s -ss -sd -ssi -o build/service或者在Axis2_HOME/samples/quickstartxmlbeans 下简单的打ant generate.service。
选项-d xmlbeans指定了XML Beans数据绑定。 -s开关指定了同步或者阻塞方式调用。-ss开关建立服务端代码(框架和相关文件)。-sd开关建立了一个服务描述(services.xml文件)。-ssi开关建立了服务框架的一个接口。现在在build/service目录下应该有服务文件了。
如果直接用WSDL2Java生成代码,接下来你不得不修改生成的框架来实现服务(如果你用“ant generate.service”,一个完整的框架将会覆盖自动生成的那个框架)。接下来打开build/service/src/samples/quickstart/service/xmlbeans/StockQuoteServiceSkeleton.java 文件,加入你的服务功能到生成的方法中(参见代码列表7)。
代码列表7:定义服务框架
package samples.quickstart.service.xmlbeans;
import samples.quickstart.service.xmlbeans.xsd.GetPriceDocument;
import samples.quickstart.service.xmlbeans.xsd.GetPriceResponseDocument;
import samples.quickstart.service.xmlbeans.xsd.UpdateDocument;
import java.util.HashMap;
public class StockQuoteServiceSkeleton implements StockQuoteServiceSkeletonInterface {
private static HashMap map;
static{ map = new HashMap(); }
public void update(UpdateDocument param0) {
map.put(param0.getUpdate().getSymbol(), new Double(param0.getUpdate().getPrice()));
}
public GetPriceResponseDocument getPrice(GetPriceDocument param1) {
Double price = (Double) map.get(param1.getGetPrice().getSymbol());
double ret = 42;
if(price != null){
ret = price.doubleValue();
}
System.err.println();
GetPriceResponseDocument resDoc =
GetPriceResponseDocument.Factory.newInstance();
GetPriceResponseDocument.GetPriceResponse res =
resDoc.addNewGetPriceResponse();
res.setReturn(ret);
return resDoc;
}
}
在build/service目录下输入下面的命令来搭建项目,这些命令包含在文件build.xml中:
ant jar.server如果一切运行正常,你将在你的窗口中看到BUILD SUCCESSFUL信息,以及在新建立的build/service/build/lib 目录下看到文件StockQuoteService.aar。把这个文件复制到Servlet引擎的the webapps/axis2/WEB-INF/services目录。
要检查确认服务被正确部署,可以访问服务列表,
http://localhost:8080/axis2/services/listServices你还可以检查定制的WSDL,
http://localhost:8080/axis2/services/StockQuoteService?wsdl和schema,
http://localhost:8080/axis2/services/StockQuoteService?xsd
用JiBX生成服务
--------------------------------------------------------------------------------
要用JiBX数据绑定生成和部署服务,执行以下步骤。
用一个控制台,并在Axis2_HOME/samples/quickstartjibx目录下输入以下命令就可以用WSDL2Java功能生成框架:
%AXIS2_HOME%/bin/wsdl2java -uri resources/META-INF/StockQuoteService.wsdl -p samples.quickstart.service.jibx -d jibx -s -ss -sd -ssi -uw -o build/service或者在Axis2_HOME/samples/quickstartjibx 目录下简单输入“ant generate.service”。
选项-d jibx指定了JiBX数据绑定。-s开关指定了同步还是阻塞方式调用。-ss开关建立服务端代码(框架和相关代码)。-sd开关建立了一个服务描述(service.xml文件)。-ssi开关建立了服务框架的一个接口。-uw开关解开传递给和获取自的服务操作的参数,这样可以建立一个更自然变成接口。
在运行WSDL2Java后,在build/service目录下应该有服务文件。如果你用WSDL2Java直接生成代码,你需要修改生成的框架来实现服务(如果你用“ant generate.service”,一个完整的框架将覆盖那个自动生成的框架)。打开并修改文件 build/service/src/samples/quickstart/service/jibx/StockQuoteServiceSkeleton.java,在生成的方法中添加你的服务功能,如代码列表8所示。
代码列表8:定义服务框架文件
package samples.quickstart.service.jibx;
import java.util.HashMap;
public class StockQuoteServiceSkeleton implements StockQuoteServiceSkeletonInterface {
private HashMap map = new HashMap();
public void update(String symbol, Double price) {
map.put(symbol, price);
}
public Double getPrice(String symbol) {
Double ret = (Double) map.get(symbol);
if (ret == null) {
ret = new Double(42.0);
}
return ret;
}
}
现在你可以在build/service目录下输入以下命令搭建项目:
ant jar.server如果一切运行正常,你将在你的框口中看到BUILD SUCCESSFUL信息,以及在build/service/build/lib目录中看到文件StockQuoteService.aar。复制这个文件到Servlet引擎的webapps/axis2/WEB-INF/services 目录。
要检查确认服务被正确部署,可以访问服务列表,
http://localhost:8080/axis2/services/listServices你还可以检查定制的WSDL,
http://localhost:8080/axis2/services/StockQuoteService?wsdl和schema,
http://localhost:8080/axis2/services/StockQuoteService?xsd要获得更多的关于在Axis2中使用JiBX的信息,参见JiBX代码生成集成细节。 你也可以检查JiBX Axis2 Wiki 网页,以获得关于Axis2中使用JiBX的更新信息。
生成客户端
在这一部分中,我们将看到四种方法来建立客户端,这个客户端基于StockQuoteService类:建立基于AXIOM的客户端,用Axis2数据绑定框架(ADB)生成一个客户端,用XMLBeans生成一个客户端,用JiBX生成客户端。
用AXIOM建立客户端
--------------------------------------------------------------------------------
用AXIOM建立客户端,执行下列步骤。
同样,注意在用AXIOM建立服务部分中的目录结构,下面完整的复制了一份。
- quickstartaxiom
- README.txt
- build.xml
- resources
- META-INF
- services.xml
- StockQuoteService.wsdl
- src
- samples
- quickstart
- service
- axiom
- StockQuoteService.java
- clients
- AXIOMClient.java
上面引用的AXIOMClient.java类如下代码列表9所示。
代码列表9:使用AXIOM的AXIOMClient类
package samples.quickstart.clients;
import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNamespace;
import org.apache.axis2.Constants;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.Options;
import org.apache.axis2.client.ServiceClient;
public class AXIOMClient {
private static EndpointReference targetEPR =
new EndpointReference("http://localhost:8080/axis2/services/StockQuoteService");
public static OMElement getPricePayload(String symbol) {
OMFactory fac = OMAbstractFactory.getOMFactory();
OMNamespace omNs = fac.createOMNamespace("http://axiom.service.quickstart.samples/xsd", "tns");
OMElement method = fac.createOMElement("getPrice", omNs);
OMElement value = fac.createOMElement("symbol", omNs);
value.addChild(fac.createOMText(value, symbol));
method.addChild(value);
return method;
}
public static OMElement updatePayload(String symbol, double price) {
OMFactory fac = OMAbstractFactory.getOMFactory();
OMNamespace omNs = fac.createOMNamespace("http://axiom.service.quickstart.samples/xsd", "tns");
OMElement method = fac.createOMElement("update", omNs);
OMElement value1 = fac.createOMElement("symbol", omNs);
value1.addChild(fac.createOMText(value1, symbol));
method.addChild(value1);
OMElement value2 = fac.createOMElement("price", omNs);
value2.addChild(fac.createOMText(value2,
Double.toString(price)));
method.addChild(value2);
return method;
}
public static void main(String[] args) {
try {
OMElement getPricePayload = getPricePayload("WSO");
OMElement updatePayload = updatePayload("WSO", 123.42);
Options options = new Options();
options.setTo(targetEPR);
options.setTransportInProtocol(Constants.TRANSPORT_HTTP);
ServiceClient sender = new ServiceClient();
sender.setOptions(options);
sender.fireAndForget(updatePayload);
System.err.println("price updated");
OMElement result = sender.sendReceive(getPricePayload);
String response = result.getFirstElement().getText();
System.err.println("Current price of WSO: " + response);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Axis2使用AXIOM,或者说AXIs对象模型,这是一个基于StAX API接口(Streaming API for XML)的类DOM(Document Object Model)结构。你在这里建立服务中的update和getPrice方法的具体内容。建立这些内容和你建立AXIOM服务中的getPriceResponse的方法是一样的。接下来你建立可选类,以及一个用来与服务通讯的ServiceClient。首先你调用update方法,这是一个不返回人和东西的fireAndForget方法。最后,你调用getPrice方法,从服务处获得当前价格并显示它们。
现在你可以建立和运行AXIOM客户端,在Axis2_HOME/samples/quickstartaxiom 中输入ant run.client。
你应该得到以下输出:
done
Current price of WSO: 123.42
用ADB建立一个客户端
--------------------------------------------------------------------------------
要用Axis数据绑定(ADB)建立客户端,执行下列步骤。
在Axis2_HOME/samples/quickstartadb 目录输入以下内容来产生客户端数据绑定:
%AXIS2_HOME%/bin/WSDL2Java -uri resources/META-INF/StockQuoteService.wsdl -p samples.quickstart.clients -d adb -s -o build/client或者在Axis2_HOME/samples/quickstartadb目录中简单的输入ant generate.client。
接下来看一下quickstartadb/src/samples/quickstart/clients/ADBClient.java, 看看它在代码列表10中是怎么被定义的。
代码列表10:ADBClient类
package samples.quickstart.clients;
import samples.quickstart.service.adb.StockQuoteServiceStub;
public class ADBClient{
public static void main(java.lang.String args[]){
try{
StockQuoteServiceStub stub =
new StockQuoteServiceStub
("http://localhost:8080/axis2/services/StockQuoteService");
getPrice(stub);
update(stub);
getPrice(stub);
} catch(Exception e){
e.printStackTrace();
System.err.println("\n\n\n");
}
}
/* fire and forget */
public static void update(StockQuoteServiceStub stub){
try{
StockQuoteServiceStub.Update req = new StockQuoteServiceStub.Update();
req.setSymbol ("ABC");
req.setPrice (42.35);
stub.update(req);
System.err.println("price updated");
} catch(Exception e){
e.printStackTrace();
System.err.println("\n\n\n");
}
}
/* two way call/receive */
public static void getPrice(StockQuoteServiceStub stub){
try{
StockQuoteServiceStub.GetPrice req = new StockQuoteServiceStub.GetPrice();
req.setSymbol("ABC");
StockQuoteServiceStub.GetPriceResponse res =
stub.getPrice(req);
System.err.println(res.get_return());
} catch(Exception e){
e.printStackTrace();
System.err.println("\n\n\n");
}
}
}
这个类用你建立的Axis数据绑定建立一个客户端功能组。接着它在Web Service上调用getPrice和update操作。getPrice方法建立一个GetPrice数据包并把symbol的值设为ABC。接着它发送请求并显示当前价格。Update方法建立了一个Update数据包,把symbol和price的值分别设为ABC和42.35。
现在搭建并运行客户端,在Axis2_HOME/samples/quickstartadb 目录下执行ant run.client。
你将得到以下的输出:
42
price updated
42.35
用XMLBeans生成客户端
--------------------------------------------------------------------------------
要用XML Beans数据绑定搭建一个客户端,执行以下步骤。
在xmlbeansClient目录里执行以下语句来产生数据绑定。
%AXIS2_HOME%/bin/WSDL2Java -uri resources/META-INF/StockQuoteService.wsdl -p samples.quickstart.service.xmlbeans -d xmlbeans -s -o build/client或者在Axis2_HOME/samples/quickstartxmlbeans 目录里简单的输入ant generate.client。
注意这样就建立了一个客户端功能组代码,它不包含服务端代码。
接着看一下quickstartxmlbeans/src/samples/quickstart/clients/XMLBEANSClient.java,看看它在代码列表11中匙如何定义的。
代码列表11:XMLBEANSClient类
package samples.quickstart.clients;
import samples.quickstart.service.xmlbeans.StockQuoteServiceStub;
import samples.quickstart.service.xmlbeans.xsd.GetPriceDocument;
import samples.quickstart.service.xmlbeans.xsd.GetPriceResponseDocument;
import samples.quickstart.service.xmlbeans.xsd.UpdateDocument;
public class XMLBEANSClient{
public static void main(java.lang.String args[]){
try{
StockQuoteServiceStub stub =
new StockQuoteServiceStub
("http://localhost:8080/axis2/services/StockQuoteService");
getPrice(stub);
update(stub);
getPrice(stub);
} catch(Exception e){
e.printStackTrace();
System.err.println("\n\n\n");
}
}
/* fire and forget */
public static void update(StockQuoteServiceStub stub){
try{
UpdateDocument reqDoc = UpdateDocument.Factory.newInstance();
UpdateDocument.Update req = reqDoc.addNewUpdate();
req.setSymbol ("BCD");
req.setPrice (42.32);
stub.update(reqDoc);
System.err.println("price updated");
} catch(Exception e){
e.printStackTrace();
System.err.println("\n\n\n");
}
}
/* two way call/receive */
public static void getPrice(StockQuoteServiceStub stub){
try{
GetPriceDocument reqDoc = GetPriceDocument.Factory.newInstance();
GetPriceDocument.GetPrice req = reqDoc.addNewGetPrice();
req.setSymbol("BCD");
GetPriceResponseDocument res =
stub.getPrice(reqDoc);
System.err.println(res.getGetPriceResponse().getReturn());
} catch(Exception e){
e.printStackTrace();
System.err.println("\n\n\n");
}
}
}
这个类用你建立的XML Beans数据绑定建立了一个客户端功能组。接着它在Web Service上调用getPrice和update操作。getPrice方法建立了GetPriceDocument实例,这是它的内部GetPrice类,并设置symbol的值为ABC。接着发送请求并接收到一个GetPriceResponseDocument实例显示当前价格。。update方法建立一个UpdateDocument实例,将symbol和price分别设置为ABC和42.32,在完成时显示‘done’。
现在搭建并运行项目,在Axis2_HOME/samples/quickstartxmlbeans 目录里输入ant run.client即可。
你将得到以下输出:
42
price updated
42.32
用JiBX生成客户端
--------------------------------------------------------------------------------
要用JiBX搭建客户端,执行以下步骤。
在Axis2_HOME/samples/quickstartjibx 目录中,打开一个控制台并输入以下内容,就可以生成客户端功能组。
%AXIS2_HOME%/bin/wsdl2java -uri resources/META-INF/StockQuoteService.wsdl -p samples.quickstart.clients -d jibx -s -uw -o build/client或者简单输入“ant generate.client”。
接下来看一下quickstartjibx/src/samples/quickstart/clients/JiBXClient.java,如下面的代码列表12所示。
代码列表12:JiBXClient类
package samples.quickstart.clients;
import samples.quickstart.service.jibx.StockQuoteServiceStub;
public class JiBXClient{
public static void main(java.lang.String args[]){
try{
StockQuoteServiceStub stub =
new StockQuoteServiceStub
("http://localhost:8080/axis2/services/StockQuoteService");
getPrice(stub);
update(stub);
getPrice(stub);
} catch(Exception e){
e.printStackTrace();
System.err.println("\n\n\n");
}
}
/* fire and forget */
public static void update(StockQuoteServiceStub stub){
try{
stub.update("CDE", new Double(42.35));
System.err.println("price updated");
} catch(Exception e){
e.printStackTrace();
System.err.println("\n\n\n");
}
}
/* two way call/receive */
public static void getPrice(StockQuoteServiceStub stub){
try{
System.err.println(stub.getPrice("CDE"));
} catch(Exception e){
e.printStackTrace();
System.err.println("\n\n\n");
}
}
}
这个类用JiBX客户端功能组在Web Service上访问getPrice和update操作。getPrice方法发送一个股票“ABC”的请求并显示价格。Update方法将股票“ABC”的值设为42.35。现在在Axis2_HOME/samples/quickstartjibx 目录里,打开一个控制台输入“ant run.client”,就能搭建和运行客户端了。
你将得到以下的输出:
42
price updated
42.35
要获得更多的关于在Axis2上使用JiBX的信息,参见JiBX代码生成集成的细节。
小结
Axis2为快速获取和运行web service,提供了一个平滑和健壮的方法。 这篇指南述说了在Axis2上部署服务的五种方法和建立与服务通讯客户端的四种方法。你现在有了可以用不同技术建立Web service的灵活性了。
进一步的学习
Apache Axis2 - http://ws.apache.org/axis2/
Axis2 体系结构 - http://ws.apache.org/axis2/1_0/Axis2ArchitectureGuide.html
Apache Axis2介绍 - http://www.redhat.com/magazine/021jul06/features/apache_axis2/
和Apache Axis2一起工作 - http://www.wso2.net/articles/axis2/java/2006/09/13/working-with-axis2
http://tech.surfcareer.com/axis2/quickstartguide.html#introduction
这片指南的目的是让你尽可能快的开始用Axis2建立服务和客户端。我们将学习一个简单的“StockQuote”服务,并向你展示用不同的方法来建立和部署他,也会看一下Axis2带来的一到两个功能。接下来我们可以看到建立客户端来访问这些服务。
目录介绍
开始
Axis2服务
建立服务
部署POJOs
用AXIOM创建服务
用ADB生成服务
用XML Beans生成服务
用JiBX生成服务
生成客户端
用AXIOM建立客户端
用ADB生成客户端
用XML Beans生成客户端
用JiBX生成客户端
小结
进一步的学习
快速安装笔记:
--------------------------------------------------------------------------------
文档中的代码可以在被解开的标准二进制发行包中找到, 更具体的说是在Axis2_HOME/samples/下的quickstart, quickstartadb, quickstartaxiom, quickstartjibx和quickstartxmlbeans目录中。(考虑现在就获得它对你后面的学习是有益的。)代码包括了Ant创建文件(build.xml),我们将在学习的例子中使用这种文件,它使编译更方便。
介绍
让我们从服务本身开始。我们将使之简化,以使你可以看到在搭建和部署服务时到底发生了什么?一个“StockQuoteService”的例子在类似的场合是必须的,所以让我们使用下面的代码(参见代码列表1)。代码列表1:StockQuoteService类
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));
}
}
它是一个有两个可能调用的服务。一个是输入/输出消息,另一个是只读服务。最后,我们将会把这个服务压缩打包,然后用四种不同的方法来部署它。首先,让我们看一下这个简单的Java类是怎么关联到一个服务的。
开始
在用Axis2搭建任何东西前,我们必须关心一些小家务。首先,你要准备好Axis2的工作环境。幸运的是,它只是涉及到一些简单的步骤:
下载安装Java(最低JDK 1.4)。将JAVA_HOME环境变量设置到你安装JDK发行包的目录路径。
下载Axis2,并解压到一个目标目录。
复制axis2.war文件到你Servlet引擎的webapps目录。
将AXIS2_HOME环境变量指向步骤2中的目标目录。注意,Axis2所有的脚本和搭建文件依赖这个值,所以不要跳过这一步。Linux用户也可以运行AXIS2_HOME/bin目录下的setenv.sh文件,这样就可以将AXIS2_HOME环境变量设置到Axis2的解压目录路径。
在大多数情况下,我们的服务也需要一个WSDL文件。Axis2的Java2WSDL可以用来产生一个WSDL。从一个Java类生成一个WSDL文件,执行一下步骤:
建立并编译Java类。
用这个命令生成WSDL: %AXIS2_HOME%/bin/java2wsdl -cp . -cn samples.quickstart.service.pojo.StockQuoteService -of StockQuoteService.wsdl
一旦你生成了WSDL文件,你可以做你需要的修改。例如,你可以加入你的定制错误或者改变生成的元素名称。例如:这个StockQuoteService.wsdl 文件存放在%AXIS2_HOME%/samples/quickstartadb/resources/META-INF 文件夹中,我们会在整个文档中使用它,替换那些用生成程序建立的普通参数。
Axis2服务
在我们搭建前,理解完成成果是什么样的是很有帮助的。Axis2的服务端可以在任何Servlet引擎上部署,它的结构如下面的代码列表2所示。代码列表2:axis2.war的目录结构
axis2-web
META-INF
WEB-INF
classes
conf
axis2.xml
lib
activation.jar
...
xmlSchema.jar
modules
modules.list
addressing.mar
...
soapmonitor.mar
services
services.list
aservice.aar
...
version.aar
web.xml
从最上面开始,axis2-web是组成管理员应用的JSP文件集合,通过它你可以执行诸如添加服务和生效或者撤销模块。WEB-INF目录包含了实际的Java类和其他支持文件,用它们来运行任何部署到服务目录的服务。这其中最主要的是axis2.xml,它控制应用程序如何处理接收到的消息,决定Axis2是否需要用模块目录中定义的模块。象你在这里看到的一样,服务可以用aar后缀的文件来部署,但是它们的内容必须按照特定的方式安排。例如,服务结构如下:
- StockQuoteService
- META-INF
- services.xml
- lib
- samples
- quickstart
- service
- pojo
- StockQuoteService.class
这里,服务名称是StockQuoteService,它是在services.xml文件中指定以及和这个服务的顶层文件夹相对应。编译过的Java类根据包的名字被放在这个目录下的合适位置。除了已经放在Axis2 WAR文件中和Servlet容器common JAR目录下的,lib目录包含了运行这个服务所需要的特定的JAR文件(本例中没有)。最后,META-INF目录包含了其他关于Axis2需要正确执行这个服务的信息。services.xml文件定义了服务本身并且将Java类链接到服务上来(参见代码列表3)。代码列表3:服务定义文件
<service name="StockQuoteService" scope="application">
<description>
Stock Quote Sample Service
</description>
<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>
<parameter name="ServiceClass">
samples.quickstart.service.pojo.StockQuoteService
</parameter>
</service>
在这里,根据messageReceiver中不同消息交换模式的相关类型,定义了服务。META-INF目录也是你想放置在此应用中任何客户化WSDL文件的位置。你可以通过复制这个简单文件层次结构到你Servlet引擎的webapps/axis2/WEB-INF/services目录来部署这个服务。(注意,Axis2 WAR必须先安装在Servlet引擎中。)这就是分解模式。你也可以将你文档压缩为一个类似jar文件的aar文件,直接把这个aar文件放到Servlet引擎的webapps/axis2/WEB-INF/services目录下。现在你知道我们要完成什么了,我们就要准备开始搭建了。首先,下载并解压合适的Axis2标准二进制发行包。确认你把AXIS2_HOME变量值设置为你解压这个发行包的目录路径。让我们看一些建立客户端和服务的不同方法。
建立服务
在这一部分里,我们将看到用五种方法来创建基于StockQuoteService类的服务:部署Plain Old Java Objects (POJO),用AXIOM's OMElement 搭建服务,用Axis2 Databinding Framework (ADB)生成服务,用XMLBeans 生成服务,用JiBX生成服务。
部署POJOs
--------------------------------------------------------------------------------
要用POJOs(Plain Old Java Objects)部署服务,执行以下步骤。
注意<AXIS2_HOME>/samples/quickstart 中的目录结构(services.xml可以参见本文的第一部分):
- quickstart
- README.txt
- build.xml
- resources
- META-INF
- services.xml
- src
- samples
- quickstart
- service
- pojo
- StockQuoteService.java
注意你可以在quickstart目录下通过输入以下命令来生成一个WSDL文件:
ant generate.wsdl
然而,创建StockQuoteService.wsdl是可选的。它可以是从Java类直接生成的版本,也可以是这个文件的一个定制版本,而且,和前面文档中引用的services.xml是同一个文件。
现在在quickstart目录下输入ant generate.service,这样就能创建如下目录结构:
- quickstart/build/classes
- META-INF
- services.xml
- samples
- quickstart
- service
- pojo
- StockQuoteService.class
如果你想要在一个分解开的目录格式下部署服务,将classes目录更名为,并把它复制到你的Servlet引擎的webapps/axis2/WEB-INF/services 目录。否则,复制build/StockQuoteService.aar文件到你Servlet引擎的webapps/axis2/WEB-INF/services目录。要检查确认服务被正确部署,可以访问服务列表:
http://localhost:8080/axis2/services/listServices你也可以检验WSDL文件:
http://localhost:8080/axis2/services/StockQuoteService?wsdl检验Schema:
http://localhost:8080/axis2/services/StockQuoteService?xsd一旦这些URL工作正常,马上测试这个服务。试着在浏览器中输入以下URL:
http://localhost:8080/axis2/services/StockQuoteService/getPrice?symbol=IBM你将得到以下反馈:
<ns:getPriceResponse xmlns:ns="http://pojo.service.quickstart.samples/xsd"><ns:return>42</ns:return></ns:getPriceResponse>如果你象下面这样调用update方法,
http://localhost:8080/axis2/services/StockQuoteService/update?symbol=IBM&price=100然后运行前面的getPrice URL,你将看到价格变化了。
用AXIOM搭建服务
--------------------------------------------------------------------------------
要使用AXIOM从头建立服务,执行以下步骤。
注意包含在/samples/quickstartaxiom 下的目录结构:
- quickstartaxiom
- README.txt
- build.xml
- resources
- META-INF
- services.xml
- StockQuoteService.wsdl
- src
- samples
- quickstart
- service
- axiom
- StockQuoteService.java
- clients
- AXIOMClient.java
因为AXIOM有一点不同,你需要一个与POJO中使用的不同的services.xml文件。像代码列表4中所示定义这个文件。
代码列表4:服务定义文件。
<service name="StockQuoteService" scope="application">
<description>
Stock Quote Service
</description>
<operation name="getPrice">
<messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/>
</operation>
<operation name="update">
<messageReceiver class="org.apache.axis2.receivers.RawXMLINOnlyMessageReceiver"/>
</operation>
<parameter name="ServiceClass">samples.quickstart.service.axiom.StockQuoteService</parameter>
</service>
注意大部分是一样的,除了在services.xml文件中明确定义的操作,以及现在的MessageReceivers用的是RawXML。
现在,在上面引用的StockQuoteService.java类在代码列表5中定义,这个类使用了来自Axis2库中的类。
代码列表类5:使用AXIOM的StockQuoteService类
package samples.quickstart.service.axiom;
import javax.xml.stream.XMLStreamException;
import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNamespace;
import java.util.HashMap;
public class StockQuoteService {
private HashMap map = new HashMap();
public OMElement getPrice(OMElement element) throws XMLStreamException {
element.build();
element.detach();
OMElement symbolElement = element.getFirstElement();
String symbol = symbolElement.getText();
String returnText = "42";
Double price = (Double) map.get(symbol);
if(price != null){
returnText = "" + price.doubleValue();
}
OMFactory fac = OMAbstractFactory.getOMFactory();
OMNamespace omNs =
fac.createOMNamespace("http://axiom.service.quickstart.samples/xsd", "tns");
OMElement method = fac.createOMElement("getPriceResponse", omNs);
OMElement value = fac.createOMElement("price", omNs);
value.addChild(fac.createOMText(value, returnText));
method.addChild(value);
return method;
}
public void update(OMElement element) throws XMLStreamException {
element.build();
element.detach();
OMElement symbolElement = element.getFirstElement();
String symbol = symbolElement.getText();
OMElement priceElement = (OMElement)symbolElement.getNextOMSibling();
String price = priceElement.getText();
map.put(symbol, new Double(price));
}
}
Axis2使用AXIOM,或者说AXIs对象模型,是一个基于StAX API(Streaming API for XML)接口的类DOM(Document Object Model)结构。作为服务的方法必须接受一个OMElement作为它的参数,OMElement代表一个XML Element,在这个例子中,它碰巧是一个输入SOAP消息承载的内容。例如,方法getPrice(OMElement)解开负载的第一个子参数的内容,它代表了股票代号,并用这个代号来查询这个股票的当前价格。除非这是一个“纯输入”服务,这个方法必须返回一个OMElement,因为它会变成返回SOAP消息的承载内容。
现在在Axis2_HOME/samples/quickstartaxiom 目录中输入ant generate.service来搭建项目。
将StockQuoteService.aar文件放到Servlet引擎的webapps/axis2/WEB-INF/services 目录下,要检查确认服务被正确部署,可以访问服务列表,
http://localhost:8080/axis2/services/listServices你还可以检查定制的WSDL,
http://localhost:8080/axis2/services/StockQuoteService?wsdl和schema,
http://localhost:8080/axis2/services/StockQuoteService?xsd
用ADB生成服务
--------------------------------------------------------------------------------
要用Axis2 Databinding Framework(ADB)生成和部署服务,执行以下步骤。
在Axis2_HOME/samples/quickstartadb目录下输入下列命令,就可以用WSDL2Java功能生成主要框架:
%AXIS2_HOME%/bin/WSDL2Java -uri resources/META-INF/StockQuoteService.wsdl -p samples.quickstart.service.adb -d adb -s -ss -sd -ssi -o build/service或者在Axis2_HOME/samples/quickstartadb 目录下简单输入ant generate.service也可以。
选项-d adb指定了Axis Data Binding (ADB) 。-s开关指定了同步还是阻塞方式。-ss开关建立了服务端代码(框架和相关文件)。-sd开关建立了一个服务描述(services.xml file)。-ssi开关建立了服务框架的接口。服务文件现在应该位于build/service目录。
如果你直接用WSDL2Java生成代码,下一步你不得不为了实现服务而修改生成的框架(如果你用了“ant generate.service”,一个完整的框架将会覆盖自动生成的那个代码)。
打开并修改文件 build/service/src/samples/quickstart/adb/service/StockQuoteServiceSkeleton.java,加入你服务的功能到生成方法中,如代码列表6所示。
代码列表6:定义服务框架文件
package samples.quickstart.service.adb;
import samples.quickstart.service.adb.xsd.GetPriceResponse;
import samples.quickstart.service.adb.xsd.Update;
import samples.quickstart.service.adb.xsd.GetPrice;
import java.util.HashMap;
public class StockQuoteServiceSkeleton {
private static HashMap map;
static{ map = new HashMap(); }
public void update(Update param0) {
map.put(param0.getSymbol(), new Double(param0.getPrice()));
}
public GetPriceResponse getPrice(GetPrice param1) {
Double price = (Double) map.get(param1.getSymbol());
double ret = 42;
if(price != null){
ret = price.doubleValue();
}
GetPriceResponse res =
new GetPriceResponse();
res.set_return(ret);
return res;
}
}
现在你可以在build/service 目录下输入下面的命令来搭建项目:
ant jar.server如果所有都运行正常,你将在窗口中看到BUILD SUCCESSFUL的消息,以及在build/service/build/lib目录中看到文件StockQuoteService.aar。复制这个文件到你Servlet引擎的webapps/axis2/WEB-INF/services目录下。
要检查确认服务被正确部署,可以访问服务列表,
http://localhost:8080/axis2/services/listServices你还可以检查定制的WSDL,
http://localhost:8080/axis2/services/StockQuoteService?wsdl和schema,
http://localhost:8080/axis2/services/StockQuoteService?xsd
用XMLBeans生成服务
--------------------------------------------------------------------------------
要使用XMLBeans生成一个服务,执行以下步骤。
在Axis2_HOME/samples/quickstartxmlbeans目录里输入以下命令,就可以用WSDL2Java功能生成框架。
%AXIS2_HOME%/bin/WSDL2Java -uri resources/META-INF/StockQuoteService.wsdl -p samples.quickstart.service.xmlbeans -d xmlbeans -s -ss -sd -ssi -o build/service或者在Axis2_HOME/samples/quickstartxmlbeans 下简单的打ant generate.service。
选项-d xmlbeans指定了XML Beans数据绑定。 -s开关指定了同步或者阻塞方式调用。-ss开关建立服务端代码(框架和相关文件)。-sd开关建立了一个服务描述(services.xml文件)。-ssi开关建立了服务框架的一个接口。现在在build/service目录下应该有服务文件了。
如果直接用WSDL2Java生成代码,接下来你不得不修改生成的框架来实现服务(如果你用“ant generate.service”,一个完整的框架将会覆盖自动生成的那个框架)。接下来打开build/service/src/samples/quickstart/service/xmlbeans/StockQuoteServiceSkeleton.java 文件,加入你的服务功能到生成的方法中(参见代码列表7)。
代码列表7:定义服务框架
package samples.quickstart.service.xmlbeans;
import samples.quickstart.service.xmlbeans.xsd.GetPriceDocument;
import samples.quickstart.service.xmlbeans.xsd.GetPriceResponseDocument;
import samples.quickstart.service.xmlbeans.xsd.UpdateDocument;
import java.util.HashMap;
public class StockQuoteServiceSkeleton implements StockQuoteServiceSkeletonInterface {
private static HashMap map;
static{ map = new HashMap(); }
public void update(UpdateDocument param0) {
map.put(param0.getUpdate().getSymbol(), new Double(param0.getUpdate().getPrice()));
}
public GetPriceResponseDocument getPrice(GetPriceDocument param1) {
Double price = (Double) map.get(param1.getGetPrice().getSymbol());
double ret = 42;
if(price != null){
ret = price.doubleValue();
}
System.err.println();
GetPriceResponseDocument resDoc =
GetPriceResponseDocument.Factory.newInstance();
GetPriceResponseDocument.GetPriceResponse res =
resDoc.addNewGetPriceResponse();
res.setReturn(ret);
return resDoc;
}
}
在build/service目录下输入下面的命令来搭建项目,这些命令包含在文件build.xml中:
ant jar.server如果一切运行正常,你将在你的窗口中看到BUILD SUCCESSFUL信息,以及在新建立的build/service/build/lib 目录下看到文件StockQuoteService.aar。把这个文件复制到Servlet引擎的the webapps/axis2/WEB-INF/services目录。
要检查确认服务被正确部署,可以访问服务列表,
http://localhost:8080/axis2/services/listServices你还可以检查定制的WSDL,
http://localhost:8080/axis2/services/StockQuoteService?wsdl和schema,
http://localhost:8080/axis2/services/StockQuoteService?xsd
用JiBX生成服务
--------------------------------------------------------------------------------
要用JiBX数据绑定生成和部署服务,执行以下步骤。
用一个控制台,并在Axis2_HOME/samples/quickstartjibx目录下输入以下命令就可以用WSDL2Java功能生成框架:
%AXIS2_HOME%/bin/wsdl2java -uri resources/META-INF/StockQuoteService.wsdl -p samples.quickstart.service.jibx -d jibx -s -ss -sd -ssi -uw -o build/service或者在Axis2_HOME/samples/quickstartjibx 目录下简单输入“ant generate.service”。
选项-d jibx指定了JiBX数据绑定。-s开关指定了同步还是阻塞方式调用。-ss开关建立服务端代码(框架和相关代码)。-sd开关建立了一个服务描述(service.xml文件)。-ssi开关建立了服务框架的一个接口。-uw开关解开传递给和获取自的服务操作的参数,这样可以建立一个更自然变成接口。
在运行WSDL2Java后,在build/service目录下应该有服务文件。如果你用WSDL2Java直接生成代码,你需要修改生成的框架来实现服务(如果你用“ant generate.service”,一个完整的框架将覆盖那个自动生成的框架)。打开并修改文件 build/service/src/samples/quickstart/service/jibx/StockQuoteServiceSkeleton.java,在生成的方法中添加你的服务功能,如代码列表8所示。
代码列表8:定义服务框架文件
package samples.quickstart.service.jibx;
import java.util.HashMap;
public class StockQuoteServiceSkeleton implements StockQuoteServiceSkeletonInterface {
private HashMap map = new HashMap();
public void update(String symbol, Double price) {
map.put(symbol, price);
}
public Double getPrice(String symbol) {
Double ret = (Double) map.get(symbol);
if (ret == null) {
ret = new Double(42.0);
}
return ret;
}
}
现在你可以在build/service目录下输入以下命令搭建项目:
ant jar.server如果一切运行正常,你将在你的框口中看到BUILD SUCCESSFUL信息,以及在build/service/build/lib目录中看到文件StockQuoteService.aar。复制这个文件到Servlet引擎的webapps/axis2/WEB-INF/services 目录。
要检查确认服务被正确部署,可以访问服务列表,
http://localhost:8080/axis2/services/listServices你还可以检查定制的WSDL,
http://localhost:8080/axis2/services/StockQuoteService?wsdl和schema,
http://localhost:8080/axis2/services/StockQuoteService?xsd要获得更多的关于在Axis2中使用JiBX的信息,参见JiBX代码生成集成细节。 你也可以检查JiBX Axis2 Wiki 网页,以获得关于Axis2中使用JiBX的更新信息。
生成客户端
在这一部分中,我们将看到四种方法来建立客户端,这个客户端基于StockQuoteService类:建立基于AXIOM的客户端,用Axis2数据绑定框架(ADB)生成一个客户端,用XMLBeans生成一个客户端,用JiBX生成客户端。
用AXIOM建立客户端
--------------------------------------------------------------------------------
用AXIOM建立客户端,执行下列步骤。
同样,注意在用AXIOM建立服务部分中的目录结构,下面完整的复制了一份。
- quickstartaxiom
- README.txt
- build.xml
- resources
- META-INF
- services.xml
- StockQuoteService.wsdl
- src
- samples
- quickstart
- service
- axiom
- StockQuoteService.java
- clients
- AXIOMClient.java
上面引用的AXIOMClient.java类如下代码列表9所示。
代码列表9:使用AXIOM的AXIOMClient类
package samples.quickstart.clients;
import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNamespace;
import org.apache.axis2.Constants;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.Options;
import org.apache.axis2.client.ServiceClient;
public class AXIOMClient {
private static EndpointReference targetEPR =
new EndpointReference("http://localhost:8080/axis2/services/StockQuoteService");
public static OMElement getPricePayload(String symbol) {
OMFactory fac = OMAbstractFactory.getOMFactory();
OMNamespace omNs = fac.createOMNamespace("http://axiom.service.quickstart.samples/xsd", "tns");
OMElement method = fac.createOMElement("getPrice", omNs);
OMElement value = fac.createOMElement("symbol", omNs);
value.addChild(fac.createOMText(value, symbol));
method.addChild(value);
return method;
}
public static OMElement updatePayload(String symbol, double price) {
OMFactory fac = OMAbstractFactory.getOMFactory();
OMNamespace omNs = fac.createOMNamespace("http://axiom.service.quickstart.samples/xsd", "tns");
OMElement method = fac.createOMElement("update", omNs);
OMElement value1 = fac.createOMElement("symbol", omNs);
value1.addChild(fac.createOMText(value1, symbol));
method.addChild(value1);
OMElement value2 = fac.createOMElement("price", omNs);
value2.addChild(fac.createOMText(value2,
Double.toString(price)));
method.addChild(value2);
return method;
}
public static void main(String[] args) {
try {
OMElement getPricePayload = getPricePayload("WSO");
OMElement updatePayload = updatePayload("WSO", 123.42);
Options options = new Options();
options.setTo(targetEPR);
options.setTransportInProtocol(Constants.TRANSPORT_HTTP);
ServiceClient sender = new ServiceClient();
sender.setOptions(options);
sender.fireAndForget(updatePayload);
System.err.println("price updated");
OMElement result = sender.sendReceive(getPricePayload);
String response = result.getFirstElement().getText();
System.err.println("Current price of WSO: " + response);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Axis2使用AXIOM,或者说AXIs对象模型,这是一个基于StAX API接口(Streaming API for XML)的类DOM(Document Object Model)结构。你在这里建立服务中的update和getPrice方法的具体内容。建立这些内容和你建立AXIOM服务中的getPriceResponse的方法是一样的。接下来你建立可选类,以及一个用来与服务通讯的ServiceClient。首先你调用update方法,这是一个不返回人和东西的fireAndForget方法。最后,你调用getPrice方法,从服务处获得当前价格并显示它们。
现在你可以建立和运行AXIOM客户端,在Axis2_HOME/samples/quickstartaxiom 中输入ant run.client。
你应该得到以下输出:
done
Current price of WSO: 123.42
用ADB建立一个客户端
--------------------------------------------------------------------------------
要用Axis数据绑定(ADB)建立客户端,执行下列步骤。
在Axis2_HOME/samples/quickstartadb 目录输入以下内容来产生客户端数据绑定:
%AXIS2_HOME%/bin/WSDL2Java -uri resources/META-INF/StockQuoteService.wsdl -p samples.quickstart.clients -d adb -s -o build/client或者在Axis2_HOME/samples/quickstartadb目录中简单的输入ant generate.client。
接下来看一下quickstartadb/src/samples/quickstart/clients/ADBClient.java, 看看它在代码列表10中是怎么被定义的。
代码列表10:ADBClient类
package samples.quickstart.clients;
import samples.quickstart.service.adb.StockQuoteServiceStub;
public class ADBClient{
public static void main(java.lang.String args[]){
try{
StockQuoteServiceStub stub =
new StockQuoteServiceStub
("http://localhost:8080/axis2/services/StockQuoteService");
getPrice(stub);
update(stub);
getPrice(stub);
} catch(Exception e){
e.printStackTrace();
System.err.println("\n\n\n");
}
}
/* fire and forget */
public static void update(StockQuoteServiceStub stub){
try{
StockQuoteServiceStub.Update req = new StockQuoteServiceStub.Update();
req.setSymbol ("ABC");
req.setPrice (42.35);
stub.update(req);
System.err.println("price updated");
} catch(Exception e){
e.printStackTrace();
System.err.println("\n\n\n");
}
}
/* two way call/receive */
public static void getPrice(StockQuoteServiceStub stub){
try{
StockQuoteServiceStub.GetPrice req = new StockQuoteServiceStub.GetPrice();
req.setSymbol("ABC");
StockQuoteServiceStub.GetPriceResponse res =
stub.getPrice(req);
System.err.println(res.get_return());
} catch(Exception e){
e.printStackTrace();
System.err.println("\n\n\n");
}
}
}
这个类用你建立的Axis数据绑定建立一个客户端功能组。接着它在Web Service上调用getPrice和update操作。getPrice方法建立一个GetPrice数据包并把symbol的值设为ABC。接着它发送请求并显示当前价格。Update方法建立了一个Update数据包,把symbol和price的值分别设为ABC和42.35。
现在搭建并运行客户端,在Axis2_HOME/samples/quickstartadb 目录下执行ant run.client。
你将得到以下的输出:
42
price updated
42.35
用XMLBeans生成客户端
--------------------------------------------------------------------------------
要用XML Beans数据绑定搭建一个客户端,执行以下步骤。
在xmlbeansClient目录里执行以下语句来产生数据绑定。
%AXIS2_HOME%/bin/WSDL2Java -uri resources/META-INF/StockQuoteService.wsdl -p samples.quickstart.service.xmlbeans -d xmlbeans -s -o build/client或者在Axis2_HOME/samples/quickstartxmlbeans 目录里简单的输入ant generate.client。
注意这样就建立了一个客户端功能组代码,它不包含服务端代码。
接着看一下quickstartxmlbeans/src/samples/quickstart/clients/XMLBEANSClient.java,看看它在代码列表11中匙如何定义的。
代码列表11:XMLBEANSClient类
package samples.quickstart.clients;
import samples.quickstart.service.xmlbeans.StockQuoteServiceStub;
import samples.quickstart.service.xmlbeans.xsd.GetPriceDocument;
import samples.quickstart.service.xmlbeans.xsd.GetPriceResponseDocument;
import samples.quickstart.service.xmlbeans.xsd.UpdateDocument;
public class XMLBEANSClient{
public static void main(java.lang.String args[]){
try{
StockQuoteServiceStub stub =
new StockQuoteServiceStub
("http://localhost:8080/axis2/services/StockQuoteService");
getPrice(stub);
update(stub);
getPrice(stub);
} catch(Exception e){
e.printStackTrace();
System.err.println("\n\n\n");
}
}
/* fire and forget */
public static void update(StockQuoteServiceStub stub){
try{
UpdateDocument reqDoc = UpdateDocument.Factory.newInstance();
UpdateDocument.Update req = reqDoc.addNewUpdate();
req.setSymbol ("BCD");
req.setPrice (42.32);
stub.update(reqDoc);
System.err.println("price updated");
} catch(Exception e){
e.printStackTrace();
System.err.println("\n\n\n");
}
}
/* two way call/receive */
public static void getPrice(StockQuoteServiceStub stub){
try{
GetPriceDocument reqDoc = GetPriceDocument.Factory.newInstance();
GetPriceDocument.GetPrice req = reqDoc.addNewGetPrice();
req.setSymbol("BCD");
GetPriceResponseDocument res =
stub.getPrice(reqDoc);
System.err.println(res.getGetPriceResponse().getReturn());
} catch(Exception e){
e.printStackTrace();
System.err.println("\n\n\n");
}
}
}
这个类用你建立的XML Beans数据绑定建立了一个客户端功能组。接着它在Web Service上调用getPrice和update操作。getPrice方法建立了GetPriceDocument实例,这是它的内部GetPrice类,并设置symbol的值为ABC。接着发送请求并接收到一个GetPriceResponseDocument实例显示当前价格。。update方法建立一个UpdateDocument实例,将symbol和price分别设置为ABC和42.32,在完成时显示‘done’。
现在搭建并运行项目,在Axis2_HOME/samples/quickstartxmlbeans 目录里输入ant run.client即可。
你将得到以下输出:
42
price updated
42.32
用JiBX生成客户端
--------------------------------------------------------------------------------
要用JiBX搭建客户端,执行以下步骤。
在Axis2_HOME/samples/quickstartjibx 目录中,打开一个控制台并输入以下内容,就可以生成客户端功能组。
%AXIS2_HOME%/bin/wsdl2java -uri resources/META-INF/StockQuoteService.wsdl -p samples.quickstart.clients -d jibx -s -uw -o build/client或者简单输入“ant generate.client”。
接下来看一下quickstartjibx/src/samples/quickstart/clients/JiBXClient.java,如下面的代码列表12所示。
代码列表12:JiBXClient类
package samples.quickstart.clients;
import samples.quickstart.service.jibx.StockQuoteServiceStub;
public class JiBXClient{
public static void main(java.lang.String args[]){
try{
StockQuoteServiceStub stub =
new StockQuoteServiceStub
("http://localhost:8080/axis2/services/StockQuoteService");
getPrice(stub);
update(stub);
getPrice(stub);
} catch(Exception e){
e.printStackTrace();
System.err.println("\n\n\n");
}
}
/* fire and forget */
public static void update(StockQuoteServiceStub stub){
try{
stub.update("CDE", new Double(42.35));
System.err.println("price updated");
} catch(Exception e){
e.printStackTrace();
System.err.println("\n\n\n");
}
}
/* two way call/receive */
public static void getPrice(StockQuoteServiceStub stub){
try{
System.err.println(stub.getPrice("CDE"));
} catch(Exception e){
e.printStackTrace();
System.err.println("\n\n\n");
}
}
}
这个类用JiBX客户端功能组在Web Service上访问getPrice和update操作。getPrice方法发送一个股票“ABC”的请求并显示价格。Update方法将股票“ABC”的值设为42.35。现在在Axis2_HOME/samples/quickstartjibx 目录里,打开一个控制台输入“ant run.client”,就能搭建和运行客户端了。
你将得到以下的输出:
42
price updated
42.35
要获得更多的关于在Axis2上使用JiBX的信息,参见JiBX代码生成集成的细节。
小结
Axis2为快速获取和运行web service,提供了一个平滑和健壮的方法。 这篇指南述说了在Axis2上部署服务的五种方法和建立与服务通讯客户端的四种方法。你现在有了可以用不同技术建立Web service的灵活性了。
进一步的学习
Apache Axis2 - http://ws.apache.org/axis2/
Axis2 体系结构 - http://ws.apache.org/axis2/1_0/Axis2ArchitectureGuide.html
Apache Axis2介绍 - http://www.redhat.com/magazine/021jul06/features/apache_axis2/
和Apache Axis2一起工作 - http://www.wso2.net/articles/axis2/java/2006/09/13/working-with-axis2