在前面几篇文章中都是使用同步方式来调用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();

Axis2(8):异步调用WebService的更多相关文章

  1. Axis2之异步调用

    本章主要介绍axis2接口的异步调用方式. 一般情况下,我们使用同步方法(invokeBlocking)调用axis2接口,如果被调用的WebService方法长时间不返回,客户端将一直被阻塞,直到该 ...

  2. 一个简单的webservice的demo(下)winform异步调用webservice

    绕了一大圈,又开始接触winform的项目来了,虽然很小吧.写一个winform的异步调用webservice的demo,还是简单的. 一个简单的Webservice的demo,简单模拟服务 一个简单 ...

  3. 异步调用webservice

    一.异步调用 asynchronous call(异步调用):一个可以无需等待被调用函数的返回值就让操作继续进行的方法 举例: 异步调用就是你 喊 你朋友吃饭 ,你朋友说知道了 ,待会忙完去找你 ,你 ...

  4. asp.net中异步调用WebService(异步页)[转]

    由于asp2.0提供了异步页的支持使异步调用WebService的性能有了真正的提升.使用异步页,首先要设置Async="true",异步页是在Prerender和Prerende ...

  5. asp.net中异步调用webservice

    WebService方法是不需要作任何修改的,只是在调用时采用异步的方式,这样在循环中,速度会显得快一点. 原来的方式: HotelMagWeb.com.china_sms.www.MainServi ...

  6. Asp.net 异步调用WebService

    //服务代码 [WebMethod] public string Test(int sleepTimes, int val) { Thread.Sleep(sleepTimes); var log = ...

  7. 浅谈WebService开发二(同步与异步调用)转

    上文 <http://www.dotnetgeek.cn/xuexiwebservice1.html>已经跟大家说了,如果创建一个webservice和简单的调用,本文将注重webserv ...

  8. 在Android 中使用KSOAP2调用WebService

    WebService 是一种基于SOAP协议的远程调用标准.通过WebService可以将不同操作系统平台,不同语言.不同技术整合到一起.在Android SDK中并没有提供调用WebService的 ...

  9. 浅谈WebService开发三(动态调用WebService)转

    在前两讲里,我已经向大家演示了如何使用WebService.同步, 异步调用WebService,而在实际开发过程中,可能会有多个WebService接口供你选择,而在程序执行过程中才决定使用哪一个 ...

随机推荐

  1. 统计难题(trie树)

    统计难题 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131070/65535 K (Java/Others)Total Submi ...

  2. poj 2155

    题目链接 二维树状数组 给出矩阵左上角和右下角坐标,矩阵里的元素 1变0 ,0 变1,然后给出询问,问某个点是多少. 树状数组下标不能为0 二维的每次更新都是从(1,1)到(x,y) 要更新(x1,y ...

  3. Android学习之DragEvent

    关于DragEvent Google Android API中是这么说的 Represents an event that is sent out by the system at various t ...

  4. SSIS: 使用最大ID和最大日期来增量更新表

    简单三步: 1.  新增变量 MaxID和MaxCreateDate以及Variable 2.  放置一个 Execute SQL  Task ,用SQL 来获取 MaxID和MaxCreateDat ...

  5. [译]Stairway to Integration Services Level 5 - 增量删除数据

    在 dbo.Contact中添加一行记录 Use AdventureWorks go Insert Into dbo.Contact (FirstName, MiddleName, LastName, ...

  6. URAL 1146 Maximum Sum 最大子矩阵和

    题目:click here #include <bits/stdc++.h> using namespace std; typedef unsigned long long ll; con ...

  7. OD调试篇1—Hello

    OD调试篇1—Hello 要求:通过OD将程序的标题“I love fishc.com”改为“I love you” 一.找到程序的标题“I love fishc.com” 1.把程序拖到OD运行出现 ...

  8. 微信开放平台 获取 component_verify_ticket

    <?php /** * @author zhaozhuobin * @date:2016-06=07 * */ namespace common\components;use DOMDocume ...

  9. [LeetCode]题解(python):009-Palindrome Number

    题目来源: https://leetcode.com/problems/palindrome-number/ 题意分析: 这题是要判断一个int是否一个回文数,要求不能申请额外的空间. 题目思路: 这 ...

  10. Qt 代码: 子窗口调用父窗口(其实就是用指针直接访问)

    之前的 Qt 编程大多只涉及简单的多窗口,并未染指窗口间的传值交互,想来还是“涉世未深”,对 Qt 的理解.应用还需殷勤努力. 这次的问题是这样的,我想要实现一个类似QQ.阿里旺旺的聊天客户端,在弹出 ...