`
yongguang423
  • 浏览: 107890 次
  • 性别: Icon_minigender_1
  • 来自: 山东
社区版块
存档分类
最新评论

Axis Web Service开发之旅 (十) --异步调用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 "火星";   
    }   
}  
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>  
<!--  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();   
    }   
}  
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();       
    }    
}  
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("完成调用");   
}  
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();  

   

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/crazystone4/archive/2009/06/20/4285777.aspx

分享到:
评论

相关推荐

    axis2_WebService_开发指南

    Axis 的简单准备 Axis 的入门实例 Axis 复杂对象类型的WebService Axis 的辅助工具发布、调用WebService ...Axis 异步调用WebService Axis 的Module 模块 Axis 使用SoapMonitar 监视WebService 的请求和响应信息

    axis2;WebService

    Axis的简单准备 Axis的入门实例 Axis复杂对象类型的WebService Axis的辅助工具发布、调用WebService ...Axis异步调用WebService Axis 的Module模块 Axis使用SoapMonitar监视WebService的请求和响应信息

    Axis2调用SAP Webservice源码

    Axis2调用SAP Webservice源码 使用Axis2 org.apache.axis2.eclipse.codegen.plugin_1.6.2.jar插件生成本地Java Proxy同事生成同步和异步调用测试用例 更重要的是配备详细文档,实乃Java与SAP集成是宝典!

    Axis2 WebService 开发指南 技术文档 入门文档

    Axis的简单准备 Axis的入门实例 Axis复杂对象类型的WebService Axis的辅助工具发布、调用WebService ... Axis异步调用WebService Axis 的Module模块 Axis使用SoapMonitor监视WebService的请求和响应信息

    Asix2 调用SAP PI Webservice

    使用axis2-eclipse-codegen-wizard-1.4生成代理方法调用SAP PI发布的Webservice,因为codegen-wizard不能识别Policy节点,所以需要手工将Policy节点删掉,此实例为异步场景 文档 + 代码 + Jar

    axis2_webservice

    Axis的简单准备 Axis的入门实例 Axis复杂对象类型的WebService Axis的辅助工具发布、调用WebService ...Axis异步调用WebService Axis的Module模块 Axis使用SoapMonitar监视WebService的请求和响应信息

    Java WebService 简单实例 方式二(axis1直接调用方式)

    NULL 博文链接:https://hyan.iteye.com/blog/2128321

    WebService大讲堂之Axis2

    WebService大讲堂之Axis2(8):异步调用WebService ................................................................................... 28 WebService大讲堂之Axis2(9):编写Axis2模块(Module) .................

    axis2-1.4.1及教程

    1):用POJO实现0配置的WebService 2):复合类型数据的传递 3):使用services.xml文件发布WebService ...8):异步调用WebService 9):编写Axis2模块(Module) 10):使用soapmonitor模块监视soap请求与响应消息

    编程入门_Eclipse教程

    3.1.5. 异步调用WebService 32 4. Eclipse中安装 Lomboz 35 4.1. 持久化对象与OID 35 4.1.1. 对持久化对象的要求 35 4.1.2. OID 36 5. Eclipse使用技巧 36 5.1. 一般插件安装 36 5.2. 自定义注释 37 5.3. 常用的...

    Axis2教程 包含描述目录的内容

    WebService大讲堂之Axis2系列教程 1. 用POJO实现0配置的WebService 2. 复合类型数据的传递 ... 异步调用WebService 9. 编写Axis2模块(Module) 10. 使用soapmonitor模块监视soap请求与响应消息

    axis2 教程_个人备用文档

    1. 用POJO实现0配置的WebService 2. 复合类型数据的传递 3. 使用services.xml文件发布WebService ... 异步调用WebService 9. 编写Axis2模块(Module) 10. 使用soapmonitor模块监视soap请求与响应消息

    AXIS2大讲堂文档

    文档1 pojo实现0配置 文档2 符合数据类型 文档3 使用services.xml发布webservice 文档4 二进制文件读取 文档5 会话管理 ...文档8 异步调用webservice 文档9 编写axis模块 文档10 使用moniter监视器

    JAVA的WebService支持CXF与SAAJ第三版

    这个教程将了如何使用CXF开发WebService,包括JAX-WS、JAX-RS规范、数字证书、MTOM附件传输、异步调用、异常处理、使用Axis+Spring解决RPC/Encode的问题向旧规范JAX-RPC的兼容,第三版版教程在最一开始分别介绍了...

    axis2编写发布和例子详解

    axis2入门学习资料,通过10个步骤详细例子(测试都能运行),简单阐述了ajax通过tomcat发布方法,session管理,异步调用和同步调用,spring整合等功能,说明,配置比较详细

    ASP EXCEL导入SQL

     客户端浏览器能够轻松通过Ajax实现REST资源的异步调用处理,同时也可以有效地减少应用服务器地压力  通过提供开放的RESTAPI,能够轻松实现与第三方的集成  平台服务  平台服务层的调用是通过RESTAPI进行的,...

Global site tag (gtag.js) - Google Analytics