樂趣無窮,可能無限的新技術(shù)_第1頁
樂趣無窮,可能無限的新技術(shù)_第2頁
樂趣無窮,可能無限的新技術(shù)_第3頁
樂趣無窮,可能無限的新技術(shù)_第4頁
樂趣無窮,可能無限的新技術(shù)_第5頁
已閱讀5頁,還剩34頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

樂趣無窮,可能無限的新技術(shù)-WebService李維11.1序言雖然電子商務(wù)的狂熱在最近似乎有減溫的現(xiàn)象,讓許多人能夠回歸到正常的步調(diào)之中,不過隨著電子商務(wù)而發(fā)展的軟件技術(shù)并沒有稍停腳步,反而更加蓬勃發(fā)展。因?yàn)橛蛇@些技術(shù)創(chuàng)造的應(yīng)用早已成為許多人生活的一部份,甚至是開啟未來趨勢(shì)的基石。在目前最熱門且最被看好的技術(shù)便是所謂的WebService了,那么什么是WebService呢?簡(jiǎn)單的說,WebService是一種想把全世界的Internet/Intranet變成一個(gè)虛擬計(jì)算環(huán)境的觀念和技術(shù)。在由WebService組成的虛擬環(huán)境中使用者可以任何的客戶端軟件,例如瀏覽器,一般的Window或是Java應(yīng)用程序或是電子行動(dòng)設(shè)備等,來調(diào)用WebService提供的服務(wù)。而WebService本身則可以由任何的技術(shù)編寫,例如開發(fā)者可以使用Delphi,Java,C/C++或是C#等的語言和工具來開發(fā)。WebService是建立在開放和標(biāo)準(zhǔn)的規(guī)格之上,允許異質(zhì)的客戶端調(diào)用以使用它提供的服務(wù)。因此各種異質(zhì)的客戶端必須使用一種共通的溝通標(biāo)準(zhǔn)才能夠順利的和由各種不同技術(shù)編寫的WebService互通。目前最流行而且最具潛力的溝通標(biāo)準(zhǔn)當(dāng)屬SOAP了。SOAP(SimpleObjectAccessProtocol)是由DonBox起草,并且獲得IBM,Microsoft,Lotus和UserLand等大型公司支持而成為W3C標(biāo)準(zhǔn)之一的通訊協(xié)議規(guī)格。從SOAP的名稱中我們便可以知道它是讓客戶端調(diào)用遠(yuǎn)程對(duì)象服務(wù)的一種機(jī)制oSOAP以XML標(biāo)準(zhǔn)封裝調(diào)用遠(yuǎn)程服務(wù)的格式,有別于其它分布式對(duì)象模型調(diào)用特定的調(diào)用格式,例如CORBA的GIOP以及DCOM的ORPCo由于SOAP以XML封裝調(diào)用格式,因此它可以使用任何的實(shí)體傳輸層來傳送,例如HTTP,TCP或是SMTP等。也許讓我們使用一個(gè)簡(jiǎn)單的概例來說明會(huì)讓各位更容易的了解。假設(shè)現(xiàn)在我在Linux平臺(tái)上以Java語言編寫了一個(gè)WebService,這個(gè)WebService提供了一個(gè)服務(wù)GetSystemTime。這個(gè)服務(wù)接受一個(gè)使用者名稱和一個(gè)密碼,如果成功的登錄之后,這個(gè)服務(wù)便會(huì)回傳Linux平臺(tái)目前的系統(tǒng)時(shí)間。那么我可以使用Delphi以SOAP的標(biāo)準(zhǔn)封裝使用者名稱和密碼來調(diào)用這個(gè)在Linux平臺(tái)上的GetSystemTime服務(wù)。目前WebService使用它來當(dāng)作數(shù)據(jù)交換的標(biāo)準(zhǔn),本文不嘗試完整解釋SOAP!如果你想完整的了解SOAP的話,請(qǐng)?jiān)诟戒浕蛳鄳?yīng)的參考書中查找相關(guān)的內(nèi)容,這里我只簡(jiǎn)單的列出幾樣你應(yīng)該要知道的部份。SOAP需要一個(gè)通訊協(xié)議來傳輸訊息,目前的SOAP1.0,1.1都偏向于使用HTTP做為通訊協(xié)議,而新的SOAP1.2版在信息包頭部包含了一些信息包容數(shù)據(jù),這樣我們也可以更加容易的使用它進(jìn)行相應(yīng)的信息加密。除了HTTP之外SOAP也可以使用SMTP,FTP等其它通訊協(xié)議來傳輸資料,但是目前除了HTTP夕卜,其它部份的實(shí)作都還沒有定論,由于SOAP的Request/Response核心運(yùn)行模式跟HTTP協(xié)議很類似,所以目前的操作及程序編寫都以HTTP為主,相信以后應(yīng)該會(huì)有更多的協(xié)議來滿足不同情況的應(yīng)用。一個(gè)標(biāo)準(zhǔn)的SOAPRequest樣子大概如代碼清單1(使用HTTP):代碼清單1POST/Project2.MyService/soap/IMyServiceHTTP/1.1Accept:application/octet-stream,text/xmlSOAPAction:"urn:MyServiceIntf-IMyService#GetComplexType"<?xmlversion="1.0"encoding='UTF-8'?><SOAP-ENV:Envelopexmlns:SOAP-ENV="/soap/envelope/"xmlns:xsd="/1999/XMLSchema"xmlns:xsi="/1999/XMLSchema-instance"xmlns:SOAP-ENC="/soap/encoding/"><SOAP-ENV:Body><NS1:GetComplexTypexmlns:NS1="urn:MyServiceIntf-IMyService"SOAP-ENV:encodingStyle="/soap/encoding/"><NS1:Param1xsi:type="xsd:string">1234</NS1:Param1></NS1:GetComplexType></SOAP-ENV:Body></SOAP-ENV:Envelope>我們先看POST/Project2.MyService/soap/IMyService這個(gè)部份,這里指定了要喚起的是那一個(gè)WebServiceServer程序,以.NET來說,這可能是一個(gè)ASP.NET網(wǎng)頁,以DELPHI來說,就是一個(gè)CGI或ISAPI程序。在下面的SOAPAction段則是指定我們想調(diào)用WebService中的那一個(gè)Method,WebServiceServer會(huì)解釋這一段來喚起對(duì)應(yīng)的Method程序代碼,不過SOAP1.1并未強(qiáng)制一定要有SOAPAction值,這必須視實(shí)程序編寫者的具體要求而定。在使用Method之前,Server還要解釋Body區(qū)段中的信息來取得Client所傳遞的參數(shù)及類別,以目前的SOAP文件標(biāo)準(zhǔn)來看,你只能夠在Body區(qū)段中包含一個(gè)Method的信息,這也代表了一次HTTPRequest只能夠喚起一個(gè)Method,雖然有人提出了可以在一次的HTTP傳輸中喚起多個(gè)Method的資料格式,但目前還沒有正式的規(guī)格。在上例中,<NS1:GetComplexType>就是我們要調(diào)用的Method信息封包,這個(gè)區(qū)段中包含了調(diào)用GetComplexTypeMethod的參數(shù)型別與值,NS1:Param1就是這個(gè)Method所需要的參數(shù),"xsi:type="xsd:string"就是該參數(shù)的型別,當(dāng)我們將這個(gè)Request送給WebService后,WebService就會(huì)根據(jù)這些信息執(zhí)行對(duì)應(yīng)的Service及調(diào)用Method,完成后它會(huì)回復(fù)像這樣的訊息給我們:代碼清單2:HTTP/1.1200OKContent-Type:text/xmlContent-Length:867Content:<?xmlversion="1.0"encoding='UTF-8'?><SOAP-ENV:Envelopexmlns:SOAP-ENV="/soap/envelope/"xmlns:xsd="/1999/XMLSchema"xmlns:xsi="/1999/XMLSchema-instance"xmlns:SOAP-ENC="/soap/encoding/"><SOAP-ENV:Body><NS1:GetComplexTypeResponsexmlns:NS1="urn:MyServiceIntf-IMyService"SOAP-ENV:encodingStyle="/soap/encoding/"xmlns:NS2="/2001/XMLSchema"><NS1:returnhref="#1"/><NS2:returnid="1"xsi:type="NS2:TXSMyComplexType"><NS2:ServerMessagexsi:type="xsd:string">TestMySelf</NS2:ServerMessage><NS2:InnerStringhref="#2"/></NS2:return><NS2:InnerStringid="2"xsi:type="NS2:TXSInnerType"><NS2:InnerStringxsi:type="xsd:string">ThisisInnerType</NS2:InnerString></NS2:InnerString></NS1:GetComplexTypeResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>這個(gè)WebService使用了兩個(gè)ComplexType,可以發(fā)現(xiàn)與Request差別不大,我們先看紅色字的部份GetComplexTypeResponse代表調(diào)用的Method回傳的數(shù)據(jù)封包,Client端程序由解釋這部分的信息來取得回傳值跟類別。例子中藍(lán)色及深藍(lán)色部份就是調(diào)用Method后的回傳值,理論上SOAP可以表現(xiàn)相當(dāng)復(fù)雜的數(shù)據(jù)型態(tài),以上面這個(gè)例子來說,我使用了一個(gè)ComplexType:TXSMyComplexType并且在里面使用了一個(gè)TXSInnerType,因應(yīng)情況的不同,你也可以傳遞TXSMyComplexType型態(tài)的數(shù)組或更復(fù)雜的數(shù)據(jù)型態(tài)來表示數(shù)據(jù)庫中的數(shù)據(jù)列。SOAPRequest/ResponseMessage通常是由開發(fā)工具幫你產(chǎn)生及解釋,所以我們接觸SOAPMessage的機(jī)會(huì)不多,但這不代表我們不需要了解SOAP,當(dāng)你的程序發(fā)生問題時(shí),這些信息將會(huì)給你相當(dāng)大的幫助。除了Request及ResponseMessage之外,SOAP也提供Fault訊息格式,這個(gè)訊息會(huì)在ServiceServer發(fā)生錯(cuò)誤時(shí)傳回Client端,DELPHI的ServiceServer會(huì)自動(dòng)將Exception包裝成這種格式后傳回Client端,Client端再根據(jù)其中的錯(cuò)誤訊息產(chǎn)生一個(gè)例外。代碼清單3:HTTP/1.1200OKContent-Type:text/xmlContent-Length:473Content:<?xmlversion="1.0"encoding='UTF-8'?><SOAP-ENV:Envelopexmlns:SOAP-ENV="/soap/envelope/"xmlns:xsd="/1999/XMLSchema"xmlns:xsi="/1999/XMLSchema-instance"xmlns:SOAP-ENC="/soap/encoding/"><SOAP-ENV:Body><SOAP-ENV:Fault><SOAP-ENV:faultcode>SOAP-ENV:Server</SOAP-ENV:faultcode><SOAP-ENV:faultstring>TestException</SOAP-ENV:faultstring></SOAP-ENV:Fault></SOAP-ENV:Body></SOAP-ENV:Envelope>WebServicesDescriptionLanguage(WSDL)【W(wǎng)eb服務(wù)描述語言】WSDL是用來描述WebService信息的語言,應(yīng)用程序經(jīng)由解釋W(xué)SDL來取得有關(guān)連結(jié)WebService的信息,WSDL大概分成幾部份:代碼清單4:<servicename=〃IDPServiceservice〃><portname=〃IDPServicePort〃binding=〃IDPServicebinding〃><soap:addresslocation=〃http://localhost:1024/Project1.MyDPService/soap/IDPService〃/></port></service>藍(lán)色部份代表WebService的名稱,應(yīng)用程序要連結(jié)至WebService時(shí)必須要指定一個(gè)Service跟一個(gè)Port,紅色部份就是ServicePort的描述。一個(gè)Port必須要有一個(gè)SOAPAddressLocation,用來描述該P(yáng)ort的URL地址,這樣應(yīng)用程序才能經(jīng)由這個(gè)地址與Service溝通,之前提過SOAP支持多種傳輸方式,而binding屬性就是描述這些信息的地方:代碼清單4:<bindingname="IDPServicebinding"type="IDPService"><soap:bindingstyle="rpc"transport="/soap/http"/><operationname="SayHello"><soap:operationsoapAction="urn:DPServiceIntf-IDPService#SayHello"/><input><soap:bodyuse="encoded"encodingStyle="/soap/encoding/"namespace="urn:DPServiceIntf-IDPService"/></input><output><soap:bodyuse="encoded"encodingStyle="/soap/encoding/"namespace="urn:DPServiceIntf-IDPService"/></output></operation></binding>藍(lán)色部份就是binding的信息,這個(gè)Port使用HTTP傳輸協(xié)議,并且指定使用rpc為傳輸樣式。SOAP目前定義兩種傳輸樣式:rpc跟documentoDELPHI目前只支持rpc的傳輸樣式,.NET則兩個(gè)都支持,默認(rèn)值是使用document模式。深藍(lán)色部份描述了Service中的Method,你可以在里面發(fā)現(xiàn)SOAPAction的信息跟SOAPBody區(qū)段所使用的樣式(Style)。SOAP的Body區(qū)段可以使用encoded/literal兩種樣式,一般來說,rpc通常搭配encoded,document則搭配literal樣式。在這里描述的只有bindinginformation,Method所需要的參數(shù)及型別則在下面這段描述中:<messagename=〃SayHelloRequest〃/><messagename=〃SayHelloResponse〃><partname=〃return〃type=〃xs:string〃/></message>籃色部份就是message的描述,這個(gè)描述代表SayHelloMethod不需要有傳入值,其紅色部份則描述了SayHelloMethod會(huì)有一個(gè)傳回值,型別是stringoWSDL中較重要的信息大概就是這些了,其它有關(guān)于WSDL的詳細(xì)信息,就請(qǐng)你至U查看。可以看到通過SOAP,Delphi的客戶端應(yīng)用程序可以輕易的調(diào)用Linux平臺(tái)上的WebService,而無需關(guān)心這個(gè)WebService是由什么技術(shù)編寫的,或是存在于任何地方,更不需要以特定的二進(jìn)制格式來封裝調(diào)用。因此通過WebService和SOAP,開發(fā)者可以輕易的整合各種異構(gòu)平臺(tái),異構(gòu)分布式對(duì)象模型,而充分的利用所有的計(jì)算資源,這在以前是不可能輕易做到的。目前各種WebService也已經(jīng)在Internet上供人使用,例如搜尋MP3的服務(wù),或是查詢?nèi)澜绺鞯貧庀蟮姆?wù)等。而在此書中我們特別推薦WWW.這個(gè)網(wǎng)站,它提供了大量的WebService供開發(fā)人員調(diào)用,并為調(diào)試自己的WebService提供方便。相信WebService和SOAP也終將成為軟件開發(fā)人員必備的軟件技能之一。我們?cè)诒菊碌膬?nèi)容主要是討論WebService的技術(shù)結(jié)構(gòu)和編寫這樣一個(gè)程序的技巧,并且首先以Delphi6做為說明如何實(shí)際的開發(fā)WebService以及客戶端應(yīng)用程序來調(diào)用WebService。接著再說明如何使用Delphi開發(fā)的客戶端應(yīng)用程序來調(diào)用Internet上由Java和MSSQL開發(fā)的WebService,來向各位讀者展示W(wǎng)ebService和SOAP的開放性以及標(biāo)準(zhǔn)性。當(dāng)我們成功的在本地機(jī)器調(diào)用了在世界上某一個(gè)角落,由某一個(gè)人使用某一種工具開發(fā)的WebService時(shí),相信讀者也會(huì)贊嘆WebService和SOAP所帶來的軟件技術(shù)的革命。11.2WebService和SOAP的架構(gòu)那么我們要如何才能夠知道每一個(gè)WebService提供的服務(wù)?要如何才能夠正常使用WebService所提供的服務(wù)呢?又要到那里找到適合的WebService呢?簡(jiǎn)單的說,WebService提供的服務(wù)是以所謂的WSDL(WebServiceDescriptionLanguage)標(biāo)準(zhǔn)來敘述的,只要我們能夠取得特定WebService的WSDL,就可以從其中了解它提供的服務(wù),以及如何調(diào)用這個(gè)WebService。最后一個(gè)問題是如何找到適用的WebService,在目前全世界已經(jīng)有人公布了許多的WebService供人調(diào)用使用。此外IBM和Microsoft等公司也正在研擬所謂的UDDI標(biāo)準(zhǔn)以提供注冊(cè),搜尋,交換和使用WebService的標(biāo)準(zhǔn),開發(fā)人員可以通過UDDI找到需要的WebService,當(dāng)然我相信許多的WebService將會(huì)由開發(fā)人員根據(jù)自己的需求而使用工具開發(fā)出來。說了那么多,可能讀者會(huì)想要知道到底WebService要如何編寫?要使用什么語言或是工具才能夠撰寫的呢?事實(shí)上WebService并不局限于任何特定的工具或是語言才能夠開發(fā)、使用,簡(jiǎn)單的說你可以使用任何的工具或是語言來開發(fā),甚至可以使用ASP/JSP等角本語言(ScriptLanguage)來編寫。當(dāng)然,開發(fā)人員也可以結(jié)合各種不同的軟件技術(shù)和組件架構(gòu)來開發(fā)。下圖是以在實(shí)際使用過程中相應(yīng)的觀點(diǎn)來敘述WebService的概念。圖中的客戶端通過SOAP和HTTP通訊協(xié)議,透過WebServiceProvider找到適合的WebService,再調(diào)用它。而實(shí)體的WebService可以是編寫在Window平臺(tái)的MTS/COM+

或是.NET對(duì)象,也可以是編寫在Linux\UNIX平臺(tái)中的CORBA或是EJB對(duì)象。這個(gè)觀點(diǎn)是以各種組件模型來編寫WebService。現(xiàn)1拭十算機(jī)圖11.1WebService的架構(gòu)示意圖至于下圖則是以更細(xì)微的觀點(diǎn)來看WebService的構(gòu)成。在這個(gè)圖形中呈現(xiàn)了WebService可以由ASP/JSP或是CGI,ISAPI的形式來編寫,以服務(wù)客戶端的請(qǐng)求。開發(fā)人員可以把所有的WebService企業(yè)邏輯編寫在ASP/JSP/CGI/ISAPI/DSO之中?;蚴侵话秧憫?yīng)客戶端請(qǐng)求的邏輯編寫在ASP/JSP/CGI/ISAPI/DSO之中,而把真正的企業(yè)邏輯編寫在后端的組件模型之中,或是后端的應(yīng)用程序之中,例如Delphi的DataSnap服務(wù)器。圖11.2WebService的編寫架構(gòu)圖從上面的討論中可以知道,開發(fā)人員可以使用任何的技術(shù)編寫WebService,只需要根據(jù)標(biāo)準(zhǔn)輸出WebService,就可以由客戶端正常使用它。討論完了概念之后,現(xiàn)在讓我們回到實(shí)際的程序編寫層次中。雖然WebService可以由任何的技術(shù)編寫,但是開發(fā)人員仍然需要選擇一種方式來開發(fā)。開發(fā)WebService除了編寫WebService的企業(yè)邏輯之外,也必須提供WebService的WSDL,并且分發(fā)WebService。由于目前使用WebService的情形仍然以SOAP/HTTP型式來進(jìn)行接口程序的編寫,所以許多的WebService也是以Web應(yīng)用程序的型態(tài)編寫,例如把WebService編寫成CGI或是ISAPI/DSO的型式,不過只要能夠處理HTTP的調(diào)用,WebService也可以編寫成一般的獨(dú)立應(yīng)用程序,這一點(diǎn)是讀者必須了解的。開發(fā)WebService雖然不是非常的困難,但是它仍然需要許多的開發(fā)步驟和處理程序,這也仍然需要花費(fèi)一些開發(fā)成本。在Borland最新推出的Delphi6中,Borland特別提供了7個(gè)直接的WebService組件,三個(gè)WebServiceWizard以及其它數(shù)個(gè)相關(guān)的VCL組件來幫助開發(fā)人員快速的開發(fā)WebService,更使人振奮是,開發(fā)人員也可以再結(jié)合Delphi原有的MTS/COM+/CORBA/EJB組件模型開發(fā)更具延展性的WebService。下圖便是Delphi6中直接和WebService相關(guān)的WebService組件組。

圖11.3Delphi6提供的WebServices組件這7個(gè)WebService組件可以讓開發(fā)人員調(diào)用遠(yuǎn)程WebService,自動(dòng)產(chǎn)生WebService的WSDL,以及進(jìn)行SOAP/HTTP和ObjectPascal語言之間的綁定(Binding),以便讓Delphi的程序員能夠使用ObjectPascal直接處理SOAP之中的訊息。下圖則顯示了在客戶端應(yīng)用程序和遠(yuǎn)程WebService之間如何通過這些組件溝通,以及每一個(gè)組件之間的關(guān)系。由于Delphi6是Window平臺(tái)上的開發(fā)工具,因此它使用了Wininet.dll來傳送HTTP封包信息。服務(wù)內(nèi)容產(chǎn)生過程客戶內(nèi)容編寫過程服務(wù)內(nèi)容產(chǎn)生過程客戶內(nèi)容編寫過程連接使用服務(wù)使用及最終結(jié)果使用及最終結(jié)果圖11.4Delphi6WebServices組件的功能示意圖從上圖可以知道,Delphi6客戶端應(yīng)用程序通過THTTPRIO調(diào)用遠(yuǎn)程WebService,而TOPToSoapDomConvert可以把ObjectPascal的調(diào)用和參數(shù)自動(dòng)轉(zhuǎn)換為SOAP封裝的格式信息,再通過THTTPReqResp傳送HTTP封包。而在服務(wù)器THTTPSoapDispatcher則負(fù)責(zé)處理客戶端傳送來的SOAP/HTTP信息,并且透過THTTPSoapPascalInvoker組件來自動(dòng)啟動(dòng)能夠處理這個(gè)SOAP/HTTP請(qǐng)求的ObjectPascal程序代碼。至于TWSDLHTMLPublish則能夠自動(dòng)的根據(jù)Delphi編寫的WebService來產(chǎn)生WSDL并且輸出此WSDL讓客戶端應(yīng)用程序能夠使用這個(gè)WSDL來調(diào)用WebService。說明了Delphi6中有關(guān)WebService的組件和其功能之后,現(xiàn)在就讓我們看看在Delphi6中開發(fā)WebService的步驟。下圖便是在Delphi6中開發(fā)WebService簡(jiǎn)易的步驟:hitemet信屈服務(wù)器數(shù)據(jù)庫服勢(shì)器客戶端計(jì)算機(jī)hitemet信屈服務(wù)器數(shù)據(jù)庫服勢(shì)器客戶端計(jì)算機(jī)ADD驅(qū)動(dòng)DBExpiressSiEI^tiI如凱驅(qū)動(dòng)圖11.5使用Delphi6開發(fā)WebService的步驟首先程序員必須編寫WebService的核心邏輯,然后定義此WebService的WSDL,以便讓客戶端能夠遵循標(biāo)準(zhǔn)調(diào)用。在編寫完WebService之后,接著程序員就可以使用Delphi6提供的WebServices組件組來編寫客戶端應(yīng)用程序,并且通過WSDL來調(diào)用WebService。在編寫WebService客戶端應(yīng)用程序時(shí),Delphi6提供了非常彈性的方法,允許程序員使用EarlyBinding或是LateBinding,不像某些解決方案只允許使用LateBinding。這種設(shè)計(jì)可以讓程序員在開發(fā)WebService解決方案時(shí)可以根據(jù)執(zhí)行效率或是執(zhí)行彈性來決定使用EarlyBinding或是LateBindingo為了讓讀者能夠真正的了解如何開發(fā)WebService系統(tǒng)并且范例Delphi6在SOAP和WebService方面的強(qiáng)勁功能,就讓我們使用一個(gè)實(shí)際的范例來說明如何使用Delphi6快速開發(fā)WebService和客戶端應(yīng)用程序,并且結(jié)合數(shù)據(jù)庫來提供客戶端信息。這個(gè)范例WebService是把MSSQL中的NorthWind數(shù)據(jù)庫中Employees數(shù)據(jù)表的數(shù)據(jù)作為服務(wù)提供出來,所有的數(shù)據(jù)可以使用多種工具進(jìn)行提取,圖11.6范例數(shù)據(jù)表至于這個(gè)范例的整體架構(gòu)如下圖所示。數(shù)據(jù)信息是儲(chǔ)存在MSSQL中,并且通過Delphi6的ADO技術(shù)來存取。至于編寫WebService的主體則是一個(gè)由Delphi6撰寫的簡(jiǎn)單Web應(yīng)用程序。最后我們編寫一個(gè)原生窗口應(yīng)用程序通過SOAP來調(diào)用此Web應(yīng)用程序編寫的WebServiceo

h-rteme+l言,息圖h-rteme+l言,息圖11.7編寫WebService的架構(gòu)圖11.2.1步驟1-開發(fā)SOAP服務(wù)器應(yīng)用程序首先程序員可以在Delphi中使用SOAPServerApplicationWizard來開發(fā)WebService服務(wù)器。在Delphi6中我們只需要點(diǎn)選File->New->Others菜單,然后點(diǎn)選WebServices頁次即可看到下圖的畫面,然后再點(diǎn)選SOAPServerApplication圖像。圖11.8Delphi6的SOAPServerApplication精靈在點(diǎn)選了SOAPServerApplication圖像之后,Delphi會(huì)詢問程序員要以那一種的實(shí)體型態(tài)來編寫WebService,如下圖所示。程序員可以選擇欲編寫的程序型態(tài),例如在這個(gè)范例中我選擇以WebAppDebuggerexecutable來編寫,因?yàn)檫@個(gè)程序型態(tài)可以讓我們?cè)陂_發(fā)WebService時(shí)能夠輕易的除錯(cuò)。當(dāng)然,程序員也可以選擇以一般的Window應(yīng)用程序來編寫WebService,而不使用SOAPServerApplication精靈提供的下列實(shí)體型態(tài)的程序。

□KICancelHelpYoumayselectfromoneofthefollowingtypesofWorldWideWebserverapplications.□KICancelHelpYoumayselectfromoneofthefollowingtypesofWorldWideWebserverapplications.L1SAPI/NSAPIDynamicLinkLibraryLCGIStand-aloneexecutableCWin-CGIStand-aloneexecutableCApacheSharedModule(DLL)<?WebAppDebuggerexecutableCoClassName:|L_FirstServiceNewSoapServerApplication圖11.9以Delphi6的WebAppDebugger應(yīng)用程序的形式開發(fā)WebService在點(diǎn)選了圖九的程序型態(tài)和OK按鈕之后,Delphi便會(huì)自動(dòng)幫助程序員產(chǎn)生如下的Web模塊。-ln|xj彥-ln|xj彥::WebModuleZPB5EHLHTTPSoapDispatcherlHTTPSoapPascallnvokerlWSDLHTMLPublishl圖11.10Delphi6建立建立的WebModule以及WebServices組件在圖十的Web模塊之中,Delphi自動(dòng)產(chǎn)生的THTTPSoapDispatcher組件可以讓W(xué)ebServer自動(dòng)調(diào)用此應(yīng)用程序,而TWSDLHTMLPublish組件則可以自動(dòng)產(chǎn)生敘述此WebService的WSDL內(nèi)容。現(xiàn)在再讓我們?cè)谶@個(gè)WebService程序的主窗體中加入一個(gè)TLabel并且設(shè)定它的Caption值為“第一個(gè)Web服務(wù)程序”,如上圖所示。11.2.2步驟2-定義WebService的服務(wù)接口并且編寫它接下來的步驟便是真正的編寫此WebService。首先在Delphi6中建立SOAPDataModule數(shù)據(jù)模塊,并且使用ADO連結(jié)到SQLServer:圖11.12SOAP類圖圖11.12SOAP類圖11.13SOAP數(shù)據(jù)庫模板這樣一個(gè)初步的提供數(shù)據(jù)集的Web服務(wù)就被建立起來了,運(yùn)行它讓它注冊(cè)在系統(tǒng)中。下面讓我們來編寫一個(gè)客戶端程序來使用它。這個(gè)客戶端程序的目的就是顯示,Web服務(wù)提供的數(shù)據(jù)集,并顯示出來,當(dāng)然在后面我們還要賦于它們相關(guān)的查詢功能。新建一個(gè)應(yīng)用通過File->New->Application,新建一個(gè)應(yīng)用,并在應(yīng)用的窗體中放入TSOAPConnection組件,如圖:圖11.14SOAP連接并設(shè)定它的URLName屬性值為“http://localhost:1024/First.L_FirstService”;打開Connected為True;連接數(shù)據(jù)集在應(yīng)用的主窗體上放入TClientDataSet組件,設(shè)定它的RemoteServer屬性值為TSOAPConnection,設(shè)置它的ProviderName屬性值為DataProvider,這樣連接數(shù)據(jù)集的任務(wù)就被完成了。加入一個(gè)數(shù)據(jù)顯示組件①ataGrid),就可以顯示將要出現(xiàn)的數(shù)據(jù)了。

FormlEmployeelDLastNameFirstNameTitle 1■■■DavolioNancvSalesRepresentative2FullerAndrewVicePresidentSales3LeverlingJanetSalesRepresentative4PeacockMargaretSalesRepresentative5BuchananStevenSalesManager6SuvamaMichaelSalesRepresentative11KingRobertSalesRepresentative10CallahanLauraInsideSalesCoordinator19DodsworthAnneSalesRepresentative■Lu21圖11.15通過WEBServices取得數(shù)據(jù)這時(shí),我們看到,整體數(shù)據(jù)集被完整的從服務(wù)端調(diào)用出來,顯示在設(shè)計(jì)好的數(shù)據(jù)介面下。是不是很方便,確實(shí)使用Delphi6開發(fā)一個(gè)WebService系統(tǒng)確實(shí)很方便,在我們開發(fā)的過程中,可以看到開發(fā)這樣的一個(gè)系統(tǒng)需要的時(shí)間是很少的。11.2.3高級(jí)的自定義Web服務(wù)接下來,為了讓大家看到Delphi6是如何將原有的程序設(shè)計(jì)資源進(jìn)行整合的,我們通過一個(gè)查詢美國州信息這樣的一個(gè)WebServer程序來展示它是怎樣將系統(tǒng)底層資源與WebServices程序設(shè)計(jì)方法進(jìn)行有效的結(jié)合,達(dá)到新的高度。同上面的步驟一樣,建立一個(gè)基本的WebServices的服務(wù)程序框架,并在其主表單中加入以下的組件,如圖:圖11.16ZIPSOAPServer當(dāng)然,這只是一個(gè)表面的內(nèi)容,與上面不同的是,我們現(xiàn)在提供給服務(wù)調(diào)用者一個(gè)服務(wù)接口,以幫助使用者,通過輸入相應(yīng)的ZIP信息就可以得到相應(yīng)的美國州的名稱服務(wù)。為了達(dá)到這樣的一個(gè)目標(biāo),我們要建立兩個(gè)單元文件,一個(gè)是提供的服務(wù)接口文件,一個(gè)是服務(wù)的實(shí)現(xiàn)文件,這兩個(gè)文件提供相應(yīng)的服務(wù)內(nèi)容。那么如何通過Delphi6來實(shí)現(xiàn)這樣的兩個(gè)文件呢?如果您是Delphi6的注冊(cè)用戶,那么您可以通過Borland的網(wǎng)站下載一個(gè)名稱為Invoker的Wizard,這個(gè)文件只是30余KB,安裝后,Delphi6的WebServices的服務(wù)生成Wizard環(huán)境中就會(huì)增加這樣的一個(gè)界面圖標(biāo)。

圖11.17類生成器雙擊它,出現(xiàn)一個(gè)對(duì)話框,在其中的NametoUse的屬性值中,填寫ZipInterFace內(nèi)容,選擇OK后,Wizard將為我們生成兩個(gè)文件,圖11.18生成過程圖11.19生成的接口文件及實(shí)現(xiàn)文件因?yàn)閆ipInterface.pas提供的是服務(wù)的接口內(nèi)容,所以我們?cè)谄渲芯帉懭绱a清單5:代碼清單5:unitZipinterface;interfaceTypeIZipService=Interface(IInvokable)['{B3977E60-6810-48EC-98E7-7254ABB31189}']{使用Ctrl+Shift+G組合鍵生成的GUID代碼}FunctionFindCity(Country:String;Zip:Integer):String;StdCall;//服務(wù)函數(shù)說明End;implementationusesInvokeRegistry;initializationInvRegistry.RegisterInterface(TypeInfo(IZipService));end.其中FindCity函數(shù),提供通過ZIP代碼查詢相應(yīng)的城市信息這樣的一個(gè)服務(wù)。FunctionFindCity(Country:String;Zip:Integer):String;StdCall;這時(shí),一個(gè)服務(wù)的接口就被完成,下面將要用實(shí)際的代碼來實(shí)現(xiàn)相應(yīng)的服務(wù)內(nèi)容。也就是ZipIntfImplementation.pas中相應(yīng)的實(shí)現(xiàn)內(nèi)容。unitZipIntfImplementation;interfaceUsesInvokeRegistry,ZipInterface;TypeTZipService=Class(TInvokableClass,IZipService)FunctionFindCity(Country:String;Zip:Integer):String;StdCall;End;implementationUsesINIFiles,SysUtils;//在這里我們使用的是INI文件保存相應(yīng)的ZIP信息{TZipService}FunctionTZipService.FindCity(Country:String;Zip:Integer):String;VarININame:String;INI:TINIFile;ZipStr:String;Begin{檢查參數(shù)值}If((UpperCase(Country)<>'US')And(UpperCase(Country)<>'FIN'))ThenRaiseException.Create('不合法的參數(shù)〃'+Country+'〃,'+'正確的參數(shù)應(yīng)該是〃US〃或者〃FIN〃.’);ZipStr:=IntToStr(Zip);While(Length(ZipStr)<5)doZipStr:='0'+ZipStr;{lookupthevalueintheINIfile}ININame:=IncludeTrailingBackslash(ExtractFilePath(ParamStr(0)))+'ZipCodes.ini';INI:=TINIFile.Create(ININame);TryResult:=INI.ReadString(Country,ZipStr,'');If(Result='')ThenRaiseException.Create('不合法的zip代碼〃'+ZipStr+'〃'+'對(duì)于國家為〃'+Country+'〃.');FinallyINI.Free;End;End;InitializationInvRegistry.RegisterInvokableClass(TZipService);end.以上就是相應(yīng)的服務(wù)內(nèi)容及其接口的實(shí)現(xiàn)方法。接下來,編譯運(yùn)行它,這時(shí)相應(yīng)的ZIP服務(wù)已經(jīng)被注冊(cè)到系統(tǒng)中,可以供大家使用了。下面,要做的工作就是實(shí)現(xiàn)相應(yīng)的客戶端應(yīng)用,用它來調(diào)用相應(yīng)的Web服務(wù),那么該怎么做呢?是不是與上面介紹的相應(yīng)的方法一樣呢?這里要注意的是,剛才我們實(shí)現(xiàn)的一個(gè)客戶端程序,它的功能是將數(shù)據(jù)集提取出來,供使用,而現(xiàn)在要實(shí)現(xiàn)的功能是將相應(yīng)的服務(wù)提取出來,這在實(shí)現(xiàn)方法上略有不同,這里也特別突出了THTTPRIO組件的使用過程及方法。新建一個(gè)客戶端接口工程文件通過主菜單的File->New->Application,來新建一個(gè)空白的工程文件,這個(gè)文件主要是實(shí)現(xiàn)提取相應(yīng)的服務(wù)功能所使用的。在上面放入相應(yīng)的THTTPRIO組件,當(dāng)然為什么要放入這樣的一個(gè)組件,我們?cè)谇懊娴慕M件介紹中已經(jīng)介紹過了,在這里就不進(jìn)行更詳細(xì)的介紹了。在放入的THTTPRIO組件中,有一個(gè)屬性值是我們必須要注意的,也就是與服務(wù)的接口內(nèi)容,如圖11.20:圖11.20標(biāo)識(shí)接口在URL屬性值中,填寫相應(yīng)的服務(wù)接口,在這里填寫的內(nèi)容是:“http://localhost:1024/ZipSOAPServer.ZipCodeSOAPServerCoClass/soap”,這就是所要呼叫的服務(wù)的相關(guān)接口。如果在Internet網(wǎng)絡(luò)上,有UDDI標(biāo)準(zhǔn)對(duì)于相應(yīng)的Web服務(wù)的名稱及接口提供服務(wù),而現(xiàn)在因?yàn)槲覀兪褂玫氖潜緳C(jī)進(jìn)行的調(diào)試所以直接輸入了相應(yīng)的內(nèi)容。當(dāng)然如果不知道怎樣提取這樣的一個(gè)內(nèi)容,可以通過在調(diào)試環(huán)境中的瀏覽器界面中直接提取,具體方法如圖所示:

打開。在新窗口中打開(山目標(biāo)另存為(由…打印目標(biāo)?C1SID:{102C3於「9對(duì)6-11D3-AB13-FD87ProgID:SEEVEE^l.Strvirlnfci剪切2^:復(fù)制快捷Localserver32:F:'FROGRAr\Bor1and\De1phi6FileStatus打開。在新窗口中打開(山目標(biāo)另存為(由…打印目標(biāo)?C1SID:{102C3於「9對(duì)6-11D3-AB13-FD87ProgID:SEEVEE^l.Strvirlnfci剪切2^:復(fù)制快捷Localserver32:F:'FROGRAr\Bor1and\De1phi6FileStatus:Foundr-j(D添加到收藏夾(日…DownloadbyNetAntsDownloadAllbyNetAnts圖DownloadbyNetAntsDownloadAllbyNetAnts圖11.22提取服務(wù)C1SID:{131羽56B-M01-414F-AB45-E96CProgID: 延$更ywZl成雖或。延$更.2...,.擘芝9 T 初.D:k軟件集中營(yíng)\網(wǎng)絡(luò)服務(wù)最新內(nèi)^Delphi6WJW0901\jarvinen\Server'Ei-LUAFM-rv-r1.巳i己FileStatus:Found圖11.21復(fù)制接口內(nèi)容也就是通過在相應(yīng)的ProgID中用鼠標(biāo)右鍵,選擇復(fù)制快捷方式,將相應(yīng)的內(nèi)容復(fù)制進(jìn)入剪貼板中,在相應(yīng)的THTTPRIO組件中的URL屬性中粘貼就可以了,最后加入soap字樣就可以了。當(dāng)然說了這么多,最終我們的目標(biāo)是要實(shí)現(xiàn)相應(yīng)的功能,接下來,在主表單中放入兩個(gè)TLable組件和兩個(gè)TEdit組件和一個(gè)按鈕組件。分別進(jìn)行相應(yīng)的設(shè)置后,結(jié)果如圖:在相應(yīng)的按鈕組件實(shí)現(xiàn)代碼中,寫入如下的代碼用于實(shí)現(xiàn)相應(yīng)的功能,(功能描述:通過在ZIP區(qū)域輸入相應(yīng)的ZIP代碼,通過調(diào)用服務(wù),在結(jié)果顯示框中顯示相應(yīng)的州及地區(qū)的英文名稱),具體實(shí)現(xiàn)如代碼清單6:代碼清單6:procedureTMainForm.LookupUSCodeClick(Sender:TObject);VarI:ZipInterface.IZipService;beginI:=HTTPRIO_USasZipInterface.IZipService;Edit1.Text:=I.FindCity('US',StrToInt(USZipCode.Text));end;當(dāng)然這個(gè)代碼本身是沒有什么值得研究的,但是有一點(diǎn)值得注意的是,我們?cè)谶@個(gè)服務(wù)的實(shí)現(xiàn)代碼中一定要加入相應(yīng)的接口文件,也就是剛才在服務(wù)代碼中的接口代碼單元(ZipInterface.PAS),這樣通過它就可以很輕松的知道相應(yīng)的服務(wù)接口是什么,那么是否在Internet上發(fā)布的服務(wù)也同樣要提供相應(yīng)的單元文件或其它文件呢?回答是否定的,我們可以通過另外一種方式來實(shí)現(xiàn)這樣的一個(gè)接口文件,下面關(guān)于如何調(diào)用Internet上的Web服務(wù)將講到在因特網(wǎng)上如何得到這樣的一個(gè)服務(wù)接口。也同時(shí)會(huì)繼續(xù)談到相應(yīng)的有關(guān)WSDL的有關(guān)概念。下面讓我們來運(yùn)行一下這個(gè)客戶端應(yīng)用吧,當(dāng)在ZIP代碼區(qū)域輸入相應(yīng)的ZIP代碼后,點(diǎn)擊相應(yīng)的按鈕,這時(shí)就可以看到結(jié)果區(qū)域顯示了相應(yīng)的美國州或地區(qū)的名稱簡(jiǎn)寫。

圖11.23提取服務(wù)的結(jié)果是不是,很值得振奮,這確實(shí)如程序員希望的那樣,將結(jié)果顯示在相應(yīng)的位置中,并且結(jié)果顯示的速度是非常之快的。11.2.4調(diào)用外部Web服務(wù)看到這些,程序員可能希望實(shí)現(xiàn)更為宏偉的目標(biāo),就是驗(yàn)證一下,Web服務(wù)是否象宣傳的那樣可以在世界的任意地區(qū)調(diào)用,而且接口是否很方便。那么我們接下來的工作就是將這樣的一個(gè)想法付諸實(shí)踐。兩年前,可能網(wǎng)上要想找到這樣的站點(diǎn)確實(shí)很難,但現(xiàn)在這樣的站點(diǎn)真的很多,包括微軟公司在內(nèi),許多公司都將自己的一些業(yè)務(wù)逐漸移植到相應(yīng)的Web服務(wù)上面來。當(dāng)然我們現(xiàn)在并不是要在這里實(shí)現(xiàn)一個(gè)完整的電子商務(wù)中的Web服務(wù)的調(diào)用,大家現(xiàn)在所要關(guān)注的是如何將這樣的一個(gè)標(biāo)準(zhǔn)通過Delphi6提供的強(qiáng)大功能來完成。在這里,向大家推薦使用的網(wǎng)站是網(wǎng)站,圖11.24XMethods站點(diǎn)它是一個(gè)供開發(fā)人員或其它相應(yīng)的技術(shù)人員進(jìn)行相應(yīng)的Web服務(wù)實(shí)驗(yàn)的一個(gè)站點(diǎn),在上面它提供了幾乎所有Web服務(wù)實(shí)現(xiàn)的可能,并提供相應(yīng)的WSDL描述和相應(yīng)的接口服務(wù)說明和示例。下面的例子就是要在它上面提供的服務(wù)當(dāng)中,選擇一個(gè)服務(wù)供Delphi制作的客戶端進(jìn)行使用。我們選擇了搜索引擎查詢功能的服務(wù),當(dāng)然這是一個(gè)非常有代表性的服務(wù),在許多網(wǎng)站中都有這樣的服務(wù)功能。現(xiàn)在程序員自己也可以將這樣的一個(gè)服務(wù)通過Delphi6介紹給大家。那么下面就讓大家來實(shí)踐一下如何將這樣的一個(gè)服務(wù)展示在面前的。服務(wù)的需求要制作這樣的一個(gè)服務(wù)客戶端,首先要了解這樣的一個(gè)服務(wù)需要一些什么內(nèi)容,這樣才可以通過相應(yīng)的程序來進(jìn)行編制及界面的構(gòu)造。在網(wǎng)站中找到這樣一個(gè)服務(wù)的相應(yīng)描述,ServiceName:SOAPWebSearch

MethodsIDNumber:32ServiceOwner:SQLDataContactEmail:ContactEmail:yzhang@ServiceHomePage:Description:http://www.SoapC/webSearch.htmlServiceHomePage:Description:SOAPInterfacetomajorsearchengines.

ReturnsHTMLsearchresultsasastring.SOAPEndpointURL:http://www.SoapC/xml/SQLDataSoap.WSDLSOAPAction:http://www.SoapC/xml/SQLDataSRLMethodNamespaceURI:http://www.SoapC/xml/SQLDataSoap.xsdMethodName(s):ProcessSRLWSDLURL:http://www.SoapC/xml/SQLDataSoap.WSDLInstructions:Usethefollowingparameters:SRLFile:ThenameoftheServiceRequestLanguageFile-use"WEB.SRI"forwebsearches.RequestName:Thenameofthesearchengine-eg.Altavista,Yahoo,Excite,etc.key:Thekeywordstobesearchedfor.ServerImplementation:SQLDataSampleClientCode:SampleClientCode:DiscussionLink:/ubb/Forum3/HTML/000024.htmlSOAPInterfacetomajorsearchengines.ReturnsHTMLsearchresultsasastring.它的大致意思就是,通過SOAP接口去實(shí)現(xiàn)一個(gè)搜索引擎,并且用一個(gè)串的變量返回相應(yīng)的HTML搜索結(jié)果。因?yàn)檫@個(gè)服務(wù)是用SQLData所實(shí)現(xiàn)的,所以它可以代表一個(gè)比較特殊的服務(wù)實(shí)現(xiàn)方法。它同時(shí)也通過這樣的一個(gè)說明告訴將要使用這樣的一個(gè)服務(wù)的使用者,它的WSDL為http://www.SoapC/xml/SQLDataSoap.WSDL,當(dāng)然也為我們提供了相應(yīng)的演示方法,如圖:

圖11.25搜索引擎站點(diǎn)示例它通過,選擇搜索引擎并在關(guān)鍵詞中輸入想要查詢的內(nèi)容,選擇Search按鈕后,就可以得到相應(yīng)的搜索結(jié)果頁面,在這里為了表示這樣一個(gè)服務(wù)是可用的,我們選擇搜索引擎為Google,輸入相應(yīng)的關(guān)鍵詞為SOAP,查找結(jié)果如下:圖11.26示例結(jié)果可以看到,結(jié)果是將所有有關(guān)SOAP的頁面及其索引顯示出來。這樣就可以非常輕松的完成相應(yīng)的搜索引擎功能,開發(fā)人員不用開發(fā)完成的搜索引擎功能,就可以通過這樣的方法得到一個(gè)強(qiáng)大的功能,這也正體現(xiàn)了,Web服務(wù)的開放性及通用性。那么我們接下來的工作就是如何將這樣的一個(gè)服務(wù)通過Delphi6來調(diào)用。如何作呢? 開發(fā)桌面搜索引擎新建一個(gè)工程文件,接著選擇主菜單File->new->Others->WebServices

圖11.27服務(wù)接口導(dǎo)入選擇WebServicesImport后,出現(xiàn)以WSDL信息生成對(duì)話窗,圖11.28服務(wù)接口導(dǎo)入過程在相應(yīng)的WSDL信息位置處填入:http://www.SoapC/xml/SQLDataSoap.WSDL,選擇Generate按鈕,生成相應(yīng)的服務(wù)所對(duì)就的ObjectPascal代碼,我們一般稱它為ProxyCode,將它保存為EngineProvider.pas文件,并保存所有的文件。EngineProvider文件的描述如代碼清單6:代碼清單6:UnitEngineProvider;interfaceusesTypes,XSBuiltIns;

typeSQLDataSoapPortType=interface(IInvokable):'{385EE7AF-630F-4931-B35A-639A10717484}']functionProcessSRL(constSRLFile:WideString;constRequestName:WideString;constkey:WideString):WideString;stdcall;〃這就是將要使用的搜索引擎接口函數(shù)functionProcessSRL2(constSRLFile:WideString;constRequestName:WideString;constkey1:WideString;constkey2:WideString):WideString;stdcall;functionProcessSQL(constDataSource:WideString;constSQLStatement:WideString;constUserName:WideString;constPassword:WideString):WideString;stdcall;end;implementationusesInvokeRegistry;initializationInvRegistry.RegisterInterface(TypeInfo(SQLDataSoapPortType),'http://www.SoapC/xml/SQLDataSoap.xsd','UTF-8');〃因?yàn)檎Z言標(biāo)準(zhǔn)為UTF-8,從這里可以看出,它支持相應(yīng)的漢字查詢end.這樣,就得到了相應(yīng)的接口代碼,下面可以通過ObjectPascal這樣,就得到了相應(yīng)的接口代碼,下面可以通過ObjectPascal的編制過程來實(shí)現(xiàn)相應(yīng)的客戶端功能。在這里的主表單中,進(jìn)行了如下的界面設(shè)計(jì):圖11.29開發(fā)客戶端提取服務(wù)通過在搜索引擎處選I擇選擇的搜索引擎來確定查詢需要的搜索引擎,在關(guān)鍵詞處填寫相應(yīng)的查詢內(nèi)容,通過啟動(dòng)服務(wù)通過在搜索引擎處選I擇選擇的搜索引擎來確定查詢需要的搜索引擎,在關(guān)鍵詞處填寫相應(yīng)的查詢內(nèi)容,通過啟動(dòng)服務(wù)來傳回相應(yīng)的結(jié)果。因?yàn)閭骰氐慕Y(jié)果是一個(gè)包含HTML文件內(nèi)容的String類型,所以我們要在相應(yīng)的代碼中作出如代碼清單7的處理:代碼清單7procedureTForm1.Button1Click(Sender:TObject);vari:SQLDataSoapPortType;Test:String;begini:=HTTPRIO1asSQLDataSoapPortType;Memo1.Lines.Add(i.ProcessSRL('WEB.SRI',Edit1.Text,Edit2.Text));Test:='d:\'+Edit1.Text+Edit2.Text+'.html';〃將相應(yīng)的結(jié)果生成文件Memo1.Lines.SaveToFile(Test);//用戶瀏覽器的界面觀察結(jié)果WebBrowser1.Navigate(Test)end;這段代碼主要是將傳回的串結(jié)果轉(zhuǎn)化為相應(yīng)的HTML文件,并在WebBrowser組件當(dāng)中顯示出來,這樣看到的結(jié)果就如圖所示:圖11.30服務(wù)提取結(jié)果這樣是不是很簡(jiǎn)單,確實(shí)Delphi6為開發(fā)人員提供了完成Web服務(wù)的強(qiáng)大功能,通過這樣的一個(gè)功能,程序員可以不費(fèi)力的完成相應(yīng)的開發(fā)任務(wù),并將相應(yīng)的系統(tǒng)與現(xiàn)有的系統(tǒng)進(jìn)行有效的集成來構(gòu)成新的完整的系統(tǒng),這也正是電子商務(wù)系統(tǒng)所要求的功能特點(diǎn)。11.2.5WebSnap與Web服務(wù)集成前面,通過一個(gè)不短的篇幅,講述了用Delphi6構(gòu)造Web服務(wù)的服務(wù)端及客戶端,接著又介紹了如何通過Delphi6來調(diào)用因特網(wǎng)中的相應(yīng)服務(wù)——舉例介紹了如何實(shí)現(xiàn)一個(gè)搜索引擎的功能。接下來,我們要通過一個(gè)更加直觀的例子,將Delphi6的WebSnap技術(shù)與WebServices技術(shù)整合在一起,通過這樣的一個(gè)例子,讓大家來感覺一下Delphi6的技術(shù)高度集成性,也使開發(fā)人員充分感覺到使用Delphi6作為電子商務(wù)系統(tǒng)的開發(fā)工具是多么的引人入勝。建立顯示框架在顯示相應(yīng)的頁面首先要建立相應(yīng)的頁面,前面我們已經(jīng)對(duì)WebSnap如何建立動(dòng)態(tài)頁面進(jìn)行了很詳細(xì)的介紹,在這里就不再進(jìn)行介紹了。有不明白的地方,可以參考前面的章節(jié)。但這里有一點(diǎn)是我們必須注意的,就是要在建立好的框架中加入相應(yīng)的服務(wù)接口,也就是THTTPRIO組件,如圖:

圖11.31增加THTTPRIO組件同時(shí),提供服務(wù)所需要的輸入及輸出界面,在這里使用了Adapter組件來提供相應(yīng)的輸入輸入界面,并提供一個(gè)按鈕來進(jìn)行相應(yīng)的查詢功能。增加界面組件圖11.32增加方法和輸入界面組件圖11.33增加引擎驅(qū)動(dòng)功能最終,通過這樣幾個(gè)組件構(gòu)成了將要提供服務(wù)的界面,通過它只要輸入相應(yīng)的ZIP代碼得到的就是相應(yīng)的地區(qū)簡(jiǎn)稱。但是,在這里需要為它們填寫一些代碼以實(shí)現(xiàn)相應(yīng)的功能,當(dāng)然要增加這樣的一個(gè)功能,首先要將相應(yīng)的服務(wù)接口文件引入相應(yīng)的頁面顯示文件中,就是ZIPInterface.pas。具體實(shí)現(xiàn)也就是:usesWebReq,WebCntxt,WebFact,Variants,ZipInterface;那么下面就是實(shí)現(xiàn)相應(yīng)的功能的具體操作方式,代碼清單8:代碼清單8:unitMainPage;interfaceusesWindows,Messages,SysUtils,Classes,HTTPApp,WebModu,HTTPProd,ReqMulti,WebDisp,WebAdapt,WebComp,CompProd,PagItems,SiteProd,WebForm,MidItems,Rio,SoapHTTPClient;typeTShowWebResult=class(TWebAppPageModule)AdapterPageProducer:TAdapterPageProducer;WebAppComponents:TWebAppComponents;ApplicationAdapter:TApplicationAdapter;PageDispatcher:TPageDispatcher;AdapterDispatcher:TAdapterDispatcher;Adapter1:TAdapter;ZIPCode:TAdapterField;ZIPResult:TAdapterField;AdapterForm1:TAdapterForm;SearchZIP:TAdapterAction;LayoutGroup1:TLayoutGroup;LayoutGroup2:TLayoutGroup;AdapterFieldGroup1:TAdapterFieldGroup;AdapterCommandGroup2:TAdapterCommandGroup;HTTPRIO1:THTTPRIO;procedureAdapterPageProducerHTMLTag(Sender:TObject;Tag:TTag;constTagString:String;TagParams:TStrings;varReplaceText:String);procedureZIPCodeGetValue(Sender:TObject;varValue:Variant);procedureZIPResultGetValue(Sender:TObject;varValue:Variant);procedureSearchZIPExecute(Sender:TObject;Params:TStrings);procedureAdapter1BeforeExecuteAction(Sender,Action:TObject;Params:TStrings;varHandled:Boolean);private{Privatedeclarations}public{Publicdeclarations}LZIPCode,LZIPResult:String;end;functionShowWebResult:TShowWebResult;implementationusesWebReq,WebCntxt,WebFact,Variants,ZipInterface;functionShowWebResult:TShowWebResult;beginResult:=TShowWebResult(WebContext.FindModuleClass(TShowWebResult));end;procedureTShowWebResult.AdapterPageProducerHTMLTag(Sender:TObject;Tag:TTag;constTagString:String;TagParams:TStrings;varReplaceText:String);beginifTagString='Result'thenbeginend;end;procedureTShowWebResult.ZIPCodeGetValue(Sender:TObject;varValue:Variant);beginValue:=LZIPCode;end;procedureTShowWebResult.ZIPResultGetValue(Sender:TObject;varValue:Variant);beginValue:=LZIPResult;end;procedureTShowWebResult.SearchZIPExecute(Sender:TObject;Params:TStrings);vari:ZipInterface.IZipService;begini:=HTTPRio1asZipInterface.IZipService;LZipResult:=I.FindCity('US',StrToInt(LZipCode));//在這里提供相應(yīng)的服務(wù)功能,操作方式與前面的范例幾乎沒有任何區(qū)別end;procedureTShowWebResult.Adapter1BeforeExecuteAction(Sender,Action:TObject;Params:TStrings;varHandled:Boolean);begin//初始化LZIPCode,LZIPResult這兩個(gè)值ifAssigned(ZIPCode.ActionValue)thenLZIPCode:=ZIPCode.ActionValue.Values[0];ifAssigned(ZIPResult.ActionValue)thenLZIPResult:=ZIPResult.ActionValue.Values[0];end;initializationifWebRequestHandler<>nilthenWebRequestHandler.AddWebModuleFactory(TWebAppPageModuleFactory.Create(TShowWebResult,TWebPageInfo.Create([wpPublished{,wpLoginRequired}],'.html'),caCache));

end.結(jié)果當(dāng)完成了以上許多的內(nèi)容后,程序員們的一個(gè)迫切要求是看到一個(gè)結(jié)果。那么啟動(dòng)相應(yīng)的的調(diào)試工具 (WebAppDebugger),開始相應(yīng)的服務(wù)??吹较鄳?yīng)的列表:圖11.34開始運(yùn)行客戶端應(yīng)用選擇GO按鈕,那么就進(jìn)入了相應(yīng)的瀏覽器界面,就是這樣的一個(gè)內(nèi)容頁面,它具有相應(yīng)的輸入及輸出內(nèi)容,同時(shí)也提供了一個(gè)查詢功能按鈕,讓使用者可以在這里使用相應(yīng)的功能。如圖:圖11.35客戶端初始界面在ZIP代碼輸入界面中,輸入“01056”,接著開始查詢,很快你就可以看到相應(yīng)的結(jié)果,確實(shí)與桌面應(yīng)用結(jié)果是一樣的,而且效率也同樣的高,如圖:

圖11.36運(yùn)行服務(wù)后的結(jié)果11.2.6Web服務(wù)的跨平臺(tái)能力前面我們所做的一些示例,都是在Windows環(huán)境下的IIS服務(wù)器進(jìn)行操作的,在這些環(huán)境下產(chǎn)生的應(yīng)用系統(tǒng)都具有了Windows下的特點(diǎn)。經(jīng)常說Web服務(wù)是不受平臺(tái)限制的,那么我們是否可以可以一個(gè)與平臺(tái)無關(guān)的系統(tǒng)呢?回答是肯定的。眾所周知,Apache服務(wù)作為一個(gè)優(yōu)秀的跨平臺(tái)服務(wù)的平臺(tái)提供者,可以在多操作平臺(tái)下運(yùn)行,為了驗(yàn)證Web服務(wù)的跨平臺(tái)特征,讓我們來建立一個(gè)使用Apache平臺(tái)下服務(wù)的應(yīng)用程序來表現(xiàn)它的特點(diǎn)吧!首先,還是在下,選擇了一個(gè)服務(wù),它實(shí)現(xiàn)的功能就是讀出今天相應(yīng)的重要新聞。它是完全以Apache平臺(tái)為基礎(chǔ)的。下面就是它的服務(wù)描述列表:ServiceName:immigrationnews-serviceXMethodsIDNumber:120ServiceOwner:VivekAnumoluContactEmail:vanumolu@ServiceHomePage:/wsdlDescription:RecentNewsonImmigrationProvidesthelatestinformationonthetopicofimmigration,gleanedfromvariouswebsitesmanually.Currentlytheservicedisplaysoneandonlyonenewsitem.Theplanistobeefuptheserviceandprovidemoreinterfacesinthenearfuture.SOAPEndpointURL:/soap/servlet/rpcrouterSOAPAction:NoneMethodNamespaceURI:urn:immigrationnews-serviceMethodName(s):getLatestNewsItemWSDLURL:/wsdl/ImmigrationNewsService.wsdlInstructions:ServerImplementation:ApacheSampleClientC

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論