客户端的调用
web services提供的服务多种多样,有的可以马上获得结果,有的要消耗很长的时间。所以,如果我们需要多种调用方式来对付不同的情况。
大多数的web services都提供阻塞(blocking)和非阻塞(non-blocking)两种apis. 这两个概念以前应该学过,简单说一下。
blocking api - 调用端要等被调用的函数运行完毕才继续往下走。
non-bloking api - 调用端运行完调用函数以后就直接往下走了,调用端和被调用端是异步执行的。返回值是用回调函数来实现的。
这种异步叫做api层异步(api level asynchrony)。他们只用到一个连接来发送和接收消息,而且,如果是那种需要运行很长时间的函数,还会碰到time out 错误,如果用两个连接分别处理发送和接收消息,调用的时间就可以缩短,也可以解决time out 问题。用两个连接来分别处理发送和接收消息,叫做传输层异步(transport level asynchrony)。

理论真无聊,还是来看实例吧。
打开 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();
}
}
}
双通道和单通道基本没什么不同,只是双通道的时候,它总是要
闽公网安备 35060202000074号