精彩的人生

          好好工作,好好生活

          BlogJava 首頁 新隨筆 聯(lián)系 聚合 管理
            147 Posts :: 0 Stories :: 250 Comments :: 0 Trackbacks

          #

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


          在進(jìn)行所有的開發(fā)之前,自然是到http://xfire.codehaus.org下載最新的xfire的發(fā)布版本,在寫這篇文檔的時候,xfire最新的版本是xfire-distribution-1.1-beta-1版,從官方網(wǎng)站下載到本地機器后,解壓,目錄結(jié)構(gòu)如下:

          xfire-distribution-1.1-beta-1

          |____api?(javadoc文檔)

          |____sample?(幾個xfire例子)

          |____lib?(xfire所需的jars)

          |____modules?(xfire?模塊)

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

          |____幾個授權(quán)和說明TXT文檔

          ?

          它所提供的例子需要Maven2編譯執(zhí)行,如果你還沒有安裝Maven,可以到apache網(wǎng)站下載安裝。在你閱讀的這篇教程的例子中,我將采用ant進(jìn)行編譯,畢竟Ant才是大家所常用的項目管理編譯工具。

          ?

          在你的tomcat的webapps建立一個web應(yīng)用程序,例如xfire,目錄結(jié)構(gòu)如下:

          ???????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文件復(fù)制到tomcat/webapps/xfire/WEB-INF文件夾下。

          Web.xml的內(nèi)容如下:
          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 閱讀(983) | 評論 (0)編輯 收藏

               摘要: Applying the Web services invocation framework Calling services independent of protocols 獨立于協(xié)議的服務(wù)調(diào)用 ...  閱讀全文
          posted @ 2006-05-15 17:31 hopeshared 閱讀(955) | 評論 (0)編輯 收藏

          即使 SOAP 只是眾多訪問 Web 服務(wù)的可能的綁定之一,它已幾乎成為 Web 服務(wù)的同義詞。這意味著使用 Web 服務(wù)的應(yīng)用程序通常通過綁到 SOAP 的特定實現(xiàn)的 API 來完成工作。本系列文章將描述一個更通用的、獨立于 SOAP 的調(diào)用 Web 服務(wù)的方法,稱之為“Web 服務(wù)調(diào)用框架”(Web Service Invocation Framework(WSIF))。它專門設(shè)計來直接調(diào)用用“Web 服務(wù)描述語言”(Web Services Description Language(WSDL))描述的 Web 服務(wù),隱藏了底層訪問協(xié)議(比如 SOAP)的復(fù)雜性。

          Web 服務(wù)承諾為因特網(wǎng)分布式計算提供基于標(biāo)準(zhǔn)的平臺,集中在簡易性和靈活性。一種關(guān)鍵的 Web 服務(wù)技術(shù)是 WSDL,即“Web 服務(wù)描述語言”。使用 WSDL,開發(fā)者可以以抽象的形式描述 Web 服務(wù),與用在其它分布式計算框架(比如 CORBA)的現(xiàn)有“接口描述語言”(Interface Description Language(IDL))類似。WSDL 也使 Web 服務(wù)開發(fā)者能夠給服務(wù)指定具體的綁定。并且這些綁定描述怎樣將抽象服務(wù)描述映射到特定訪問協(xié)議。WSDL 的這部分是可擴展的,這就是說任何人都可以提出他們自己的綁定,使之可能通過某個定制的協(xié)議訪問服務(wù)。

          因此,從某種程度來說,使用 Web 服務(wù)是一種挑戰(zhàn)。對于同樣的服務(wù)可以有多個綁定。這些綁定中的一些可能適合于一些情形,其它可能適合于另外的情形。綁定本身可以代表抽象服務(wù)描述到用來訪問服務(wù)的任意一種協(xié)議的映射。雖然有多種選擇使用服務(wù)和允許綁定擴展是很有用的,但這給客戶機以統(tǒng)一方式查看服務(wù)造成了困難。

          我以當(dāng)前客戶機端 API 及其性能的討論開始這篇文章。我將通過討論來激發(fā)人們對 WSIF,即“Web 服務(wù)調(diào)用框架”的需要,然后繼續(xù)進(jìn)行 WSIF 的概述。

          當(dāng)前的調(diào)用風(fēng)格及其缺點
          用于 Web 服務(wù)的 SOAP 綁定是 WSDL 規(guī)范的一部分。在大多數(shù)編程語言中,該協(xié)議有可用的實現(xiàn)和工具,在許多情況下是免費的。這樣,它使得開發(fā)者能以微乎其微的成本進(jìn)行用于 Web 服務(wù)的獨立于平臺的開發(fā)。

          因此,下述情況是不足為奇的:大多數(shù)開發(fā)者當(dāng)想到使用 Web 服務(wù)時,在他們頭腦中出現(xiàn)的是使用某個 SOAP 客戶機 API 來裝配一個 SOAP 消息并將它經(jīng)由網(wǎng)絡(luò)發(fā)送到服務(wù)端點。例如,使用 Apache SOAP,客戶機將創(chuàng)建和植入一個 Call 對象。它封裝了服務(wù)端點、要調(diào)用的 SOAP 操作的標(biāo)識、必須發(fā)送的參數(shù)等等。而這是對 SOAP 而言,它僅限于將其用作調(diào)用 Web 服務(wù)的一般模型,這是因為下面的原因:

          • Web 服務(wù)不僅僅是 SOAP 服務(wù)
            將 Web 服務(wù)視為 SOAP 上提供的服務(wù)的同義詞。這是對 Web 服務(wù)狹隘的見解。帶有功能方面和訪問協(xié)議 WSDL 描述的任何一段代碼均可以被認(rèn)為是 Web 服務(wù)。WSDL 規(guī)范為 Web 服務(wù)定義了 SOAP 綁定,但是原則上可能要添加綁定擴展,這樣,例如,使用 RMI/IIOP 作為訪問協(xié)議,EJB 就可以作為 Web 服務(wù)來提供。或者您甚至可以想象任意一個 Java 類可以被當(dāng)作 Web 服務(wù),以本機 Java 調(diào)用作為訪問協(xié)議。就這個更廣闊的 Web 服務(wù)定義來說,您需要用于服務(wù)調(diào)用的獨立于綁定的機制。
          • 將客戶機代碼綁到一個特殊的協(xié)議實現(xiàn)要受到限制
            將客戶機代碼緊密地綁定到特殊的協(xié)議實現(xiàn)的客戶機庫造成了難以維護(hù)的代碼。讓我們假設(shè)您在客戶機端有一個用 Apache SOAP v2.1 調(diào)用 Web 服務(wù)的應(yīng)用程序。如果您想利用 v2.2 中出現(xiàn)的新的功能和錯誤修正,您將不得不更新所有的客戶機代碼,這是一項耗時的任務(wù),將涉及到常見的令人頭痛的遷移問題。類似的,如果您想從 Apache SOAP 移到一個不同的 SOAP 實現(xiàn),這個過程并非無關(guān)緊要。所需要的是用于服務(wù)調(diào)用的獨立于協(xié)議實現(xiàn)的機制。
          • 將新的綁定融入到客戶機代碼是很困難的。
            WSDL 允許有定義新的綁定的可擴展性元素。這使開發(fā)者能夠定義綁定,這種綁定允許使用某種定制協(xié)議的代碼作為 Web 服務(wù)。但是,事實上實現(xiàn)起來是很困難的。將不得不設(shè)計使用該協(xié)議的客戶機 API 。應(yīng)用程序本身可能正是使用 Web 服務(wù)的抽象接口,因此將必須編寫一些工具來生成啟用抽象層的存根。這些又一次是并非無關(guān)緊要的而且耗時的任務(wù)。所需要的是使綁定能夠被更新或新的綁定能夠容易地插入的服務(wù)調(diào)用機制。
          • 可以以靈活的方式使用多綁定
            例如,設(shè)想您已經(jīng)成功地部署了一個應(yīng)用程序,該應(yīng)用程序使用提供多綁定的 Web 服務(wù)。為了使這個示例更具體,假設(shè)您有用于服務(wù)的 SOAP 綁定和允許您將本地服務(wù)實現(xiàn)(一個 Java 類)作為 Web 服務(wù)的本地 Java 綁定。顯而易見,如果客戶機部署在與服務(wù)本身相同的環(huán)境中,只能使用面向服務(wù)的本地 Java 綁定,并且如果情況確實如此,通過直接進(jìn)行 Java 調(diào)用而不是使用 SOAP 綁定與服務(wù)進(jìn)行通信將高效得多。Java 綁定作為一種快捷訪問機制。接下來,想要利用多綁定可用性的客戶機將必須具有一種能力 — 根據(jù)運行時信息對要用的實際綁定進(jìn)行切換的能力。因此為了利用提供多綁定的 Web 服務(wù),您需要一種服務(wù)調(diào)用機制,允許您在運行時在可用的服務(wù)綁定之間進(jìn)行切換,而不需要生成或重編譯存根。

          介紹 WSIF
          “Web 服務(wù)調(diào)用框架”(WSIF)是為調(diào)用 Web 服務(wù)提供簡單 API 的工具箱,而不管服務(wù)怎樣提供或由哪里提供。它具有上面討論中我確定的所有功能:

          • 有給任何 Web 服務(wù)提供獨立于綁定訪問的 API。
          • 提供端口類型編譯器來生成允許使用抽象服務(wù)接口的調(diào)用的存根。
          • 允許無存根(完全動態(tài))的 Web 服務(wù)調(diào)用。
          • 可以在運行時將更新的綁定實現(xiàn)插入到 WSIF。
          • 可以在運行時插入的新的綁定。
          • 允許將綁定選擇延后到運行時。

          分析 WSIF 的客戶機 API
          為了進(jìn)行討論,我將使用很常見的股票報價程序 — Web 服務(wù)的“Hello World”示例。請考慮下面清單 1 所示的使用 WSDL 的抽象服務(wù)描述。

          清單 1:股票報價 Web 服務(wù)的 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>


          足夠簡單:它描述了只帶有由一個端口類型提供一個操作的服務(wù)。該操作等待一個字符串,被解釋為股票的報價機符號,然后返回當(dāng)前該股票報價,一個浮點值。為了實際使用該服務(wù),您需要某個定義訪問機制的綁定以及該綁定的服務(wù)端點。清單 2 展示了該服務(wù)的 SOAP 綁定:

          清單 2:股票報價 Web 服務(wù)的 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>

          這是一個標(biāo)準(zhǔn)的 SOAP 綁定,使用 RPC 風(fēng)格和作為傳輸協(xié)議的 HTTP 與服務(wù)進(jìn)行通信。在文檔的 port 部分中,我定義了使用 SOAP 綁定可以訪問服務(wù)的 URI。在清單 3 中,我將就通過 Apache SOAP 2.2 客戶機端 API 和 WSIF 的客戶機 API 使用該服務(wù)進(jìn)行對比。

          清單 3:用于服務(wù)訪問的 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,?null,?null);?
          ?
          //?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 編寫的抽象服務(wù)描述驅(qū)動;它完全從實際使用的綁定中分離出來。該調(diào)用 API 是面向 WSDL 的,并且使用它更自然,因為它使用 WSDL 術(shù)語引用消息部件(message part)、操作等等。當(dāng)您閱讀一個 WSDL 描述,出于直覺會想到選用支持所需端口類型的端口,然后通過提供必需抽象輸入消息(由必要部件組成)調(diào)用操作(不用擔(dān)心怎樣將消息映射到特定的綁定協(xié)議);WSIF API 就是這樣設(shè)計的。

          常用的 API,比如上面所示的 Apache SOAP API 采用了以特殊協(xié)議為中心的概念,比如在使用 SOAP 的情況下,目標(biāo) URI 和編碼風(fēng)格。這是不可避免的,因為 API 不是普遍適用于 WSDL,而是為特殊的協(xié)議設(shè)計。

          兩種使用 WSIF 的調(diào)用模型
          WSIF 允許 Web 服務(wù)以兩種方式調(diào)用。一種是無存根的動態(tài)調(diào)用,它要求直接使用 WSIF API;另一種是通過生成允許應(yīng)用程序使用 Java 接口(直接對應(yīng)于 WSDL 端口類型)和隱藏了 WSIF API 的存根的調(diào)用。

          無存根(動態(tài)的)調(diào)用
          訪問 Web 服務(wù)所需的所有信息 — 抽象接口、綁定和服務(wù)端點可以通過 WSDL 得到。如果您仔細(xì)查看上面的客戶機 API 示例,您將會注意到唯一由用戶提供的信息是用于服務(wù)的 WSDL 文件位置和所需要的股票報價符號。很明顯接下來是用 WSFL API 在運行時裝入這個服務(wù)和進(jìn)行該調(diào)用。

          WSIF 分發(fā)包包含了演示怎樣執(zhí)行 WSDL 的任意一個操作的 DynamicInvoker。它以 WSDL 文件的 URI 和所需的操作參數(shù)作為命令行參數(shù)(在最初的實現(xiàn)中只接受簡單的類型,如字符串),并且直接使用 WSIF API 完成工作。其用來調(diào)用股票報價服務(wù)的示例如清單 4 所示;您可以在包含 WSIF 分發(fā)包的文檔中查找詳細(xì)信息。

          因為這類調(diào)用不會導(dǎo)致生成存根類,并且不需要單獨的編譯周期,所以它很方便。

          清單 4:使用 DynamicInvoker 訪問股票報價服務(wù)

          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!

          使用存根的調(diào)用
          在應(yīng)用程序需要更抽象的服務(wù)視圖和不希望處理 WSIF 客戶機 API 的情況下,無存根調(diào)用不適用。WSIF 提供一個端口編譯器,如果給定一個 WSDL,與所用到的復(fù)雜類型的 Java 等價物(以 JavaBean 的形式)一起,端口編譯器將為每一個端口類型生成一個客戶機存根。使用生成存根的應(yīng)用程序可以利用抽象服務(wù)接口,并且這樣與協(xié)議和 WSIF 客戶機 API 分離。對于實際服務(wù)調(diào)用,這些存根使用缺省端口。通過由 WSIF 的端口類型編譯器生成的存根使用股票報價服務(wù)的示例如清單 5 所示。

          清單 5:使用生成存根的 WSIF 訪問股票報價服務(wù)。

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

          值得注意的是存根駐留在某些受管環(huán)境(如應(yīng)用程序服務(wù)器)的情況,它們能夠被定制;例如,可以改變負(fù)責(zé)返回恰當(dāng)端口的工廠來定制端口選擇算法,或者可以改變用于調(diào)用自身的實際端口。

          在這篇文章中,我略述了對 WSIF 的需要,分析其通過高級 API 進(jìn)行獨立于綁定的服務(wù)訪問的主要特征以及生成可定制的存根(通過其抽象接口使用服務(wù))的端口類型編譯器的可用性。直接通過 SOAP 客戶機 API 和使用 WSIF API 進(jìn)行服務(wù)訪問之間的對比展示了 WSIF(由服務(wù)的 WSDL 描述驅(qū)動)怎樣將 Web 服務(wù)調(diào)用的全部問題從以綁定為中心的觀點轉(zhuǎn)移到更抽象的級別。這是 WSIF 的設(shè)計原則之一,使服務(wù)綁定能被看作是根據(jù)特殊協(xié)議進(jìn)行調(diào)用所需的代碼片斷,可以在任何時候插入它們。

          在接下來的文章,我將分析 WSIF 的體系結(jié)構(gòu),看一看它怎樣允許新的或更新的綁定實現(xiàn)被插入,它怎樣使定制的類型系統(tǒng)用于 Web 服務(wù)以及怎樣使運行時環(huán)境使用定制的探索性方法在多端口之間進(jìn)行選擇。

          參考資料

          • 請參加關(guān)于這篇文章的討論論壇
          • 請下載 alphaworks 上的 WSIF 分發(fā)包,并且試驗比較簡單的樣本。它將給您一個由 WSIF 支持的不同調(diào)用風(fēng)格的第一手示例以及它優(yōu)于特定協(xié)議客戶機 API 的優(yōu)勢。
          • 重溫 WSDL 規(guī)范,看一看允許哪一種擴展;如果用來為訪問 Web 服務(wù)定義 SOAP 綁定,您也可以學(xué)習(xí) WSDL 的擴展機制。
          • 重溫 SOAP 規(guī)范本身。
          • 如果以前您沒有對 Web 服務(wù)編過程,Web Services Toolkit 是很好的起點。
          • 請查看 WSDL4J,一個可擴展的 WSDL 分析框架,WSIF 在此基礎(chǔ)上進(jìn)行構(gòu)建。

          關(guān)于作者
          Nirmal K. Mukhi 是 IBM 的 T J Watson Research Lab 的副研究員,自 2000 年 11 月,他一直在從事各種 Web 服務(wù)技術(shù)的研究。他還對 AI、創(chuàng)造性寫作以及過時的計算機游戲感興趣。您可以通過
          nmukhi@us.ibm.com 與 Nirmal 聯(lián)系。




          轉(zhuǎn)載自:http://www.itepub.net/page/article/htmldata/2004_10/17/76/article_3575_1.html
          posted @ 2006-05-15 17:20 hopeshared 閱讀(577) | 評論 (0)編輯 收藏

          我們都知道,RDF只表示二元關(guān)系,但在實際應(yīng)用中,多元關(guān)系非常常見,如:小紅借給小明語文書,是個三元關(guān)系:?borrow(小紅,語文書,小明);?再如,小明的身高是170cm.也是個三元關(guān)系?length(小明,170,?cm).?推廣來說,n元關(guān)系如何在RDF和OWL中表示呢?

          我們假設(shè)三元組為(a,b,c).?a,b.c?都是資源或Literal

          1.?方法一
          如果三元組中a是老大,即有個資源的地位是支配性的,如:小明的身高是170cm.
          表示方法為?把老大提出來,再把三元關(guān)系分解為3個二元關(guān)系:
          ??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.?方法二
          如果三元組中沒有明顯的老大,如:?小紅借給小明語文書.
          表示方法為提出一個對象,每個元素都和這個對象有關(guān)系:
          R1(g,?a)?,?R2(g,b),??R3(g,?c)
          例如:小紅借書的例子可以表示為
          rdf:type?(borrow_obj_1,??BorrowRelation);?//?BorrowRelation?是一個表示借書關(guān)系的類
          borrow_owner((borrow_obj_1,小紅);?
          borrow_agent((borrow_obj_1,小明);?//借書的人
          borrow_book((borrow_obj_1,?語文書);


          3.?結(jié)論
          1)?n-元關(guān)系有2exp(n-2)?種表示方法:?二元關(guān)系一種表示法,三元關(guān)系有如上二種表示法,由數(shù)學(xué)歸納法得證。
          2)?如果用RDF對復(fù)雜系統(tǒng)建模,有必要引入一個中間的抽象層,用以表示N元關(guān)系,還有named?graph,?context?等。如引入rdfe:relation(a,b,c,d,….)表示n元關(guān)系?
          3)?n-關(guān)系的表示對RDF數(shù)據(jù)的查詢和存儲優(yōu)化很有價值,因為n-關(guān)系往往對應(yīng)了數(shù)據(jù)庫中的表。


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

          更為詳細(xì)的信息也參考它。

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

          posted @ 2006-05-10 10:31 hopeshared 閱讀(864) | 評論 (0)編輯 收藏

          ?

          在網(wǎng)絡(luò)中為了保證數(shù)據(jù)的實時性,需要對數(shù)據(jù)進(jìn)行異步操作。Java Web Service和J2EE中的異步操作通過java消息機制來完成,消息機制是非常完善的技術(shù)了。而Microsoft的Web Service的異步功能是怎樣完成的呢?怎樣才能達(dá)到j(luò)ava的境地呢?當(dāng)然,Microsoft有自己的一套。

          眾所周知,Web Service是靠SOAP協(xié)議進(jìn)行數(shù)據(jù)傳輸?shù)摹6鳶OAP是基于XML技術(shù)之上的。SOAP協(xié)議是連接客戶和服務(wù)器的橋梁。而SOAP協(xié)議本身沒有異步功能,需要在客戶端實現(xiàn)異步調(diào)用。我們以一個簡單的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;

          }

          }

          這是個實現(xiàn)了加,減,乘,除的Web Service,任何客戶端程序都可以調(diào)用它。下面我們用wsdl(微軟公司提供)工具產(chǎn)生一個MathService.asmx 的客戶代理程序:wsdl /n:MyMath http://localhost/mathservice.asmx (假設(shè)MathService.asmx放在IIS服務(wù)器的根目錄) ,產(chǎn)生一個MathService.cs代理程序,默認(rèn)是SOAP協(xié)議。

          二、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編譯并產(chǎn)生一個MathService.dll.

          現(xiàn)在我們可以寫任何的客戶程序去調(diào)用服務(wù)器上的MathService.asmx。

          如:WinForm, C#,ASPX等。

          下面我們寫一個test.cs去測試異步調(diào)用:

          三、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);

          }

          }

          我們看到它是先調(diào)用代理MathService.cs中的BeginAdd方法,然后狀態(tài)信息保存在IasyncResult中,直到調(diào)用了EndAdd方法才返回調(diào)用的確切值。本例是遠(yuǎn)端調(diào)用MathService.asmx中的Add方法。

          那Microsoft到底怎樣實現(xiàn)客戶端的異步呢?設(shè)計模式又是怎樣的呢?

          異步模式所提供的革新之一就是調(diào)用方確定特定調(diào)用是否應(yīng)是異步的。  對于被調(diào)用的對象,沒有必要執(zhí)行附加的編程來用于支持其客戶端的異步行為;在該模式中異步委托提供此功能。公共語言運行庫處理調(diào)用方和被調(diào)用的對象視圖之間的差異。被調(diào)用的對象可以選擇顯式支持異步行為,這或者是因為它可以比一般結(jié)構(gòu)更為有效地實現(xiàn)異步行為,或者是因為它想只支持其調(diào)用方的異步行為。但是,建議這種被調(diào)用的對象遵循公開異步操作的異步設(shè)計模式。

          類型安全是異步模式的另一項革新。尤其對于異步委托,針對 .NET 框架和公共語言運行庫的語言編譯器可令映射到規(guī)則 Invoke 方法的開始和結(jié)束操作(例如,BeginInvoke 和 EndInvoke)的方法簽名是類型安全的。這是十分重要的,因為編譯器為異步委托將同步調(diào)用拆分成開始和結(jié)束操作,使其能夠只傳遞有效參數(shù)。

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

          1.調(diào)用方確定特定調(diào)用是否應(yīng)是異步的。

          2. 對于被調(diào)用的對象,沒有必要由其客戶端執(zhí)行附加的編程來用于支持異步行為。公共語言運行庫結(jié)構(gòu)應(yīng)該能夠處理調(diào)用方和被調(diào)用的對象視圖之間的差異。

          3. 被調(diào)用的對象可以選擇顯式支持異步行為,這或者是因為它可以比一般結(jié)構(gòu)更為有效地實現(xiàn)異步行為,或者是因為它想只支持其調(diào)用方的異步行為。但是,建議這種被調(diào)用的對象遵循公開異步操作的異步設(shè)計模式。

          4. 編譯器為 BeginInvoke 和 EndInvoke 以及異步委托生成類型安全方法簽名。

          5. .NET 框架提供支持異步編程模型所需的服務(wù)。此類服務(wù)的部分列表示例是:

          (1)同步基元,例如監(jiān)視器和閱讀器編寫器鎖定。

          (2)線程和線程池。

          (3)同步構(gòu)造,例如支持等候?qū)ο蟮娜萜鳌?/p>

          (4)向基礎(chǔ)結(jié)構(gòu)片(例如 IMessage 對象和線程池)公開。

          該模式將一個同步調(diào)用拆分成各構(gòu)成部分:開始操作、結(jié)束操作和結(jié)果對象。考慮以下示例,在其中可能要用大量時間來完成 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.

          }

          }

          服務(wù)器將異步操作拆分成兩個邏輯部分:采用來自客戶端的輸入并調(diào)用異步操作的部分,向客戶端提供異步操作結(jié)果的部分。

          除了異步操作所需的輸入外,第一部分還采用在完成異步操作時后要被調(diào)用的 AsyncCallback 委托。第一部分返回一個可等待的對象,該對象實現(xiàn)客戶端使用的 IAsyncResult 接口來確定異步操作的狀態(tài)。

          服務(wù)器還利用它返回到客戶端的可等待的對象來維護(hù)與異步操作關(guān)聯(lián)的任何狀態(tài)。通過提供可等待的對象,客戶端使用第二部分獲取異步操作的結(jié)果。

          可用于客戶端來啟動異步操作的選項有:

          在開始異步調(diào)用時提供回調(diào)委托。

           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);

              } 

          在開始異步調(diào)用時不提供回調(diào)委托。

          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);// 異步調(diào)用的委派.

          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");

          }

          }

              

          如果異步調(diào)用成功,將顯示:

          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 閱讀(2698) | 評論 (1)編輯 收藏

          僅列出標(biāo)題
          共30頁: First 上一頁 7 8 9 10 11 12 13 14 15 下一頁 Last 
          主站蜘蛛池模板: 威信县| 临泽县| 宁武县| 中江县| 巫溪县| 贵德县| 莲花县| 广饶县| 观塘区| 九龙坡区| 五莲县| 汝城县| 越西县| 仁怀市| 吴旗县| 工布江达县| 斗六市| 奉贤区| 灌云县| 隆德县| 霍邱县| 芜湖市| 晋中市| 武定县| 老河口市| 朝阳县| 梁平县| 桐庐县| 拉萨市| 孟津县| 肃南| 那坡县| 津南区| 江北区| 科技| 云阳县| 兰州市| 深州市| 太和县| 德令哈市| 临西县|