博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
WebService大讲堂之Axis2(8):异步调用WebService
阅读量:6937 次
发布时间:2019-06-27

本文共 4892 字,大约阅读时间需要 16 分钟。

 
在前面几篇文章中都是使用同步方式来调用
WebService
。也就是说,如果被调用的
WebService
方法长时间不返回,客户端将一直被阻塞,直到该方法返回为止。使用同步方法来调用
WebService
虽然很直观,但当
WebService
方法由于各种原因需要很长时间才能返回的话,就会使客户端程序一直处于等待状态,这样用户是无法忍受的。

    
当然,我们很容易就可以想到解决问题的方法,这就是多线程。解决问题的基本方法是将访问
WebService
的任务交由一个或多个线程来完成,而主线程并不负责访问
WebService
。这样即使被访问的
WebService
方法长时间不返回,客户端仍然可以做其他的工作。我们可以管这种通过多线程访问
WebService
的方式称为异步访问。

    
虽然直接使用多线程可以很好地解决这个问题,但比较麻烦。幸好
Axis2
的客户端提供了异步访问
WebService
的功能。

    RPCServiceClient
类提供了一个
invokeNonBlocking
方法可以通过异步的方式来访问
WebService
。下面先来建立一个
WebService
    MyService
是一个
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
秒。
    
下面是MyService
类的配置代码:
<!--
  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
客户端代码:

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
    {
        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
                    
public
 
void
 onComplete()
                    {
                    }
                    @Override
                    
public
 
void
 onError(Exception arg0)
                    {
                    }                    }
                    @Override
                    
public
 
void
 onFault(MessageContext arg0)
                    {
                    }
                    @Override
                    
public
 
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%\bin\wsdl2java -uri http://localhost:
8080
/axis2/services/myService?wsdl -p client -s -a -o stub
    
在执行上面的命令后,将生成两个类:MyServiceStub
MyServiceCallbackHandler
类,其中MyServiceStub
类负责同步和异步调用WebService
MyServiceCallbackHandler
类是一个抽象类,也是一个回调类,当使用异步方式调用WebService
方法时,如果方法返回,则MyServiceCallbackHandler
类的receiveResultgetName
方法被调用。下面是使用MyServiceStub
类异步访问WebService
的代码:
package
 client;
import
 client.MyServiceStub.GetNameResponse;
class
 MyCallback 
extends
 MyServiceCallbackHandler
{
    @Override
    
public
 
void
 receiveResultgetName(GetNameResponse result)
    {
        
//
  输出getName方法的返回结果
        System.out.println(result.get_return());
    }
}
public
 
class
 StubClient
{
    
public
 
static
 
void
 main(String[] args) 
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
);
}
private
 
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.myService();
    my.getNameCompleted 
+=
 
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();
 本文转自 androidguy 51CTO博客,原文链接:http://blog.51cto.com/androidguy/215187,如需转载请自行联系原作者
你可能感兴趣的文章
帮助你检查Linux系统内存及其使用情况的命令
查看>>
Jeff Dean本科论文首次曝光!第一批90后出生时,他就在训练神经网络
查看>>
Python中lambda的用法
查看>>
E036-rpmdb open failed
查看>>
手把手:一张图看清编程语言发展史,你也能用Python画出来!
查看>>
使用MaxCompute进行数据质量核查
查看>>
SQLServer2005 判断数据库中是否存在某张表或是查找库中的所有表名,然后删除...
查看>>
awk工具
查看>>
mysql 常用日期处理函数
查看>>
使用python进行数据的采集 编辑 删除
查看>>
布尔类型及return 严重程度
查看>>
解决springboot程序员的一点小困惑,nginx的反向代理
查看>>
Java虚拟机基本结构的简单记忆
查看>>
hibernate查询返回结果值为实体时接收方法
查看>>
七牛云 ssl免费证书申请
查看>>
基于结构化平均感知机的分词器Java实现
查看>>
比较好的中文分词方案汇总推荐
查看>>
Chrome本地安装Metamask
查看>>
Tomcat介绍 (资源 )
查看>>
【2018.06.28学习笔记】【linux高级知识 17.1-17.5】
查看>>