Axis2(8):异步调用WebService
在前面几篇文章中都是使用同步方式来调用WebService。也就是说,如果被调用的WebService方法长时间不返回,客户端将一直被阻塞,直到该方法返回为止。使用同步方法来调用WebService虽然很直观,但当WebService方法由于各种原因需要很长时间才能返回的话,就会使客户端程序一直处于等待状态,这样用户是无法忍受的。
package?service;
public? class?MyService { ???? public?String?getName() ????{ ???????? try ????????{???????????? ????????????System.out.println("getName方法正在执行 "); ???????????? // ??延迟5秒 ????????????Thread.sleep(5000); ????????} ???????? catch?(Exception?e) ????????{???????? ????????} ???????? return?"火星"; ????} } ????为了模拟需要一定时间才返回的WebService方法,在getName方法中使用了sleep方法来延迟5秒。 <!--
??services.xml??
-->
< service? name ="myService" > ???? description > ????????异步调用演示 ???? </ parameter? ="ServiceClass" > ????????service.MyService??? ???? parameter messageReceivers > ???????? messageReceiver? mep ="http://www.w3.org/2004/08/wsdl/in-out" ????????????class ="org.apache.axis2.rpc.receivers.RPCMessageReceiver" ? /> ???? > service >
????从上面的配置代码可以看出,MyService的配置方式与前几章的WebService的配置方式完全一样,也就是说,MyService只是一个普通的WebService。 package?client;
import?javax.xml.namespace.QName; import?org.apache.axis2.addressing.EndpointReference; import?org.apache.axis2.client.Options; import?org.apache.axis2.context.MessageContext; import?org.apache.axis2.rpc.client.RPCServiceClient; class?RPCAsyncClient { ???? static? void?main(String[]?args)? throws?Exception ????{ ????????RPCServiceClient?serviceClient?=? new?RPCServiceClient(); ????????Options?options?=?serviceClient.getOptions(); ????????EndpointReference?targetEPR?=? new?EndpointReference( ????????????????"http://localhost:8080/axis2/services/myService"); ????????options.setTo(targetEPR); ????????Object[]?opAddEntryArgs?=? new?Object[]{}; ????????QName?opAddEntry?=? new?QName("http://service",?"getName"); ????????serviceClient.invokeNonBlocking(opAddEntry,?opAddEntryArgs, ???????????????? new?org.apache.axis2.client.async.AxisCallback() ????????????????{ ????????????????????@Override ???????????????????? void?onComplete() ????????????????????{ ????????????????????} ????????????????????@Override ???????????????????? void?onError(Exception?arg0) ????????????????????{ ????????????????????}????????????????????} ????????????????????@Override ???????????????????? void?onFault(MessageContext?arg0) ????????????????????{ ????????????????????} ????????????????????@Override ???????????????????? void?onMessage(MessageContext?mc) ????????????????????{ ???????????????????????? ??输出返回值 ????????????????????????System.out.println(mc.getEnvelope().getFirstElement() ????????????????????????????????.getFirstElement().getFirstElement().getText()); ????????????????????} ????????????????}); ????????System.out.println("异步调用!"); ???????? ??阻止程序退出 ????????System.in.read(); ????} }??
????从上面的代码可以看出,invokeNonBlocking方法有三个参数,前两个参数分别指定了要调用的方法及方法参数的相关信息,而最后一个参数并不是方法返回值的类型信息,而是一个实现org.apache.axis2.client.async.AxisCallback接口的类的对象实例。在本例中隐式实现了AxisCallback接口。在AxisCallback接口中有四个方法需要实现,其中当被异步调用的方法返回时onMessage方法被调用。当运行上面的程序后,将输出如下的信息:
异步调用!
火星 ????虽然上面的例子可以实现异步调用,但比较麻烦。为了更方便地实现异步调用,可以使用wsdl2java命令的-a参数生成可异步调用的Stub类。下面的命令可生成同步和异步调用的客户端代码(两个类),其中-s表示生成同步调用代码,-a表示生成异步调用代码。
%AXIS2_HOME%binwsdl2java?-uri?http://localhost:8080/axis2/services/myService?wsdl?-p?client?-s?-a?-o?stub
????在执行上面的命令后,将生成两个类:MyServiceStub和MyServiceCallbackHandler类,其中MyServiceStub类负责同步和异步调用WebService,MyServiceCallbackHandler类是一个抽象类,也是一个回调类,当使用异步方式调用WebService方法时,如果方法返回,则MyServiceCallbackHandler类的receiveResultgetName方法被调用。下面是使用MyServiceStub类异步访问WebService的代码: import?client.MyServiceStub.GetNameResponse;
class?MyCallback? extends?MyServiceCallbackHandler { ????@Override ???? void?receiveResultgetName(GetNameResponse?result) ????{ ???????? ??输出getName方法的返回结果 ????????System.out.println(result.get_return()); ????} } class?StubClient { ???? throws?Exception?? ????{ ????????MyServiceStub?stub?=? new?MyServiceStub();???????? ???????? ??异步调用WebService ????????stub.startgetName( new?MyCallback()); ????????System.out.println("异步调用!"); ????????System.in.read();???? ????}? }
???执行上面的程序后,将输出如下的信息:????
异步调用!
火星 ??? ?? 在.net中也可以使用异步的方式来调用WebService,如在C#中可使用如下的代码来异步调用getName方法: ??回调方法
private? void?getNameCompletedEvent(object?sender,?WSC.asyn.getNameCompletedEventArgs?e) { ????listBox1.Items.Add(?e.Result.@ return); } void?button1_Click(object?sender,?EventArgs?e) {?????????? ????async.myService?my?=? new?WSC.async.myService(); ????my.getNameCompleted?+=? new?WSC.async.getNameCompletedEventHandler(getNameCompletedEvent); ?????my.getNameAsync(); ?????MessageBox.Show("完成调用"); } ????其中async是引用MyService的服务名。要注意的是,在C#中不能在同一个WebService实例的getName方法未返回之前,再次调用该实例的getName方法,否则将抛出异常。如下面的代码会抛出一个异常:
????async.myService?my?=?
new?WSC.async.getNameCompletedEventHandler(getNameCompletedEvent);
??? my.getNameAsync(); ???? ??将抛出异常 ??? my.getNameAsync();
????但不同的WebService实例的方法可以在方法未返回时调用,如下面的代码是可以正常工作的:
asyn.myService?my?=?
new?WSC.asyn.myService();
my.getNameAsync(); my.getNameCompleted?+=? new?WSC.asyn.getNameCompletedEventHandler(getNameCompletedEvent); asyn.myService?my1?=? new?WSC.asyn.myService(); my1.getNameCompleted?+=? new?WSC.asyn.getNameCompletedEventHandler(getNameCompletedEvent); my1.getNameAsync(); (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |