精彩的人生

          好好工作,好好生活

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

               摘要: Applying the Web services invocation framework Calling services independent of protocols 獨立于協議的服務調用 ...  閱讀全文
          posted @ 2006-05-15 17:31 hopeshared 閱讀(950) | 評論 (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,?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 編寫的抽象服務描述驅動;它完全從實際使用的綁定中分離出來。該調用 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),?
          ????
          null,?null);
          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 閱讀(575) | 評論 (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 閱讀(860) | 評論 (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 閱讀(2694) | 評論 (1)編輯 收藏

          僅列出標題
          共30頁: First 上一頁 7 8 9 10 11 12 13 14 15 下一頁 Last 
          主站蜘蛛池模板: 阿图什市| 林州市| 博兴县| 长汀县| 正镶白旗| 镇沅| 泗水县| 沿河| 庄河市| 屏东县| 广昌县| 东源县| 嘉荫县| 南乐县| 贡嘎县| 顺义区| 新巴尔虎左旗| 闻喜县| 海原县| 毕节市| 贡嘎县| 曲靖市| 京山县| 金湖县| 龙陵县| 巴青县| 万源市| 浦县| 京山县| 孝义市| 扶沟县| 新沂市| 怀柔区| 石城县| 阆中市| 乌海市| 正蓝旗| 宁德市| 衡山县| 衡阳县| 都匀市|