精彩的人生

好好工作,好好生活

BlogJava 首页 新随笔 联系 聚合 管理
  147 Posts :: 0 Stories :: 250 Comments :: 0 Trackbacks

#

原文地址:http://javaresearch.org/article/showarticle.jsp?column=5&thread=50134


在进行所有的开发之前,自然是到http://xfire.codehaus.org下载最新的xfire的发布版本,在写这篇文档的时候,xfire最新的版本是xfire-distribution-1.1-beta-1版,从官方网站下载到本地机器后,解压,目录结构如下:

xfire-distribution-1.1-beta-1

|____api (javadoc文档)

|____sample (几个xfire例子)

|____lib (xfire所需的jars)

|____modules (xfire 模块)

|____xfire-all-1.1-beta-1.jar

|____几个授权和说明TXT文档

 

它所提供的例子需要Maven2编译执行,如果你还没有安装Maven,可以到apache网站下载安装。在你阅读的这篇教程的例子中,我将采用ant进行编译,毕竟Ant才是大家所常用的项目管理编译工具。

 

在你的tomcat的webapps建立一个web应用程序,例如xfire,目录结构如下:

       xfire

         |____WEB_INF

                |____web.xml

             |____classes

             |____lib

 

将下载解压的xfire-distribution-1.1-beta-1\lib文件夹下的所有的jar放入的这个lib文件夹下(tomcat/webapps/xfire/WEB-INF/lib)、将xfire-distribution-1.1-beta-1\xfire-all-1.1-beta-1.jar放入到tomcat/webapps/xfire/WEB-INF/lib文件夹下。

将xfire-distribution-1.1-beta-1\examples\book\src\webapp\WEB-INF下的web.xml文件复制到tomcat/webapps/xfire/WEB-INF文件夹下。

Web.xml的内容如下:
  1. <?xml version="1.0" encoding="ISO-8859-1"?>
  2. <!-- START SNIPPET: webxml -->
  3. <!DOCTYPE web-app
  4.     PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
  5.     "http://java.sun.com/dtd/web-app_2_3.dtd">
  6.    
  7. <web-app>
  8.   <servlet>
  9.     <servlet-name>XFireServlet</servlet-name>
  10.     <display-name>XFire Servlet</display-name>
  11.     <servlet-class>
  12.         org.codehaus.xfire.transport.http.XFireConfigurableServlet
  13.     </servlet-class>
  14.   </servlet>
  15.   <servlet-mapping>
  16.     <servlet-name>XFireServlet</servlet-name>
  17.     <url-pattern>/servlet/XFireServlet/*</url-pattern>
  18.   </servlet-mapping>
  19.   <servlet-mapping>
  20.     <servlet-name>XFireServlet</servlet-name>
  21.     <url-pattern>/services/*</url-pattern>
  22.   </servlet-mapping>
  23. </web-app>

启动tomcat,然后打开浏览器,在浏览器地址栏中输入http://localhost:8080/xfire/services/,如何能够正常显示页面,说明xfire就配置成功了。

 
这样,我们的XFire就配置完成了。
posted @ 2006-06-04 19:53 hopeshared 阅读(960) | 评论 (0)编辑 收藏

     摘要: Applying the Web services invocation framework Calling services independent of protocols 独立于协议的服务调用 ...  阅读全文
posted @ 2006-05-15 17:31 hopeshared 阅读(929) | 评论 (0)编辑 收藏

即使 SOAP 只是众多访问 Web 服务的可能的绑定之一,它已几乎成为 Web 服务的同义词。这意味着使用 Web 服务的应用程序通常通过绑到 SOAP 的特定实现的 API 来完成工作。本系列文章将描述一个更通用的、独立于 SOAP 的调用 Web 服务的方法,称之为“Web 服务调用框架”(Web Service Invocation Framework(WSIF))。它专门设计来直接调用用“Web 服务描述语言”(Web Services Description Language(WSDL))描述的 Web 服务,隐藏了底层访问协议(比如 SOAP)的复杂性。

Web 服务承诺为因特网分布式计算提供基于标准的平台,集中在简易性和灵活性。一种关键的 Web 服务技术是 WSDL,即“Web 服务描述语言”。使用 WSDL,开发者可以以抽象的形式描述 Web 服务,与用在其它分布式计算框架(比如 CORBA)的现有“接口描述语言”(Interface Description Language(IDL))类似。WSDL 也使 Web 服务开发者能够给服务指定具体的绑定。并且这些绑定描述怎样将抽象服务描述映射到特定访问协议。WSDL 的这部分是可扩展的,这就是说任何人都可以提出他们自己的绑定,使之可能通过某个定制的协议访问服务。

因此,从某种程度来说,使用 Web 服务是一种挑战。对于同样的服务可以有多个绑定。这些绑定中的一些可能适合于一些情形,其它可能适合于另外的情形。绑定本身可以代表抽象服务描述到用来访问服务的任意一种协议的映射。虽然有多种选择使用服务和允许绑定扩展是很有用的,但这给客户机以统一方式查看服务造成了困难。

我以当前客户机端 API 及其性能的讨论开始这篇文章。我将通过讨论来激发人们对 WSIF,即“Web 服务调用框架”的需要,然后继续进行 WSIF 的概述。

当前的调用风格及其缺点
用于 Web 服务的 SOAP 绑定是 WSDL 规范的一部分。在大多数编程语言中,该协议有可用的实现和工具,在许多情况下是免费的。这样,它使得开发者能以微乎其微的成本进行用于 Web 服务的独立于平台的开发。

因此,下述情况是不足为奇的:大多数开发者当想到使用 Web 服务时,在他们头脑中出现的是使用某个 SOAP 客户机 API 来装配一个 SOAP 消息并将它经由网络发送到服务端点。例如,使用 Apache SOAP,客户机将创建和植入一个 Call 对象。它封装了服务端点、要调用的 SOAP 操作的标识、必须发送的参数等等。而这是对 SOAP 而言,它仅限于将其用作调用 Web 服务的一般模型,这是因为下面的原因:

  • Web 服务不仅仅是 SOAP 服务
    将 Web 服务视为 SOAP 上提供的服务的同义词。这是对 Web 服务狭隘的见解。带有功能方面和访问协议 WSDL 描述的任何一段代码均可以被认为是 Web 服务。WSDL 规范为 Web 服务定义了 SOAP 绑定,但是原则上可能要添加绑定扩展,这样,例如,使用 RMI/IIOP 作为访问协议,EJB 就可以作为 Web 服务来提供。或者您甚至可以想象任意一个 Java 类可以被当作 Web 服务,以本机 Java 调用作为访问协议。就这个更广阔的 Web 服务定义来说,您需要用于服务调用的独立于绑定的机制。
  • 将客户机代码绑到一个特殊的协议实现要受到限制
    将客户机代码紧密地绑定到特殊的协议实现的客户机库造成了难以维护的代码。让我们假设您在客户机端有一个用 Apache SOAP v2.1 调用 Web 服务的应用程序。如果您想利用 v2.2 中出现的新的功能和错误修正,您将不得不更新所有的客户机代码,这是一项耗时的任务,将涉及到常见的令人头痛的迁移问题。类似的,如果您想从 Apache SOAP 移到一个不同的 SOAP 实现,这个过程并非无关紧要。所需要的是用于服务调用的独立于协议实现的机制。
  • 将新的绑定融入到客户机代码是很困难的。
    WSDL 允许有定义新的绑定的可扩展性元素。这使开发者能够定义绑定,这种绑定允许使用某种定制协议的代码作为 Web 服务。但是,事实上实现起来是很困难的。将不得不设计使用该协议的客户机 API 。应用程序本身可能正是使用 Web 服务的抽象接口,因此将必须编写一些工具来生成启用抽象层的存根。这些又一次是并非无关紧要的而且耗时的任务。所需要的是使绑定能够被更新或新的绑定能够容易地插入的服务调用机制。
  • 可以以灵活的方式使用多绑定
    例如,设想您已经成功地部署了一个应用程序,该应用程序使用提供多绑定的 Web 服务。为了使这个示例更具体,假设您有用于服务的 SOAP 绑定和允许您将本地服务实现(一个 Java 类)作为 Web 服务的本地 Java 绑定。显而易见,如果客户机部署在与服务本身相同的环境中,只能使用面向服务的本地 Java 绑定,并且如果情况确实如此,通过直接进行 Java 调用而不是使用 SOAP 绑定与服务进行通信将高效得多。Java 绑定作为一种快捷访问机制。接下来,想要利用多绑定可用性的客户机将必须具有一种能力 — 根据运行时信息对要用的实际绑定进行切换的能力。因此为了利用提供多绑定的 Web 服务,您需要一种服务调用机制,允许您在运行时在可用的服务绑定之间进行切换,而不需要生成或重编译存根。

介绍 WSIF
“Web 服务调用框架”(WSIF)是为调用 Web 服务提供简单 API 的工具箱,而不管服务怎样提供或由哪里提供。它具有上面讨论中我确定的所有功能:

  • 有给任何 Web 服务提供独立于绑定访问的 API。
  • 提供端口类型编译器来生成允许使用抽象服务接口的调用的存根。
  • 允许无存根(完全动态)的 Web 服务调用。
  • 可以在运行时将更新的绑定实现插入到 WSIF。
  • 可以在运行时插入的新的绑定。
  • 允许将绑定选择延后到运行时。

分析 WSIF 的客户机 API
为了进行讨论,我将使用很常见的股票报价程序 — Web 服务的“Hello World”示例。请考虑下面清单 1 所示的使用 WSDL 的抽象服务描述。

清单 1:股票报价 Web 服务的 WSDL 描述

<?xml version="1.0" ?> 
<definitions targetNamespace="http://www.ibm.com/namespace/wsif/samples/stockquote-interface" 
             xmlns:tns
="http://www.ibm.com/namespace/wsif/samples/stockquote-interface" 
             xmlns:xsd
="http://www.w3.org/1999/XMLSchema" 
             xmlns
="http://schemas.xmlsoap.org/wsdl/"> 
  
<message name="GetQuoteInput"> 
    
<part name="symbol" type="xsd:string"/> 
  
</message> 
  
<message name="GetQuoteOutput"> 
    
<part name="quote" type="xsd:float"/> 
  
</message> 
  
<portType name="StockquotePT"> 
    
<operation name="getQuote"> 
      
<input message="tns:GetQuoteInput"/> 
      
<output message="tns:GetQuoteOutput"/> 
    
</operation> 
  
</portType> 
</definitions>


足够简单:它描述了只带有由一个端口类型提供一个操作的服务。该操作等待一个字符串,被解释为股票的报价机符号,然后返回当前该股票报价,一个浮点值。为了实际使用该服务,您需要某个定义访问机制的绑定以及该绑定的服务端点。清单 2 展示了该服务的 SOAP 绑定:

清单 2:股票报价 Web 服务的 SOAP 绑定

<?xml version="1.0" ?> 
<definitions targetNamespace="http://www.ibm.com/namespace/wsif/samples/stockquote" 
             xmlns:tns
="http://www.ibm.com/namespace/wsif/samples/stockquote" 
             xmlns:tns-int
="http://www.ibm.com/namespace/wsif/samples/stockquote-interface" 
             xmlns:xsd
="http://www.w3.org/1999/XMLSchema" 
             xmlns:soap
="http://schemas.xmlsoap.org/wsdl/soap/" 
             xmlns:java
="http://schemas.xmlsoap.org/wsdl/java/" 
             xmlns
="http://schemas.xmlsoap.org/wsdl/"> 
  
<import namespace="http://www.ibm.com/namespace/wsif/samples/stockquote-interface" 
          location
="stockquote-interface.wsdl"/> 
  
<binding name="SOAPBinding" type="tns-int:StockquotePT"> 
    
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> 
    
<operation name="getQuote"> 
      
<soap:operation soapAction="http://example.com/GetTradePrice"/> 
      
<input> 
        
<soap:body use="encoded" 
                   namespace
="urn:xmltoday-delayed-quotes" 
                   encodingStyle
="http://schemas.xmlsoap.org/soap/encoding/"/> 
      
</input> 
      
<output> 
        
<soap:body use="encoded" 
                   namespace
="urn:xmltoday-delayed-quotes" 
                   encodingStyle
="http://schemas.xmlsoap.org/soap/encoding/"/> 
      
</output> 
    
</operation> 
  
</binding> 
  
<service name="StockquoteService"> 
    
<documentation>Stock quote service</documentation> 
    
<port name="SOAPPort" binding="tns:SOAPBinding"> 
      
<soap:address location="http://localhost:8080/soap/servlet/rpcrouter"/> 
    
</port> 
  
</service> 
</definitions>

这是一个标准的 SOAP 绑定,使用 RPC 风格和作为传输协议的 HTTP 与服务进行通信。在文档的 port 部分中,我定义了使用 SOAP 绑定可以访问服务的 URI。在清单 3 中,我将就通过 Apache SOAP 2.2 客户机端 API 和 WSIF 的客户机 API 使用该服务进行对比。

清单 3:用于服务访问的 Apache SOAP API 与 WSIF API 对比

Apache SOAP API

// Step 1: identify the service 
 Call call = new Call(); 
 call.setTargetObjectURI(
"urn:xmltoday-delayed-quotes"); 
 
// Step 2: identify the operation 
 call.setMethodName("getQuote"); 
 call.setEncodingStyleURI(encodingStyleURI); 
 
// Step 3: identify the parameters 
 Vector params = new Vector(); 
 params.addElement(
new Parameter("symbol"
                          String.
class, symbol, null));
 call.setParams(params); 
 
// Step 4: execute the operation 
 Response resp = call.invoke(url, 
                   
"http://example.com/GetTradePrice");
 
// Step 5: extract the result or fault 
 if(resp.generatedFault()) 
 

   Fault fault 
= resp.getFault(); 
   System.out.println(
"Ouch, the call failed: "); 
   System.out.println(
"  Fault Code   = " +  
                      fault.getFaultCode()); 
   System.out.println(
"  Fault String = " +  
                      fault.getFaultString()); 
   
throw new SOAPException("Execution failed " + fault); 
 }
 
 
else 
 

   Parameter result 
= resp.getReturnValue(); 
   
return ((Float) result.getValue()).floatValue(); 
 }


WSIF API

// Step 1: identify the service 
 Definition def = WSIFUtils.readWSDL(null,wsdlLocation);
 
// Step 2: identify the operation (choose an 
 
// appropriate service port) 
 WSIFDynamicPortFactory portFactory = 
        
new  WSIFDynamicPortFactory(def, nullnull); 
 
// Get default port 
 WSIFPort port = portFactory.getPort(); 
 
// The user can also explicitly select a port  
 
// to use. 
 
// WSIFPort port =  
 
//             portFactory.getPort("SOAPPort"); 
 
// Step 3: identify the parameters 
 
// Prepare the input message 
 WSIFMessage input = port.createInputMessage(); 
 input.setPart(
"symbol",  
               
new WSIFJavaPart(String.class, symbol));
 
// Prepare a placeholder for the output value 
 WSIFMessage output = port.createOutputMessage(); 
 
// Step 4: execute the operation 
 port.executeRequestResponseOperation("getQuote"
                             input, output, 
null);
 
// Step 5: extract the result or fault 
 WSIFPart part = output.getPart("quote"); 
 
return ((Float)part.getJavaValue()).floatValue();


正如您可以看到的,WSIF 的 API 由以 WSDL 编写的抽象服务描述驱动;它完全从实际使用的绑定中分离出来。该调用 API 是面向 WSDL 的,并且使用它更自然,因为它使用 WSDL 术语引用消息部件(message part)、操作等等。当您阅读一个 WSDL 描述,出于直觉会想到选用支持所需端口类型的端口,然后通过提供必需抽象输入消息(由必要部件组成)调用操作(不用担心怎样将消息映射到特定的绑定协议);WSIF API 就是这样设计的。

常用的 API,比如上面所示的 Apache SOAP API 采用了以特殊协议为中心的概念,比如在使用 SOAP 的情况下,目标 URI 和编码风格。这是不可避免的,因为 API 不是普遍适用于 WSDL,而是为特殊的协议设计。

两种使用 WSIF 的调用模型
WSIF 允许 Web 服务以两种方式调用。一种是无存根的动态调用,它要求直接使用 WSIF API;另一种是通过生成允许应用程序使用 Java 接口(直接对应于 WSDL 端口类型)和隐藏了 WSIF API 的存根的调用。

无存根(动态的)调用
访问 Web 服务所需的所有信息 — 抽象接口、绑定和服务端点可以通过 WSDL 得到。如果您仔细查看上面的客户机 API 示例,您将会注意到唯一由用户提供的信息是用于服务的 WSDL 文件位置和所需要的股票报价符号。很明显接下来是用 WSFL API 在运行时装入这个服务和进行该调用。

WSIF 分发包包含了演示怎样执行 WSDL 的任意一个操作的 DynamicInvoker。它以 WSDL 文件的 URI 和所需的操作参数作为命令行参数(在最初的实现中只接受简单的类型,如字符串),并且直接使用 WSIF API 完成工作。其用来调用股票报价服务的示例如清单 4 所示;您可以在包含 WSIF 分发包的文档中查找详细信息。

因为这类调用不会导致生成存根类,并且不需要单独的编译周期,所以它很方便。

清单 4:使用 DynamicInvoker 访问股票报价服务

java clients.DynamicInvoker http://services.xmethods.net/soap/urn:
    xmethods-delayed-quotes.wsdl getQuote IBM
Reading WSDL document from 'http://services.xmethods.net/soap/urn:
    xmethods-delayed-quotes.wsdl'
Preparing WSIF dynamic invocation
Executing operation getQuote
Result:
Result=108.8
Done!

使用存根的调用
在应用程序需要更抽象的服务视图和不希望处理 WSIF 客户机 API 的情况下,无存根调用不适用。WSIF 提供一个端口编译器,如果给定一个 WSDL,与所用到的复杂类型的 Java 等价物(以 JavaBean 的形式)一起,端口编译器将为每一个端口类型生成一个客户机存根。使用生成存根的应用程序可以利用抽象服务接口,并且这样与协议和 WSIF 客户机 API 分离。对于实际服务调用,这些存根使用缺省端口。通过由 WSIF 的端口类型编译器生成的存根使用股票报价服务的示例如清单 5 所示。

清单 5:使用生成存根的 WSIF 访问股票报价服务。

StockquotePT service = new StockquotePTStub(WSIFUtils.readWSDL(null, wsdlLocation), 
    
nullnull);
float quote = service.getQuote("IBM");
System.err.println (
">> Received quote: "+quote);

值得注意的是存根驻留在某些受管环境(如应用程序服务器)的情况,它们能够被定制;例如,可以改变负责返回恰当端口的工厂来定制端口选择算法,或者可以改变用于调用自身的实际端口。

在这篇文章中,我略述了对 WSIF 的需要,分析其通过高级 API 进行独立于绑定的服务访问的主要特征以及生成可定制的存根(通过其抽象接口使用服务)的端口类型编译器的可用性。直接通过 SOAP 客户机 API 和使用 WSIF API 进行服务访问之间的对比展示了 WSIF(由服务的 WSDL 描述驱动)怎样将 Web 服务调用的全部问题从以绑定为中心的观点转移到更抽象的级别。这是 WSIF 的设计原则之一,使服务绑定能被看作是根据特殊协议进行调用所需的代码片断,可以在任何时候插入它们。

在接下来的文章,我将分析 WSIF 的体系结构,看一看它怎样允许新的或更新的绑定实现被插入,它怎样使定制的类型系统用于 Web 服务以及怎样使运行时环境使用定制的探索性方法在多端口之间进行选择。

参考资料

  • 请参加关于这篇文章的讨论论坛
  • 请下载 alphaworks 上的 WSIF 分发包,并且试验比较简单的样本。它将给您一个由 WSIF 支持的不同调用风格的第一手示例以及它优于特定协议客户机 API 的优势。
  • 重温 WSDL 规范,看一看允许哪一种扩展;如果用来为访问 Web 服务定义 SOAP 绑定,您也可以学习 WSDL 的扩展机制。
  • 重温 SOAP 规范本身。
  • 如果以前您没有对 Web 服务编过程,Web Services Toolkit 是很好的起点。
  • 请查看 WSDL4J,一个可扩展的 WSDL 分析框架,WSIF 在此基础上进行构建。

关于作者
Nirmal K. Mukhi 是 IBM 的 T J Watson Research Lab 的副研究员,自 2000 年 11 月,他一直在从事各种 Web 服务技术的研究。他还对 AI、创造性写作以及过时的计算机游戏感兴趣。您可以通过
nmukhi@us.ibm.com 与 Nirmal 联系。




转载自:http://www.itepub.net/page/article/htmldata/2004_10/17/76/article_3575_1.html
posted @ 2006-05-15 17:20 hopeshared 阅读(554) | 评论 (0)编辑 收藏

我们都知道,RDF只表示二元关系,但在实际应用中,多元关系非常常见,如:小红借给小明语文书,是个三元关系: borrow(小红,语文书,小明); 再如,小明的身高是170cm.也是个三元关系 length(小明,170, cm). 推广来说,n元关系如何在RDF和OWL中表示呢?

我们假设三元组为(a,b,c). a,b.c 都是资源或Literal

1. 方法一
如果三元组中a是老大,即有个资源的地位是支配性的,如:小明的身高是170cm.
表示方法为 把老大提出来,再把三元关系分解为3个二元关系:
  R1(a, a’) , R2(a’,b),  R3(a’,c)  // R1(a, a’) 用RDF三元组表示为 (a , R1 , a’)
例如:小明的例子可以表示为
length(小明,length_obj_1);  //小明是老大, length_obj_1 是一个身高对象 
value(length_obj_1,170);     //值
unit(length_obj_1,cm);      //单位
2. 方法二
如果三元组中没有明显的老大,如: 小红借给小明语文书.
表示方法为提出一个对象,每个元素都和这个对象有关系:
R1(g, a) , R2(g,b),  R3(g, c)
例如:小红借书的例子可以表示为
rdf:type (borrow_obj_1,  BorrowRelation); // BorrowRelation 是一个表示借书关系的类
borrow_owner((borrow_obj_1,小红); 
borrow_agent((borrow_obj_1,小明); //借书的人
borrow_book((borrow_obj_1, 语文书);


3. 结论
1) n-元关系有2exp(n-2) 种表示方法: 二元关系一种表示法,三元关系有如上二种表示法,由数学归纳法得证。
2) 如果用RDF对复杂系统建模,有必要引入一个中间的抽象层,用以表示N元关系,还有named graph, context 等。如引入rdfe:relation(a,b,c,d,….)表示n元关系 
3) n-关系的表示对RDF数据的查询和存储优化很有价值,因为n-关系往往对应了数据库中的表。


注:大部分摘译自: 
http://www.w3.org/2001/sw/BestPractices/OEP/n-aryRelations-20040623/

更为详细的信息也参考它。

原文地址:http://bbs.w3china.org/dispbbs.asp?boardID=2&ID=8416

posted @ 2006-05-10 10:31 hopeshared 阅读(819) | 评论 (0)编辑 收藏

 

在网络中为了保证数据的实时性,需要对数据进行异步操作。Java Web Service和J2EE中的异步操作通过java消息机制来完成,消息机制是非常完善的技术了。而Microsoft的Web Service的异步功能是怎样完成的呢?怎样才能达到java的境地呢?当然,Microsoft有自己的一套。

众所周知,Web Service是靠SOAP协议进行数据传输的。而SOAP是基于XML技术之上的。SOAP协议是连接客户和服务器的桥梁。而SOAP协议本身没有异步功能,需要在客户端实现异步调用。我们以一个简单的Web Service的例子来说明这一点。

一、MathService.asmx

<%@ WebService Language="C#" Class="MathService" %>

using System;

using System.Web.Services;

[WebService]

public class MathService : WebService {

[WebMethod]

public float Add(float a, float b)

{

return a + b;

}

[WebMethod]

public double Subtract(double a, double b)

{

return a - b;

}

[WebMethod]

public float Multiply(float a, float b)

{

return a * b;

}

[WebMethod]

public float Divide(float a, float b)

{

if (b==0) return -1;

return a / b;

}

}

这是个实现了加,减,乘,除的Web Service,任何客户端程序都可以调用它。下面我们用wsdl(微软公司提供)工具产生一个MathService.asmx 的客户代理程序:wsdl /n:MyMath http://localhost/mathservice.asmx (假设MathService.asmx放在IIS服务器的根目录) ,产生一个MathService.cs代理程序,默认是SOAP协议。

二、MathService.cs:

namespace MyMath{

using System.Diagnostics;

using System.Xml.Serialization;

using System;

using System.Web.Services.Protocols;

using System.ComponentModel;

using System.Web.Services;

[System.Diagnostics.DebuggerStepThroughAttribute()]

[System.ComponentModel.DesignerCategoryAttribute("code")]

[System.Web.Services.WebServiceBindingAttribute(Name="MathServiceSoap", Namespace="http://tempuri.org/")]

public class MathService : System.Web.Services.Protocols.SoapHttpClientProtocol {

public MathService() {

this.Url = "http://localhost/mathservice.asmx";

}

[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/Add", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]

public System.Single Add(System.Single a, System.Single b) {

object[] results = this.Invoke("Add", new object[] {

a,

b});

return ((System.Single)(results[0]));

}

public System.IAsyncResult BeginAdd(System.Single a, System.Single b, System.AsyncCallback callback, object asyncState) {

return this.BeginInvoke("Add", new object[] {

a,

b}, callback, asyncState);

}

/// <remarks/>

public System.Single EndAdd(System.IAsyncResult asyncResult) {

object[] results = this.EndInvoke(asyncResult);

return ((System.Single)(results[0]));

}

/// <remarks/>

[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/Subtract", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]

public System.Double Subtract(System.Double a, System.Double b) {

object[] results = this.Invoke("Subtract", new object[] {

a,

b});

return ((System.Double)(results[0]));

}

/// <remarks/>

public System.IAsyncResult BeginSubtract(System.Double a, System.Double b, System.AsyncCallback callback, object asyncState) {

return this.BeginInvoke("Subtract", new object[] {

a,

b}, callback, asyncState);

}

/// <remarks/>

public System.Double EndSubtract(System.IAsyncResult asyncResult) {

object[] results = this.EndInvoke(asyncResult);

return ((System.Double)(results[0]));

}

/// <remarks/>

[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/Multiply", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]

public System.Single Multiply(System.Single a, System.Single b) {

object[] results = this.Invoke("Multiply", new object[] {

a,

b});

return ((System.Single)(results[0]));

}

/// <remarks/>

public System.IAsyncResult BeginMultiply(System.Single a, System.Single b, System.AsyncCallback callback, object asyncState) {

return this.BeginInvoke("Multiply", new object[] {

a,

b}, callback, asyncState);

}

/// <remarks/>

public System.Single EndMultiply(System.IAsyncResult asyncResult) {

object[] results = this.EndInvoke(asyncResult);

return ((System.Single)(results[0]));

}

/// <remarks/>

[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/Divide", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]

public System.Single Divide(System.Single a, System.Single b) {

object[] results = this.Invoke("Divide", new object[] {

a,

b});

return ((System.Single)(results[0]));

}

/// <remarks/>

public System.IAsyncResult BeginDivide(System.Single a, System.Single b, System.AsyncCallback callback, object asyncState) {

return this.BeginInvoke("Divide", new object[] {

a,

b}, callback, asyncState);

}

/// <remarks/>

public System.Single EndDivide(System.IAsyncResult asyncResult) {

object[] results = this.EndInvoke(asyncResult);

return ((System.Single)(results[0]));

}

}

}

之后我们用csc /t:library MathService.cs编译并产生一个MathService.dll.

现在我们可以写任何的客户程序去调用服务器上的MathService.asmx。

如:WinForm, C#,ASPX等。

下面我们写一个test.cs去测试异步调用:

三、test.cs:

using System;

public class test{

public static void Main(){

MyMath.MathService math = new MyMath.MathService();

IAsyncResult result1 = math.BeginAdd(10,20,null,null);

Object result=math.EndAdd(result1);

Console.WriteLine("result =========="+result);

}

}

我们看到它是先调用代理MathService.cs中的BeginAdd方法,然后状态信息保存在IasyncResult中,直到调用了EndAdd方法才返回调用的确切值。本例是远端调用MathService.asmx中的Add方法。

那Microsoft到底怎样实现客户端的异步呢?设计模式又是怎样的呢?

异步模式所提供的革新之一就是调用方确定特定调用是否应是异步的。  对于被调用的对象,没有必要执行附加的编程来用于支持其客户端的异步行为;在该模式中异步委托提供此功能。公共语言运行库处理调用方和被调用的对象视图之间的差异。被调用的对象可以选择显式支持异步行为,这或者是因为它可以比一般结构更为有效地实现异步行为,或者是因为它想只支持其调用方的异步行为。但是,建议这种被调用的对象遵循公开异步操作的异步设计模式。

类型安全是异步模式的另一项革新。尤其对于异步委托,针对 .NET 框架和公共语言运行库的语言编译器可令映射到规则 Invoke 方法的开始和结束操作(例如,BeginInvoke 和 EndInvoke)的方法签名是类型安全的。这是十分重要的,因为编译器为异步委托将同步调用拆分成开始和结束操作,使其能够只传递有效参数。

在此模式中所蕴含的基本想法如下所示:

1.调用方确定特定调用是否应是异步的。

2. 对于被调用的对象,没有必要由其客户端执行附加的编程来用于支持异步行为。公共语言运行库结构应该能够处理调用方和被调用的对象视图之间的差异。

3. 被调用的对象可以选择显式支持异步行为,这或者是因为它可以比一般结构更为有效地实现异步行为,或者是因为它想只支持其调用方的异步行为。但是,建议这种被调用的对象遵循公开异步操作的异步设计模式。

4. 编译器为 BeginInvoke 和 EndInvoke 以及异步委托生成类型安全方法签名。

5. .NET 框架提供支持异步编程模型所需的服务。此类服务的部分列表示例是:

(1)同步基元,例如监视器和阅读器编写器锁定。

(2)线程和线程池。

(3)同步构造,例如支持等候对象的容器。

(4)向基础结构片(例如 IMessage 对象和线程池)公开。

该模式将一个同步调用拆分成各构成部分:开始操作、结束操作和结果对象。考虑以下示例,在其中可能要用大量时间来完成 Factorize 方法。

public class PrimeFactorizer

{

public bool Factorize(int factorizableNum, ref int primefactor1, ref int primefactor2)

{

// Determine whether factorizableNum is prime.

// If is prime, return true. Otherwise, return false.

// If is prime, place factors in primefactor1 and primefactor2.

}

}

如果遵循异步模式,则类库编写器添加 BeginFactorize 和 EndFactorize方法,这两个方法将同步操作拆分成两个异步操作:

public class PrimeFactorizer

{

public bool Factorize(

    int factorizableNum,

    ref int primefactor1,

    ref int primefactor2)

{

// Determine whether factorizableNum is prime.

// if is prime, return true; otherwise return false.

// if is prime palce factors in primefactor1 and primefactor2

}

public IAsyncResult BeginFactorize(

   int factorizableNum,

   ref int primefactor1,

   ref int primefactor2,

   AsyncCallback callback,

   Object state)

{

 // Begin the factorizing asynchronously, and return a result object,

}

public bool EndFactorize(

   ref int primefactor1,

   ref int primefactor2,

   IAsyncResult asyncResult

 )

{

// End (or complete) the factorizing, and

// return the results,

// and obtain the prime factors.

}

}

服务器将异步操作拆分成两个逻辑部分:采用来自客户端的输入并调用异步操作的部分,向客户端提供异步操作结果的部分。

除了异步操作所需的输入外,第一部分还采用在完成异步操作时后要被调用的 AsyncCallback 委托。第一部分返回一个可等待的对象,该对象实现客户端使用的 IAsyncResult 接口来确定异步操作的状态。

服务器还利用它返回到客户端的可等待的对象来维护与异步操作关联的任何状态。通过提供可等待的对象,客户端使用第二部分获取异步操作的结果。

可用于客户端来启动异步操作的选项有:

在开始异步调用时提供回调委托。

 public class Driver1

   {

     public PrimeFactorizer primeFactorizer;

     public void Results(IAsyncResult asyncResult)

    {

     int primefactor1=0;

      int primefactor2=0;

      bool prime = primeFactorizer.EndFactorize(

         ref primefactor1,

         ref primefactor2,

         asyncResult);

    }

     public void Work()

     {

      int factorizableNum=1000589023,

      int primefactor1=0;

      int primefactor2=0;

      Object state = new Object();

      primeFactorizer = new PrimeFactorizer();

      AsyncCallback callback = new Callback(this.Results);

      IAsyncResult asyncResult =                      primeFactorizer.BeginFactorize(

       factorizableNum,

       ref primefactor1,

       ref primefactor2,

       callback,

       state);

    } 

在开始异步调用时不提供回调委托。

public class Driver2

{

public static void Work()

{

int factorizableNum=1000589023,

int primefactor1=0;

int primefactor2=0;

Object state = new Object();

PrimeFactorizer primeFactorizer = new PrimeFactorizer();

AsyncCallback callback = new Callback(this.Results);

IAsyncResult asyncResult = primeFactorizer.BeginFactorize(

factorizableNum,

ref primefactor1,

ref primefactor2,

callback,

state);

bool prime = primeFactorizer.EndFactorize(

ref primefactor1,

ref primefactor2,

asyncResult);

}

}

我们以.Net的一个例子来说明这一点:

AsyncDelegate2.cs

using System;

using System.Threading;

using System.Runtime.Remoting;

using System.Runtime.Remoting.Messaging;

public class Wak

{

public int Pat(int i)

{

Console.WriteLine("Hash: {0} Wak Pat", Thread.CurrentThread.GetHashCode());

return i*2;

}

};

public delegate int WakPatDelegate(int i);// 异步调用的委派.

public class Simple

{

public static void SomeMethod(IAsyncResult ar)

{

// Obtain value from AsyncState object

int value = Convert.ToInt32(ar.AsyncState);

// Obtain results via EndInvoke

int result = ((WakPatDelegate)((AsyncResult)ar).AsyncDelegate ).EndInvoke(ar);

Console.WriteLine("Simple.SomeMethod (AsyncCallback): Result of {0} in Wak.Pak is {1} ",value, result);

}

public static void Main(String[] args)

{

Console.WriteLine("Thread Simple Context Sample");

Console.WriteLine("");

Console.WriteLine("Make an instance of a context-bound type Wak");

Wak oWak = new Wak();

int value=0;

int result=0;

Console.WriteLine("Make a sync call on the object");

value = 10;

result = oWak.Pat(value);

Console.WriteLine("Result of {0} in Wak.Pak is {1} ",value, result);

Console.WriteLine("Make single Async call on Context-bound object");

WakPatDelegate wpD1 = new WakPatDelegate(oWak.Pat);

value = 20;

IAsyncResult ar1 = wpD1.BeginInvoke(value,null,null);

ar1.AsyncWaitHandle.WaitOne();

result = wpD1.EndInvoke(ar1);

Console.WriteLine("Result of {0} in Wak.Pak is {1} ",value, result);

Console.WriteLine("Make single Async call on Context-bound object - use AsyncCallback and StateObject");

WakPatDelegate wpD2 = new WakPatDelegate(oWak.Pat);

value = 30;

IAsyncResult ar2 = wpD2.BeginInvoke(

value,

new AsyncCallback(Simple.SomeMethod),

value

);

Console.WriteLine("Make multiple Async calls on Context-bound object");

int asyncCalls = 5;

IAsyncResult[] ars = new IAsyncResult[asyncCalls];

WaitHandle[] whs = new WaitHandle[asyncCalls];

int[] values = new int[asyncCalls];

WakPatDelegate wpD3 = new WakPatDelegate(oWak.Pat);

for (int i=0; i < asyncCalls; i++)

{

values[i] = i;

ars[i] = wpD3.BeginInvoke(values[i],null,null);

whs[i] = ars[i].AsyncWaitHandle;

}

WaitHandle.WaitAll(whs,1000, false);

for (int i=0; i < asyncCalls; i++)

{

result = wpD3.EndInvoke(ars[i]);

Console.WriteLine("Result of {0} in Wak.Pak is {1} ",values[i], result);

}

Console.WriteLine("");

Console.WriteLine("Done");

}

}

    

如果异步调用成功,将显示:

Thread Simple Context Sample

Make an instance of a context-bound type Wak

Make a sync call on the object

Hash: 3 Wak Pat

Result of 10 in Wak.Pak is 20

Make single Async call on Context-bound object

Hash: 16 Wak Pat

Result of 20 in Wak.Pak is 40

Make single Async call on Context-bound object - use AsyncCallback and StateObje

ct

Hash: 16 Wak Pat

Make multiple Async calls on Context-bound object

Simple.SomeMethod (AsyncCallback): Result of 30 in Wak.Pak is 60

Hash: 16 Wak Pat

Hash: 16 Wak Pat

Hash: 16 Wak Pat

Hash: 16 Wak Pat

Hash: 16 Wak Pat

Result of 0 in Wak.Pak is 0 

Result of 1 in Wak.Pak is 2

Result of 2 in Wak.Pak is 4

Result of 3 in Wak.Pak is 6

Result of 4 in Wak.Pak is 8

Done

原文地址:http://www.ccw.com.cn/htm/center/prog/02_8_23_6.asp

posted @ 2006-05-07 16:28 hopeshared 阅读(2674) | 评论 (1)编辑 收藏

仅列出标题
共30页: First 上一页 7 8 9 10 11 12 13 14 15 下一页 Last