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

简介:
  在前面几篇文章中都是使用同步方式来调用 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,如需转载请自行联系原作者

相关文章
|
Java C#
WebService大讲堂之Axis2(4):二进制文件传输
本文为原创,如需转载,请注明作者和出处,谢谢! 上一篇:WebService大讲堂之Axis2(3):使用services.xml文件发布WebService     在《WebService大讲堂之Axis2(2):复合类型数据的传递》中讲过,如果要传递二进制文件(如图像、音频文件等),可以使用byte[]作为数据类型进行传递,然后客户端使用RPC方式进行调用。
1086 0
|
C# Java
WebService大讲堂之Axis2(8):异步调用WebService
本文为原创,如需转载,请注明作者和出处,谢谢!     在前面几篇文章中都是使用同步方式来调用WebService。也就是说,如果被调用的WebService方法长时间不返回,客户端将一直被阻塞,直到该方法返回为止。
1102 0
|
应用服务中间件 网络架构 安全
WebService大讲堂之Axis2(9):编写Axis2模块(Module)
本文为原创,如需转载,请注明作者和出处,谢谢!     Axis2可以通过模块(Module)进行扩展。Axis2模块至少需要有两个类,这两个类分别实现了Module和Handler接口。
1045 0
|
Java 应用服务中间件 C#
WebService大讲堂之Axis2(2):复合类型数据的传递
本文为原创,如需转载,请注明作者和出处,谢谢! 上一篇:WebService大讲堂之Axis2(1):用POJO实现0配置的WebService     在实际的应用中,不仅需要使用WebService来传递简单类型的数据,有时也需要传递更复杂的数据,这些数据可以被称为复合类型的数据。
911 0