加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

WebService大讲堂之Axis2(8):异步调用WebService

发布时间:2020-12-16 23:56:47 所属栏目:安全 来源:网络整理
导读:在前面几篇文章中都是使用同步方式来调用 WebService 。也就是说,如果被调用的 方法长时间不返回,客户端将一直被阻塞,直到该方法返回为止。使用同步方法来调用 虽然很直观,但当 方法由于各种原因需要很长时间才能返回的话,就会使客户端程序一直处于等待
在前面几篇文章中都是使用同步方式来调用 WebService 。也就是说,如果被调用的 方法长时间不返回,客户端将一直被阻塞,直到该方法返回为止。使用同步方法来调用 虽然很直观,但当 方法由于各种原因需要很长时间才能返回的话,就会使客户端程序一直处于等待状态,这样用户是无法忍受的。
???? 当然,我们很容易就可以想到解决问题的方法,这就是多线程。解决问题的基本方法是将访问 的任务交由一个或多个线程来完成,而主线程并不负责访问 。这样即使被访问的 方法长时间不返回,客户端仍然可以做其他的工作。我们可以管这种通过多线程访问 的方式称为异步访问。
虽然直接使用多线程可以很好地解决这个问题,但比较麻烦。幸好 Axis2 的客户端提供了异步访问 的功能。
??? RPCServiceClient 类提供了一个 invokeNonBlocking 方法可以通过异步的方式来访问 。下面先来建立一个
????MyService
是一个 类,代码如下:
package ?service;
public ? class ?MyService
{
????
?String?getName()
????{
????????
try
????????{????????????
????????????System.out.println(
" getName方法正在执行

);
????????????
// ??延迟5秒
????????????Thread.sleep( 5000 );
????????}
????????
catch ?(Exception?e)
????????{????????
????????}
????????
return 火星 ;
????}
}
???? 为了模拟需要一定时间才返回的WebService 方法,在getName 方法中使用了sleep 方法来延迟5 秒。
???? 下面是MyService 类的配置代码:
<!-- ??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
???? 下面是异步调用MyService Java 客户端代码:

?client;

import ?javax.xml.namespace.QName;
?org.apache.axis2.addressing.EndpointReference;
?org.apache.axis2.client.Options;
?org.apache.axis2.context.MessageContext;
?org.apache.axis2.rpc.client.RPCServiceClient;

?RPCAsyncClient
{
????
static void ?main(String[]?args)? throws ?Exception
????{
????????RPCServiceClient?serviceClient?
= new ?RPCServiceClient();
????????Options?options?
?serviceClient.getOptions();
????????EndpointReference?targetEPR?
?EndpointReference(
????????????????
http://localhost:8080/axis2/services/myService );
????????options.setTo(targetEPR);
????????Object[]?opAddEntryArgs?
?Object[]{};
????????QName?opAddEntry?
?QName( http://service ,? getName );
????????serviceClient.invokeNonBlocking(opAddEntry,?opAddEntryArgs,
????????????????
?org.apache.axis2.client.async.AxisCallback()
????????????????{
????????????????????@Override
????????????????????
?onComplete()
????????????????????{
????????????????????}
????????????????????@Override
????????????????????
?onError(Exception?arg0)
????????????????????{
????????????????????}????????????????????}
????????????????????@Override
????????????????????
?onFault(MessageContext?arg0)
????????????????????{
????????????????????}
????????????????????@Override
????????????????????
?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 的代码:
?client.MyServiceStub.GetNameResponse;

?MyCallback? extends ?MyServiceCallbackHandler
{
????@Override
????
?receiveResultgetName(GetNameResponse?result)
????{
????????
??输出getName方法的返回结果 ????????System.out.println(result.get_return());
????}
}
?StubClient
{
????
?Exception??
????{
????????MyServiceStub?stub?
?MyServiceStub();????????
????????
??异步调用WebService ????????stub.startgetName( ?MyCallback());
????????System.out.println(
);
????????System.in.read();????
????}?
}
??? 执行上面的程序后,将输出如下的信息:????
异步调用!
火星
<span times="" new="" roman'"="" style="padding: 0px; margin: 0px; color: rgb(85,85); font-family: 宋体,serif; font-size: 10.5pt; line-height: 28px;">
??? ?? 在.net中也可以使用异步的方式来调用WebService,如在C#中可使用如下的代码来异步调用getName方法:
??回调方法 private ?getNameCompletedEvent(object?sender,?WSC.asyn.getNameCompletedEventArgs?e)
{
????listBox1.Items.Add(?e.Result.@
);
}
?button1_Click(object?sender,?EventArgs?e)
{??????????
????async.myService?my?
?WSC.async.myService();
????my.getNameCompleted?
+= ?WSC.async.getNameCompletedEventHandler(getNameCompletedEvent);
?????my.getNameAsync();
?????MessageBox.Show(
完成调用 );
}
???? 其中async 是引用MyService 的服务名。要注意的是,在C# 中不能在同一个WebService 实例的getName 方法未返回之前,再次调用该实例的getName 方法,否则将抛出异常。如下面的代码会抛出一个异常:
????async.myService?my? ?WSC.async.getNameCompletedEventHandler(getNameCompletedEvent);
??? my.getNameAsync();
????
??将抛出异常 ??? my.getNameAsync();
???? 但不同的WebService 实例的方法可以在方法未返回时调用,如下面的代码是可以正常工作的:
asyn.myService?my? ?WSC.asyn.myService();
my.getNameAsync();
my.getNameCompleted?
?WSC.asyn.getNameCompletedEventHandler(getNameCompletedEvent);
asyn.myService?my1?
?WSC.asyn.myService();
my1.getNameCompleted?
?WSC.asyn.getNameCompletedEventHandler(getNameCompletedEvent);
my1.getNameAsync();

本文出自 “李宁的极客世界” 博客,请务必保留此出处http://www.voidcn.com/article/p-fhppwswu-bkp.html

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读