分享
 
 
 

新一代Web Service 实现包 -- AXIS2 学习笔记 (二)

王朝java/jsp·作者佚名  2006-01-10
窄屏简体版  字體: |||超大  

客户端的调用

Web services提供的服务多种多样,有的可以马上获得结果,有的要消耗很长的时间。所以,如果我们需要多种调用方式来对付不同的情况。

大多数的Web services都提供阻塞(Blocking)和非阻塞(Non-Blocking)两种APIs. 这两个概念以前应该学过,简单说一下。

Blocking API - 调用端要等被调用的函数运行完毕才继续往下走。

Non-Bloking API - 调用端运行完调用函数以后就直接往下走了,调用端和被调用端是异步执行的。返回值是用回调函数来实现的。

这种异步叫做API层异步(API Level Asynchrony)。他们只用到一个连接来发送和接收消息,而且,如果是那种需要运行很长时间的函数,还会碰到Time Out 错误,如果用两个连接分别处理发送和接收消息,调用的时间就可以缩短,也可以解决Time Out 问题。用两个连接来分别处理发送和接收消息,叫做传输层异步(Transport Level Asynchrony)。

API

传输

描述

阻塞

1连接

简单的传统用法

非阻塞

1连接

使用回调或者轮询

阻塞

2连接

Service是有返回值的,但是它的传输是单路。(比如 SMTP)

非阻塞

2连接

最大程度的异步执行

理论真无聊,还是来看实例吧。

打开 Eclipse, 创建一个新Project, 新建一个叫userguide.clients的包, 把"samples\userguide\src\userguide\clients" 下面的文件都copy到那个包下面, 把AXIS2的lib下面的jar都加到ilbrary里面去(应该不用全加,懒一点就全加了吧.) 发现了关于echo的调用的方式, 居然有五个:

EchoBlockingClient

EchoBlockingDualClient

EchoBlockingWsaBasedClient

EchoNonBlockingClient

EchoNonBlockingDualClient

一个一个看吧.

EchoBlockingClient.java

public class EchoBlockingClient {

private static EndpointReference targetEPR = new EndpointReference("http://localhost:8080/axis2/services/MyService");

public static void main(String[] args) {

try {

OMElement payload = ClientUtil.getEchoOMElement();

Call call = new Call();

call.setTo(targetEPR);

call.setTransportInfo(Constants.TRANSPORT_HTTP,

Constants.TRANSPORT_HTTP,

false);

//Blocking invocation

OMElement result = call.invokeBlocking("echo",

payload);

StringWriter writer = new StringWriter();

result.serializeWithCache(XMLOutputFactory.newInstance()

.createXMLStreamWriter(writer));

writer.flush();

System.out.println(writer.toString());

} catch (AxisFault axisFault) {

axisFault.printStackTrace();

} catch (XMLStreamException e) {

e.printStackTrace();

}

}

}

和一代几乎一样, 弄一个EndpointReference, 再弄一个call, 其他不一样,但是也很简单, 弄一个OMElement作为参数, 返回也是一个OMElement. 可惜运行居然有错.

再来看双通道的版本

EchoBlockingDualClient.java

public class EchoBlockingDualClient {

private static EndpointReference targetEPR = new EndpointReference("http://127.0.0.1:8080/axis2/services/MyService");

public static void main(String[] args) {

try {

OMElement payload = ClientUtil.getEchoOMElement();

Call call = new Call();

call.setTo(targetEPR);

call.engageModule(new QName(Constants.MODULE_ADDRESSING));

call.setTransportInfo(Constants.TRANSPORT_HTTP,

Constants.TRANSPORT_HTTP,

true);

//Blocking Invocation

OMElement result = call.invokeBlocking("echo",

payload);

StringWriter writer = new StringWriter();

result.serializeWithCache(XMLOutputFactory.newInstance()

.createXMLStreamWriter(writer));

writer.flush();

System.out.println(writer.toString());

//Need to close the Client Side Listener.

call.close();

} catch (AxisFault axisFault) {

axisFault.printStackTrace();

} catch (Exception ex) {

ex.printStackTrace();

}

}

}

加了一句engageModule, 这句话好像没什么用,我删掉这句话也能运行的, 然后setTransportInfo最后一个参数改成了true. 关于setTransportInfo的三个参数, 第一个是发送的Transport, 第二个是接收的Transport, 第三个是"是否双通道", 支持的搭配形式如下:

http, http, true

http, http, false

http,smtp,true

smtp,http,true

smtp,smtp,true

看下一个吧,EchoNonBlockingClient,这个是单通道的非阻塞模式:

public class EchoNonBlockingClient {

private static EndpointReference targetEPR = new EndpointReference("http://127.0.0.1:8080/axis2/services/MyService");

public static void main(String[] args) {

try {

OMElement payload = ClientUtil.getEchoOMElement();

Call call = new Call();

call.setTo(targetEPR);

call.setTransportInfo(Constants.TRANSPORT_HTTP,

Constants.TRANSPORT_HTTP,

false);

//Callback to handle the response

Callback callback = new Callback() {

public void onComplete(AsyncResult result) {

try {

StringWriter writer = new StringWriter();

result.getResponseEnvelope().serializeWithCache(XMLOutputFactory.newInstance()

.createXMLStreamWriter(writer));

writer.flush();

System.out.println(writer.toString());

} catch (XMLStreamException e) {

reportError(e);

}

}

public void reportError(Exception e) {

e.printStackTrace();

}

};

//Non-Blocking Invocation

call.invokeNonBlocking("echo", payload, callback);

//Wait till the callback receives the response.

while (!callback.isComplete()) {

Thread.sleep(1000);

}

} catch (AxisFault axisFault) {

axisFault.printStackTrace();

} catch (Exception ex) {

ex.printStackTrace();

}

}

}

不同的地方,只是调用的方法从invokeBlocking变成了invokeNonBlocking,然后写了一个简单的匿名Callback类作为回调函数。关于这个Callback类,它是一个抽象类,其中有两个方法:onComplete和reportError,都是client端必须实现的,他还有一个Field,就是complete,可以用来设置和查询调用是否完成。可惜也不能运行,和上面的错误一样,是在createSOAPMessage的时候报null错误。

看下一个EchoNonBlockingDualClient,非阻塞的双通道:

public class EchoNonBlockingDualClient {

private static EndpointReference targetEPR = new EndpointReference("http://127.0.0.1:8080/axis2/services/MyService");

public static void main(String[] args) {

try {

OMElement payload = ClientUtil.getEchoOMElement();

Call call = new Call();

call.setTo(targetEPR);

//The boolean flag informs the axis2 engine to use two separate transport connection

//to retrieve the response.

call.engageModule(new QName(Constants.MODULE_ADDRESSING));

call.setTransportInfo(Constants.TRANSPORT_HTTP,

Constants.TRANSPORT_HTTP,

true);

//Callback to handle the response

Callback callback = new Callback() {

public void onComplete(AsyncResult result) {

try {

StringWriter writer = new StringWriter();

result.getResponseEnvelope().serializeWithCache(XMLOutputFactory.newInstance()

.createXMLStreamWriter(writer));

writer.flush();

System.out.println(writer.toString());

} catch (XMLStreamException e) {

reportError(e);

}

}

public void reportError(Exception e) {

e.printStackTrace();

}

};

//Non-Blocking Invocation

call.invokeNonBlocking("echo", payload, callback);

//Wait till the callback receives the response.

while (!callback.isComplete()) {

Thread.sleep(1000);

}

//Need to close the Client Side Listener.

call.close();

} catch (AxisFault axisFault) {

axisFault.printStackTrace();

} catch (Exception ex) {

ex.printStackTrace();

}

}

}

双通道和单通道基本没什么不同,只是双通道的时候,它总是要设定engageModule,然后多了一个call.close();,自己关闭监听器(close the Client Side Listener)。

以上这些都是需要返回值的调用,如果不需要返回值呢,看看PingClient

public class PingClient {

private static EndpointReference targetEPR = new EndpointReference("http://localhost:8080/axis2/services/MyService");

public static void main(String[] args) {

try {

OMElement payload = ClientUtil.getPingOMElement();

MessageSender msgSender = new MessageSender();

msgSender.setTo(targetEPR);

msgSender.setSenderTransport(Constants.TRANSPORT_HTTP);

msgSender.send("ping", payload);

} catch (AxisFault axisFault) {

axisFault.printStackTrace();

}

}

}

呵呵,这也忒简单了一点,就一个msgSender.send就搞定了。

Client端的调用组合基本看完了,但是还有一个EchoBlockingWsaBasedClient,这是什么东啊? 还有那个engageModule是用来做啥的?先不管它们吧。

看看那个我认为最有用的工具:WSDL2Java,在bin目录下面有WSDL2Java.bat和WSDL2Java.sh,这个工具是用来干啥的呢,和一代一样,是用来生成stub的,就是说别人发布了Web Service以后,就会有一个wsdl文件,这个工具可以根据wsdl生成几个class,把底层的调用都wrap起来了,然后你用的时候就像普通函数调用一样。

演练一下吧,从命令行走到samples\wsdl目录下面,看到Axis2SampleDocLit.wsdl,执行..\..\bin\WSDL2Java.bat -uri Axis2SampleDocLit.wsdl,目录下面一下子多了两个目录,不管schemaorg_apache_xmlbeans,把codegen目录copy到Eclipse的一个Project里面去,哇,好多class啊,不看别的,就看Axis2SampleDocLitPortTypeStub,里面有三个函数是Web Service提供的:echoStringArray,echoStruct和echoString,哈哈,什么Call类了,MessageContext了,都在里面了,使用起来嘛,就像这样:

try {

Axis2SampleDocLitPortTypeStub stub= new Axis2SampleDocLitPortTypeStub(null, "http://localhost:8080/axis2/services/Axis2SampleDocLitPortType");

//Create the request document to be sent.

EchoStringParamDocument reqDoc= EchoStringParamDocument.Factory.newInstance();

reqDoc.setEchoStringParam("Axis2 Echo");

//invokes the web service.

EchoStringReturnDocument resDoc=stub.echoString(reqDoc);

System.out.println(resDoc.getEchoStringReturn());

} catch (Exception e) {

e.printStackTrace();

}

就是创一个stub,再创一个参数类(EchoStringParamDocument),然后调用函数传参数,和普通的函数调用没有区别。如果你在命令行输入WSDL2Java.bat,会看到它的帮助提示如下:

Usage WSDL2Code -uri <Location of WSDL> :WSDL file location

-o <output Location> : output file location

-a : Generate async style code only. Default if off

-s : Generate sync style code only. Default if off. takes precedence over -a

-p <package name> : set custom package name

-l <language> : valid languages are java and csharp. Default is java

-t : Generate TestCase to test the generated code

-ss : Generate server side code (i.e. skeletons).Default is off

-sd : Generate service descriptor (i.e. axis2.xml).Default is off.Valid with -ss

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有