??xml version="1.0" encoding="utf-8" standalone="yes"?>
会自动生成一些代码?br />
package org.hermit.study.jdk.client;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
/**
* This class was generated by the JAXWS SI.
* JAX-WS RI 2.0_02-b08-fcs
* Generated source version: 2.0
*
*/
@WebService(name = "Hello", targetNamespace = "http://jdk.study.hermit.org/client")
@SOAPBinding(style = SOAPBinding.Style.RPC)
public interface Hello {
/**
*
* @param arg0
* @return
* returns java.lang.String
*/
@WebMethod
@WebResult(partName = "return")
public String sayHello(
@WebParam(name = "arg0", partName = "arg0")
String arg0);
}
package org.hermit.study.jdk.client;
import java.net.MalformedURLException;
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import javax.xml.ws.WebEndpoint;
import javax.xml.ws.WebServiceClient;
/**
* This class was generated by the JAXWS SI.
* JAX-WS RI 2.0_02-b08-fcs
* Generated source version: 2.0
*
*/
@WebServiceClient(name = "HelloService", targetNamespace = "http://jdk.study.hermit.org/client", wsdlLocation = "http://localhost:8080/HelloService?wsdl")
public class HelloService
extends Service
{
private final static URL HELLOSERVICE_WSDL_LOCATION;
static {
URL url = null;
try {
url = new URL("http://localhost:8080/HelloService?wsdl");
} catch (MalformedURLException e) {
e.printStackTrace();
}
HELLOSERVICE_WSDL_LOCATION = url;
}
public HelloService(URL wsdlLocation, QName serviceName) {
super(wsdlLocation, serviceName);
}
public HelloService() {
super(HELLOSERVICE_WSDL_LOCATION, new QName("http://jdk.study.hermit.org/client", "HelloService"));
}
/**
*
* @return
* returns Hello
*/
@WebEndpoint(name = "HelloPort")
public Hello getHelloPort() {
return (Hello)super.getPort(new QName("http://jdk.study.hermit.org/client", "HelloPort"), Hello.class);
}
}
下面我们再写个测试,看看能不能用Q?br />
import org.hermit.study.jdk.client.Hello;
import org.hermit.study.jdk.client.HelloService;
public class TestClient {
public static void main(String[] args) {
HelloService service = new HelloService();
Hello _hello = service.getHelloPort();
System.out.println(_hello.sayHello("hermit"));
}
}
hello:hermit
okQ搞定?br />java6搞定web servicep么简单。。。。。。。。。。。。。。。。。。。。。。。。。?br />
xfire危险了。。。。。。。。。。。。。。。。。。。。。。。?/div>
]]>
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
@WebService(targetNamespace = "http://jdk.study.hermit.org/client")
@SOAPBinding(style = SOAPBinding.Style.RPC)
public class Hello {
@WebMethod
public String sayHello(String name) {
return "hello:" + name;
}
}
targetNamespace = "http://jdk.study.hermit.org/client"q句是指定客L获取服务端服务后存放的类路径。注意是反着的,http: //jdk.study.hermit.org/client在客L生成的类会放在org.hermit.study.jdk.client包下?br />下面是发布服务:package org.hermit.study.jdk;
import javax.xml.ws.Endpoint;
public class StartService ...{
public static void main(String[] args) ...{
Endpoint.publish("http://localhost:8080/HelloService", new Hello());
}
}
q行StartService ...Q开发浏览器输入Qhttp://localhost:8080/HelloService?wsdl
如果能看C下内容,可?br />
- <definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://jdk.study.hermit.org/client" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" targetNamespace="http://jdk.study.hermit.org/client" name="HelloService">
<types />
- <message name="sayHello">
<part name="arg0" type="xsd:string" />
</message>
- <message name="sayHelloResponse">
<part name="return" type="xsd:string" />
</message>
- <portType name="Hello">
- <operation name="sayHello" parameterOrder="arg0">
<input message="tns:sayHello" />
<output message="tns:sayHelloResponse" />
</operation>
</portType>
- <binding name="HelloPortBinding" type="tns:Hello">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
- <operation name="sayHello">
<soap:operation soapAction="" />
- <input>
<soap:body use="literal" namespace="http://jdk.study.hermit.org/client" />
</input>
- <output>
<soap:body use="literal" namespace="http://jdk.study.hermit.org/client" />
</output>
</operation>
</binding>
- <service name="HelloService">
- <port name="HelloPort" binding="tns:HelloPortBinding">
<soap:address location="http://localhost:8080/HelloService" />
</port>
</service>
</definitions>
]]>
Axis2 是下一?Apache Axis。Axis2 虽然?Axis 1.x 处理E序模型提供支持Q但它具有更强的灉|性ƈ可扩展到新的体系l构。Axis2 Z新的体系l构q行了全新编写,而且没有采用 Axis 1.x 的常用代码。支持开?Axis2 的动力是探寻模块化更强、灵zL更高和更有效的体系l构Q这U体pȝ构可以很Ҏ地插入到其他相关 Web 服务标准和协议(?WS-Security、WS-ReliableMessaging {)的实C?/p>
Axis2 的特性包括:
本系列文章以 Axis2 0.92 版本为基。您可以?Apache |站获得 Axis2 的最新版本?/p>
![]() ![]() |
![]()
|
Axis2 体系l构逻辑与状态分;q允许在q行U程中执行逻辑。服务和调用的静态状态和动态状态分别存储在 Description
?Context
cM。Axis2 体系l构是?7 个独立模块实现的?/p>
![]() ![]() |
![]()
|
部v Axis2 与部|?Axis 1 一L单。首先在 Axis2 二进制代码分发包?webapps 目录下查?Axis2 Web 应用E序 axis2.war。在 servlet 容器中部|此 war 文g。在 Tomcat 中,如果已在服务器配|中?unpackWARs 讄?TrueQ则只需?axis2.war 复制?$TOMCAT_HOME/webapps 目录卛_部v Axis2。请立即启动 Tomcat q访?http://localhost:<port>/axis2。将昄 Axis2 Ƣ迎,单击此页上的 Validate 链接。您应到?Axis2 Happiness pageQ不会出CQ何错误?/p>
![]() ![]() |
![]()
|
下面介绍如何使用 In-Only subscribe() ?In-Out getQuote() q两个操作来开?StockQuoteService。subscribe() 操作预订指定代L每小时报P?getQuote() 获得指定代L当前报h?/p>
下面?a >清单 1 ?StockQuoteService 的实现示例:
|
Ҏ法签名感到很疑惑Q我们将讨论上述Ҏ中的 OMElement?/p>
![]() ![]() |
![]()
|
部v描述W?/b>
?Axis2 中,服务部v信息包含?services.xml 文gQ在 0.92 以前的版本中Q此文g名ؓ service.xmlQ中。对于上q?StockQuoteServiceQ服务部|描q符与下面的清单 2 cM?/p>
清单 2. Services.xml
|
服务?name 属性定义服务的名称。Axis2 使用服务的名U创建服务的端点地址Q例?http://localhost:<port>/axis2/services/<nameofservice>。因此,对于 StockQuoteServiceQ服务端点ؓ http://localhost:<port>/axis2/services/StockQuoteService?code>ServiceClass 参数指定服务实现cR?/p>
每个 <operation> 元素定义服务中一个操作的配置?lt;operation> ?name 属性应讄为服务实现类中方法的名称?code>messageReceiver 元素定义用于处理此操作的消息接收器。Axis2 针对 In-Only ?In-Out 操作提供了两个无数据l定的内|?MessageReceiversQ?code>org.apache.axis2.receivers.RawXMLINOnlyMessageReceiver 用于 In-Only 操作Q?org.apache.axis2.receivers.RawXMLINOutMessageReceiver
用于 In-Out 操作。如果没有指?messageReceiverQ则 Axis2 尝试?org.apache.axis2.receivers.RawXMLINOutMessageReceiver 作ؓ~省?messageReceiver。上q?RAWXML 消息接收器将传入 SOAP 消息?<Body> 的内容作?OMElementQOMElement ?XML 元素?AXIOM ~写Q传递给服务实现。此操作应作?OMElement q回 SOAP 响应?<Body> 元素包含?XML 内容。这便解释了Z subscribe() ?getQuote() 操作采用和返?OMElement?/p>
services.xml q可以包含分?servicegroup 的多个服务?/p>
打包
Axis 2 服务是作?Axis Archive (.aar) 打包的。这是一?JAR 文gQ?jar ?zip 实用E序创徏Q,在存档的 META-INF 目录中打包了 services.xml 文g。StockQuoteService 在打包成 StockQuoteService.aar 时将h以下l构Q?
|
预先打包?StockQuoteService 存档可以在本文的下蝲部分中找到?/p>
部v
?Axis2 中部|服务相当简单,只需?.aar 文g复制?servlet 容器?axis2 Web 应用E序中的 axis2/WEB-INF/services 目录下即可。对?TomcatQ此位置?$TOMCAT_HOME/webapps/axis2/WEB-INF/services?
另一U部|服务的好方法是使用 Axis2 理控制C?Upload Service 工具。请转到 http://localhost:<port>/axis2Q然后选择 Administration 链接。输入用户名和密?admin/axis2Q然后登录。(您可以在 axis2.xml 中配|用户名/密码?在工具部分选择 Upload Service 链接Q再选择 .aar 文gQ然后单?Upload。就是这L单!如果上传成功Q系l将昄一条绿色成功消息。服务即被部|Ԍ而且可随时调用。如果要在远E?Axis2 服务器上部v服务Q则此功能非常方ѝ?/p>
![]() ![]() |
![]()
|
Web 服务调用的特性由 MEP、传输协议以及客L API 的同步和/或异步行为决定。Axis2 当前支持 WSDL 2.0 定义?In-Only ?In-Out MEP。Axis2 客户?API 支持服务的同步和异步调用。在调用 In-Out 操作Ӟ?API U别和传输别提供异步行为。API U别异步是通过回滚获得的,它用一个传输连接来同时传输h和响应(例如Q通过一?HTTP q接传输h和响应)。在传输U别异步中,使用不同的传输连接分别发送请求和接收响应Q例如?SMTP q行传输时即如此?/p>
下面是?Axis2 客户?API 调用 In-Only ?In-Out 操作的详l信息?/p>
org.apache.axis2.clientapi.MessageSender
cȝ于调?In-Only 操作Q如下面?a >清单 3 所C)Q?In-Only 操作调用 StockQuoteService
?subscribe()
操作?/p>
清单 3. 调用 In-Only 操作
|
MessageSender.send()
发送请求消息ƈ其立即q回。要使用的传输由 MessageSender.setSenderTransport()
指定。此CZ通过 HTTP 发送消息?/p>
使用 org.apache.axis2.clientapi.Call
cd以方便地调用 In-Out 操作。调?In-Out 操作Ӟ?Call
cL持下?4 U模式:
d单传输模?/b>Q这是调?In-Out Web 服务操作最单的方式。在操作完成和接收到响应或错误之前,服务调用被阻塞。它使用一个传输连接同时发送和接收响应Q如下面?a >清单 4 所C?/p>
清单 4. d单传输模?/b>
try {
EndpointReference targetEPR = new EndpointReference(
"http://localhost:8080/axis2/services/StockQuoteService");
// Create request message
OMFactory fac = OMAbstractFactory.getOMFactory();
OMNamespace omNs = fac.createOMNamespace(
"http://www.developerworks.com/example", "example");
OMElement payload = fac.createOMElement("getQuote",omNs);
payload.setText("IBM");
// Create the call
Call call = new Call();
call.setTo(targetEPR);
call.setTransportInfo(Constants.TRANSPORT_HTTP,
Constants.TRANSPORT_HTTP, false);
// Invoke blocking
OMElement result = call.invokeBlocking("getQuote", payload);
System.out.println("Quote ="+result.getText());
}catch (AxisFault axisFault) {
axisFault.printStackTrace();
}
代码的第一部分使用 AXIOM 创徏h消息?code>Call.setTransportInfo() 讄用于发送请求和获得响应的传输?code>Call.setTransportInfo() 操作?Boolean 参数指出是否要用不同的传输q接来分别发送请求和接收响应。在本例中,要求用一?HTTP q接发送请求和接收响应?/p>
非阻塞单传输模式Q在此调用模式中Q只使用下面的一个传输连接获得非d调用。如果在一个客L应用E序中要完成多个 Web 服务调用Q而且不希望每ơ调用都d客户端,则需要此c行为。此Ӟ如果响应可用Q则调用立即q回且客L得以回滚Q如下面?a >清单 5 所C?/p>
清单 5. 非阻塞单传输模式
|
Call.invokeNonBlocking()
Ҏ立即q回而不d?code>Call.invokeNonBlocking() 采用 org.apache.axis2.clientapi.CallBack
的对象,如果响应来自服务Q则触发此对象?code>CallBack 有两个抽象方?onComplete(AsynchResult)
?reportError(Exception)
Q需要由具体?CallBack
cd现这些方法。在服务调用正常完成后,Axis2 引擎调用 onComplete()
Ҏ。在从服务器获得错误消息后,调用 Callback
?reportError()
Ҏ?code>Callback.isComplete() 指出操作调用是否完成?/p>
因ؓ上面两个Ҏ使用一个传输连接来发送和接收消息Q所以这些方法不适合长时间运行的事务。原因是在响应可用之前,传输q接可能会超时。要解决此问题,可用两个不同的q接来分别发送请求和接收响应。但因ؓ使用了其他传输连接来获得响应Q因此需要将h和响应关联v来。Axis2 支持 WS-AddressingQ后者通过使用 <wsa:MessageID> ?<wsa:RelatesTo> Header 可解x问题。因此,如果使用两个传输Q则支持Ҏ块寻址Q如下面两个模式所C?/p>
d双传输模?/b>Q此模式在以下情况下非常有用Q服务操作在本质上是 In-OutQ但使用的传输是单向的(?SMTPQ或服务执行需要很长时间且 HTTP q接时。请参见下面?a >清单 6?/p>
清单 6. d双传输模?/b>
try{
EndpointReference targetEPR = new EndpointReference(
"http://localhost:8080/axis2/services/StockQuoteService");
OMFactory fac = OMAbstractFactory.getOMFactory();
OMNamespace omNs = fac.createOMNamespace(
"http://www.developerworks.com/example", "example");
OMElement payload = fac.createOMElement("getQuote",omNs);
payload.setText("IBM");
Call call = new Call();
call.setTo(targetEPR);
call.setTransportInfo(
Constants.TRANSPORT_HTTP, Constants.TRANSPORT_HTTP, true);
//Blocking Invocation
OMElement result = call.invokeBlocking("getQuote", payload);
System.out.println("Quote = "+result.getText());
}catch (AxisFault axisFault) {
axisFault.printStackTrace();
}catch (Exception ex) {
ex.printStackTrace();
}
非阻塞双传输模式Q就 API U别和传输别的非阻塞而言Q此模式提供了最大的灉|性,如下面的清单 7 所C?/p>
清单 7. 非阻塞双传输模式
|
![]() ![]() |
![]()
|
在这一׃部分l成的系列的W?1 部分中,您了解了 Axis2 体系l构以及如何使用不同的调用模式来部v和用一个简单的 Web 服务。在本系列的W?2 部分中,您将详细了解该体pȝ构,以及如何通过d处理E序?Axis2 消息接收器来自定?Axis2。您q将了解如何使用 Axis2 提供?XMLBeans 数据l定支持?/p>