精彩的人生

          好好工作,好好生活

          BlogJava 首頁(yè) 新隨筆 聯(lián)系 聚合 管理
            147 Posts :: 0 Stories :: 250 Comments :: 0 Trackbacks
          即使 SOAP 只是眾多訪問(wèn) Web 服務(wù)的可能的綁定之一,它已幾乎成為 Web 服務(wù)的同義詞。這意味著使用 Web 服務(wù)的應(yīng)用程序通常通過(guò)綁到 SOAP 的特定實(shí)現(xiàn)的 API 來(lái)完成工作。本系列文章將描述一個(gè)更通用的、獨(dú)立于 SOAP 的調(diào)用 Web 服務(wù)的方法,稱之為“Web 服務(wù)調(diào)用框架”(Web Service Invocation Framework(WSIF))。它專門設(shè)計(jì)來(lái)直接調(diào)用用“Web 服務(wù)描述語(yǔ)言”(Web Services Description Language(WSDL))描述的 Web 服務(wù),隱藏了底層訪問(wèn)協(xié)議(比如 SOAP)的復(fù)雜性。

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

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

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

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

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

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

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

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

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

          清單 1:股票報(bào)價(jià) 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>


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

          清單 2:股票報(bào)價(jià) 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>

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

          清單 3:用于服務(wù)訪問(wèn)的 Apache SOAP API 與 WSIF API 對(duì)比

          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ū)動(dòng);它完全從實(shí)際使用的綁定中分離出來(lái)。該調(diào)用 API 是面向 WSDL 的,并且使用它更自然,因?yàn)樗褂?WSDL 術(shù)語(yǔ)引用消息部件(message part)、操作等等。當(dāng)您閱讀一個(gè) WSDL 描述,出于直覺(jué)會(huì)想到選用支持所需端口類型的端口,然后通過(guò)提供必需抽象輸入消息(由必要部件組成)調(diào)用操作(不用擔(dān)心怎樣將消息映射到特定的綁定協(xié)議);WSIF API 就是這樣設(shè)計(jì)的。

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

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

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

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

          因?yàn)檫@類調(diào)用不會(huì)導(dǎo)致生成存根類,并且不需要單獨(dú)的編譯周期,所以它很方便。

          清單 4:使用 DynamicInvoker 訪問(wèn)股票報(bào)價(jià)服務(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 客戶機(jī) API 的情況下,無(wú)存根調(diào)用不適用。WSIF 提供一個(gè)端口編譯器,如果給定一個(gè) WSDL,與所用到的復(fù)雜類型的 Java 等價(jià)物(以 JavaBean 的形式)一起,端口編譯器將為每一個(gè)端口類型生成一個(gè)客戶機(jī)存根。使用生成存根的應(yīng)用程序可以利用抽象服務(wù)接口,并且這樣與協(xié)議和 WSIF 客戶機(jī) API 分離。對(duì)于實(shí)際服務(wù)調(diào)用,這些存根使用缺省端口。通過(guò)由 WSIF 的端口類型編譯器生成的存根使用股票報(bào)價(jià)服務(wù)的示例如清單 5 所示。

          清單 5:使用生成存根的 WSIF 訪問(wèn)股票報(bào)價(jià)服務(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)端口的工廠來(lái)定制端口選擇算法,或者可以改變用于調(diào)用自身的實(shí)際端口。

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

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

          參考資料

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

          關(guān)于作者
          Nirmal K. Mukhi 是 IBM 的 T J Watson Research Lab 的副研究員,自 2000 年 11 月,他一直在從事各種 Web 服務(wù)技術(shù)的研究。他還對(duì) AI、創(chuàng)造性寫作以及過(guò)時(shí)的計(jì)算機(jī)游戲感興趣。您可以通過(guò)
          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 on 2006-05-15 17:20 hopeshared 閱讀(575) 評(píng)論(0)  編輯  收藏 所屬分類: Web Service
          主站蜘蛛池模板: 徐汇区| 益阳市| 富民县| 友谊县| 烟台市| 西乌| 麻阳| 泰和县| 秦安县| 昭平县| 泾源县| 湾仔区| 滕州市| 古丈县| 香格里拉县| 宾阳县| 库尔勒市| 连江县| 南岸区| 九寨沟县| 吴堡县| 喀什市| 镇巴县| 麟游县| 酒泉市| 息烽县| 湖南省| 平果县| 诸暨市| 江阴市| 巴彦淖尔市| 湄潭县| 东乡县| 莫力| 漳州市| 东乌| 繁昌县| 鹤壁市| 霍州市| 潼南县| 南涧|