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

系统 1948 0

本文为原创,如需转载,请注明作者和出处,谢谢!

上一篇: WebService大讲堂之Axis2(7):将Spring的装配JavaBean发布成WebService

在前面几篇文章中都是使用同步方式来调用 WebService 。也就是说,如果被调用的 WebService 方法长时间不返回,客户端将一直被阻塞,直到该方法返回为止。使用同步方法来调用 WebService 虽然很直观,但当 WebService 方法由于各种原因需要很长时间才能返回的话,就会使客户端程序一直处于等待状态,这样用户是无法忍受的。
当然,我们很容易就可以想到解决问题的方法,这就是多线程。解决问题的基本方法是将访问 WebService 的任务交由一个或多个线程来完成,而主线程并不负责访问 WebService 。这样即使被访问的 WebService 方法长时间不返回,客户端仍然可以做其他的工作。我们可以管这种通过多线程访问 WebService 的方式称为异步访问。
虽然直接使用多线程可以很好地解决这个问题,但比较麻烦。幸好 Axis2 的客户端提供了异步访问 WebService 的功能。
RPCServiceClient 类提供了一个 invokeNonBlocking 方法可以通过异步的方式来访问 WebService 。下面先来建立一个 WebService
MyService
是一个 WebService 类,代码如下:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> package service;
public class MyService
{
public StringgetName()
{
try
{
System.out.println(
" getName方法正在执行 " );
// 延迟5秒
Thread.sleep( 5000 );
}
catch (Exceptione)
{
}
return " 火星 " ;
}
}

为了模拟需要一定时间才返回的 WebService 方法,在 getName 方法中使用了 sleep 方法来延迟 5 秒。
下面是 MyService 类的配置代码:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> <!-- services.xml -->
< service name ="myService" >
< description >
异步调用演示
</ description >
< parameter name ="ServiceClass" >
service.MyService
</ parameter >
< messageReceivers >
< messageReceiver mep ="http://www.w3.org/2004/08/wsdl/in-out"
class
="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />
</ messageReceivers >
</ service >

从上面的配置代码可以看出, MyService 的配置方式与前几章的 WebService 的配置方式完全一样,也就是说, MyService 只是一个普通的 WebService
下面是异步调用 MyService Java 客户端代码:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> 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;

public class RPCAsyncClient
{
public static void main(String[]args) throws Exception
{
RPCServiceClientserviceClient
= new RPCServiceClient();
Optionsoptions
= serviceClient.getOptions();
EndpointReferencetargetEPR
= new EndpointReference(
" http://localhost:8080/axis2/services/myService " );
options.setTo(targetEPR);
Object[]opAddEntryArgs
= new Object[]{};
QNameopAddEntry
= new QName( " http://service " , " getName " );
serviceClient.invokeNonBlocking(opAddEntry,opAddEntryArgs,
new org.apache.axis2.client.async.AxisCallback()
{
@Override
public void onComplete()
{
}
@Override
public void onError(Exceptionarg0)
{
}}
@Override
public void onFault(MessageContextarg0)
{
}
@Override
public void onMessage(MessageContextmc)
{
// 输出返回值
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 方法被调用。当运行上面的程序后,将输出如下的信息:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> 异步调用!
火星

虽然上面的例子可以实现异步调用,但比较麻烦。为了更方便地实现异步调用,可以使用 wsdl2java 命令的 -a 参数生成可异步调用的 Stub 类。下面的命令可生成同步和异步调用的客户端代码(两个类),其中 -s 表示生成同步调用代码, -a 表示生成异步调用代码。

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> %AXIS2_HOME%\bin\wsdl2java-urihttp://localhost: 8080 /axis2/services/myService?wsdl-pclient-s-a-ostub

在执行上面的命令后,将生成两个类: MyServiceStub MyServiceCallbackHandler 类,其中 MyServiceStub 类负责同步和异步调用 WebService MyServiceCallbackHandler 类是一个抽象类,也是一个回调类,当使用异步方式调用 WebService 方法时,如果方法返回,则 MyServiceCallbackHandler 类的 receiveResultgetName 方法被调用。下面是使用 MyServiceStub 类异步访问 WebService 的代码:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> package client;

import client.MyServiceStub.GetNameResponse;

class MyCallback extends MyServiceCallbackHandler
{
@Override
public void receiveResultgetName(GetNameResponseresult)
{
// 输出getName方法的返回结果
System.out.println(result.get_return());
}
}
public class StubClient
{
public static void main(String[]args) throws Exception
{
MyServiceStubstub
= new MyServiceStub();
// 异步调用WebService
stub.startgetName( new MyCallback());
System.out.println(
" 异步调用! " );
System.in.read();
}
}

执行上面的程序后,将输出如下的信息:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> 异步调用!
火星

在.net中也可以使用异步的方式来调用WebService,如在C#中可使用如下的代码来异步调用getName方法:
<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> // 回调方法
private void getNameCompletedEvent(objectsender,WSC.asyn.getNameCompletedEventArgse)
{
listBox1.Items.Add(e.Result.@
return );
}
private void button1_Click(objectsender,EventArgse)
{
async.myServicemy
= new WSC.async.myService();
my.getNameCompleted
+= new WSC.async.getNameCompletedEventHandler(getNameCompletedEvent);
my.getNameAsync();
MessageBox.Show(
" 完成调用 " );
}

其中 async 是引用 MyService 的服务名。要注意的是,在 C# 中不能在同一个 WebService 实例的 getName 方法未返回之前,再次调用该实例的 getName 方法,否则将抛出异常。如下面的代码会抛出一个异常:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> async.myServicemy = new WSC.async.myService();
my.getNameCompleted
+= new WSC.async.getNameCompletedEventHandler(getNameCompletedEvent);
my.getNameAsync();
// 将抛出异常
my.getNameAsync();

但不同的 WebService 实例的方法可以在方法未返回时调用,如下面的代码是可以正常工作的:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> asyn.myServicemy = new WSC.asyn.myService();
my.getNameAsync();
my.getNameCompleted
+= new WSC.asyn.getNameCompletedEventHandler(getNameCompletedEvent);
asyn.myServicemy1
= new WSC.asyn.myService();
my1.getNameCompleted
+= new WSC.asyn.getNameCompletedEventHandler(getNameCompletedEvent);
my1.getNameAsync();

下一篇: WebService大讲堂之Axis2(9):编写Axis2模块(Module)

国内最棒的Google Android技术社区(eoeandroid),欢迎访问!

《银河系列原创教程》 发布

《Java Web开发速学宝典》 出版,欢迎定购

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


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论