用Delphi?6開發(fā)Web?Service初探
簡(jiǎn)介:“網(wǎng)絡(luò)就是計(jì)算機(jī),軟件就是服務(wù)”的思想已經(jīng)逐步深入人心。由于Web?Services能夠通過網(wǎng)絡(luò)把服務(wù)直接遞送給終端用戶,而且由眾多主流廠商所支持和描繪的美好前景也讓我們心動(dòng)不已。據(jù)有關(guān)報(bào)告預(yù)計(jì),2002年多數(shù)企業(yè)將會(huì)對(duì)于Web服務(wù)產(chǎn)生關(guān)心。另外,在2004年Fortune?2000家企業(yè)引進(jìn)的應(yīng)用軟件解決方案之中,Web服務(wù)將占很大的比重。最近,關(guān)于如何建立Web?Service的文章較多,但大多是用VS.NET完成的,而關(guān)于如何用Delphi?6開發(fā)的文章較少。本文介紹了一個(gè)用Delphi?6開發(fā)Web?Service的簡(jiǎn)單的例子,以達(dá)到拋磚引玉之效果。?
一、?Web?Service概述?
盡管關(guān)于Web?Service是什么有各種各樣的理解,但下面的定義有助于讀者從不同側(cè)面、不同層次了解Web?Service。第一:Web?Service就是一個(gè)應(yīng)用程序。它通過WEB向外界提供了如何調(diào)用自身功能/服務(wù)的說明(WSDL)。這可以讓任何人從任何地方使用它所提供的這些服務(wù)。或者這樣說,Web?Service是指可以通過Web技術(shù)實(shí)現(xiàn)動(dòng)態(tài)聯(lián)動(dòng)的軟件。?
第二:Web?Service是新興的電子商務(wù)應(yīng)用(IBM公司高級(jí)副總裁兼軟件部執(zhí)行官Steve?Mills語(yǔ))。Web?Service使在Web上的彼此互聯(lián)和交互更容易、更有效,并可以大大降低目前在B2B等環(huán)境下進(jìn)行編碼定制時(shí)所需的時(shí)間。第三:Web?Services是透過網(wǎng)絡(luò)享用遠(yuǎn)程服務(wù)的一種概念。第四:Web?Services是建立可互操作的分布式應(yīng)用程序的新平臺(tái)。Web?Services的主要目標(biāo)是跨平臺(tái)的可互操作性。Web?Services平臺(tái)是一套標(biāo)準(zhǔn),它定義了應(yīng)用程序如何在WEB上實(shí)現(xiàn)互操作性。第五:Web?Services是指一套軟件工具,以及一種旨在使軟件通過互聯(lián)網(wǎng)發(fā)揮類似拼裝玩具作用的整體處理方式。第六:Web?Service是一種想把全世界的Internet/Intranet變成一個(gè)虛擬計(jì)算環(huán)境的觀念和技術(shù)。第七:Web?服務(wù)是一個(gè)被包裝成單一實(shí)體,且被發(fā)布以供其它程序使用的功能集合,或者說Web?服務(wù)是Internet上一系列能夠以編程的方式調(diào)用的相關(guān)的應(yīng)用程序功能。還有一些其它的說法,但通過這些定義,我們可以看出Web?Services的基本理念是:把軟件做成服務(wù),并且遵從相應(yīng)的標(biāo)準(zhǔn),讓不同的系統(tǒng)可以跨越平臺(tái),彼此相互兼容,具有進(jìn)行無縫通信和數(shù)據(jù)共享的能力。?
接著,我們看看關(guān)于Web?Services的幾個(gè)核心概念。第一:Web?Services若要讓異構(gòu)平臺(tái)上不同系統(tǒng)可以相互通信和共享數(shù)據(jù),那數(shù)據(jù)在WEB上傳輸必須以一定的標(biāo)準(zhǔn)和格式進(jìn)行,這個(gè)表示數(shù)據(jù)的標(biāo)準(zhǔn)就是XML(所以微軟稱之為XML?Web?Services)。第二:不同系統(tǒng)遵從什么協(xié)議發(fā)送和接收這些標(biāo)準(zhǔn)的XML數(shù)據(jù)從而達(dá)到相互通信的目的呢?這個(gè)必須遵守的協(xié)議就是SOAP(Simple?Object?Access?Protocol簡(jiǎn)單對(duì)象訪問協(xié)議)。SOAP是在2000年5月8日由Microsoft?和IBM等公司參與制定的規(guī)范。SOAP不與任何一種對(duì)象模式(如DCOM、CORBA等)相關(guān),它是一種獨(dú)立的、通用的、基于XML標(biāo)準(zhǔn)的、文本的對(duì)象間訪問協(xié)議。簡(jiǎn)而言之,SOAP是運(yùn)用?XML?技術(shù)之遠(yuǎn)程過程調(diào)用?(?Remote?Procedure?Call)?的通訊協(xié)議。SOAP把對(duì)象間的訪問請(qǐng)求和響應(yīng)都打包成XML文檔,在對(duì)象間傳遞。由于SOAP傳遞的消息都以XML文檔形式發(fā)送和接收,它最理想、最自然的實(shí)現(xiàn)方式就是HTTP,所以客戶端僅需具備基本?TCP/IP?網(wǎng)絡(luò)環(huán)境,即可享用全球各處之?Web?Services。第三:其他系統(tǒng)如何知道你的Web?Services是完成什么功能的?你如何讓其他系統(tǒng)知道你的Web?Services提供了哪些服務(wù)?解決辦法就是WSDL(Web?Service?Description?Language-Web?服務(wù)描述語(yǔ)言)。它用機(jī)器可閱讀的格式描述了你的Web?Services,從而讓其他系統(tǒng)可以調(diào)用你所提供的服務(wù)。只要我們能夠取得特定Web?Service的WSDL,就可以從其中了解它提供的服務(wù),以及如何呼叫這個(gè)Web?Service。WSDL也是?XML?,只是有一定的規(guī)范要求。服務(wù)端提供?WSDL?文件最重要的用途就是向客戶端提供服務(wù)端接口的描述。第四:你的Web?Services如何發(fā)布以便讓世界上任何一個(gè)地點(diǎn)的人或系統(tǒng)得知你有這項(xiàng)服務(wù)從而調(diào)用它?或者作為服務(wù)請(qǐng)求者,你如何搜索你需要的Web?Services呢?這個(gè)概念為UDDI(?Universal?Description,?Discovery,?Integration-通用描述、發(fā)現(xiàn)與集成)。類似于yahoo提供的搜索網(wǎng)站的引擎和B2B電子商務(wù)的產(chǎn)品目錄搜索,Web?Service的提供者必須在UDDI注冊(cè)中心注冊(cè),而服務(wù)的請(qǐng)求者若搜索某項(xiàng)服務(wù),可到UDDI注冊(cè)中心查詢。UDDI注冊(cè)中心扮演了服務(wù)的代理者的角色。現(xiàn)在有商業(yè)的UDDI運(yùn)營(yíng)商和公眾UDDI注冊(cè)中心。三者的關(guān)系如下圖所示:?
圖1?服務(wù)提供者、服務(wù)請(qǐng)求者、服務(wù)代理者的關(guān)系
UDDI與XML、SOAP(簡(jiǎn)單對(duì)象訪問協(xié)議)以及WSDL(Web服務(wù)描述語(yǔ)言)一起成為Web?Services的事實(shí)上的核心標(biāo)準(zhǔn)。??
二、如何用Delphi?6開發(fā)Web?Services?
Web?Service可以由任何的技術(shù)開發(fā),Delphi6作為Microsoft?Window平臺(tái)的Web?Services?基礎(chǔ)環(huán)境與開發(fā)工具,將?RAD便利性帶入Web?Services?開發(fā)領(lǐng)域,簡(jiǎn)化了開發(fā)Web?Services應(yīng)用程序復(fù)雜度,讓開發(fā)人員專注于應(yīng)用面的開發(fā),而無須顧及繁瑣的Web?Services規(guī)格面制作。下面我們以一個(gè)簡(jiǎn)單的例子說明如何用Delphi?6開發(fā)Web?Services。這個(gè)例子中我們提供了查詢成績(jī)的服務(wù),客戶端(服務(wù)請(qǐng)求者——可以是瀏覽器、Windows程序甚或Linux程序,在這里,為了簡(jiǎn)單起見,我們用了傳統(tǒng)的Windows程序)可以輸入學(xué)號(hào),查詢出相應(yīng)的成績(jī)來。?
1、創(chuàng)建服務(wù)?
首先我們要建立一個(gè)成績(jī)表,名稱為Grade。我們?cè)赟QL?SERVER里面建立一個(gè)TEST庫(kù),在其下建立Grade表,它有三個(gè)字段,分別為StudentID、Name、Grade。隨后我們隨便向里面添加一些數(shù)據(jù)。然后我們配置一下ODBC,在系統(tǒng)DSN中添加一個(gè)數(shù)據(jù)源,名稱起為Grade,指向我們剛才建立的TEST庫(kù)。如圖二所示:?
圖2?配置ODBC
接著我們?cè)贒elphi6里啟動(dòng)New?|?Web?Services?|?Soap?Server?Application,確定后,在接下來的對(duì)話框中選擇Web?App?Debugger?executable。我們選擇這種類型制作Web?Services是因?yàn)檫@個(gè)形態(tài)可以讓我們?cè)陂_發(fā)時(shí)便于調(diào)試。設(shè)置其CoClass?Name為MyWebServicesTest1,如下圖所示:?
圖3?建立Web?Services
這時(shí)Delphi會(huì)自動(dòng)給我們生成一個(gè)Form和一個(gè)WebModule,WebModule中的幾個(gè)組件是幫助我們用SOAP進(jìn)行通信和發(fā)布WSDL的,有了它們,我們就可以開始集中精力編寫實(shí)際的應(yīng)用代碼了。現(xiàn)在我們New一個(gè)Data?Module?,在File菜單里選擇New|Data?Module,在其上放置一個(gè)ADOQuery以連接我們的數(shù)據(jù),設(shè)置其ConnectionString屬性為Provider=MSDASQL.1;Password=sa;Persist?Security?Info=True;User?ID=sa;Data?Source=Grade(選擇Build,然后選擇微軟提供的ODBC驅(qū)動(dòng),選下一步,使用指定的數(shù)據(jù)源名稱Grade,輸入用戶名稱和密碼確定即可)。將該單元保存為dm。如圖所示:?
圖4?連數(shù)據(jù)源
現(xiàn)在我們要定義要存儲(chǔ)學(xué)生信息的結(jié)構(gòu)。我們New一個(gè)Unit,在file菜單里選擇New|Unit,寫上如下的代碼:?
unit?DataType;?
interface?
Uses?InvokeRegistry;?
Type?
TStudentInfo=Class(TRemotable)?
Private?
FName?:?String;?
FGrade?:?Single;?
published?
Property?Name?:?String?Read?FName?Write?FName;?
Property?Grade?:?Single?Read?FGrade?Write?FGrade;?
end;?
implementation?
Initialization?
RemClassRegistry.RegisterXSClass(TStudentInfo);?
Finalization?
RemClassRegistry.UnRegisterXSClass(TStudentInfo);?
end.?
因?yàn)閷W(xué)生信息需要傳遞到客戶端,所以它必須從?TRemotable?類派生。將這個(gè)Unit保存為DataType。??
接著,我們要建立用戶請(qǐng)求服務(wù)的接口,這個(gè)接口只有一個(gè)取得成績(jī)的功能。New一個(gè)Unit,寫上如下的代碼:?
unit?ServicesInterface;?
interface?
Uses?InvokeRegistry,DataType;?
Type?
ISoapGrade=Interface(IInvokable)?
['{9884ADA8-8FDC-4002-94A3-2370A269018F}']?//注意,要給這個(gè)接口分配//一個(gè)GUID,在Delphi里用Crtl+Shift+G產(chǎn)生。?
Function?GetGrade(Number:Integer):TStudentInfo;StdCall;?//調(diào)用這個(gè)接口函數(shù)?
//將返回一個(gè)TstudentInfo類型的數(shù)據(jù)。?
End;?
implementation?
Initialization?
InvRegistry.RegisterInterface(TypeInfo(ISoapGrade));?
end.?
將這個(gè)單元保存為ServicesInterface。?
然后我們要編寫這個(gè)接口的實(shí)現(xiàn)類。在Unit2(WebModule單元)里添加實(shí)現(xiàn)類的定義。完整的代碼如下:?
unit?Unit2;?
interface?
uses?SysUtils,?Classes,?HTTPApp,?WSDLPub,?SOAPPasInv,?SOAPHTTPPasInv,?SoapHTTPDisp,?WebBrokerSOAP;?
type?
TWebModule2?=?class(TWebModule)?
HTTPSoapDispatcher1:?THTTPSoapDispatcher;?
HTTPSoapPascalInvoker1:?THTTPSoapPascalInvoker;?
WSDLHTMLPublish1:?TWSDLHTMLPublish;?
private?
{?Private?declarations?}?
public?
{?Public?declarations?}?
end;?
var?
WebModule2:?TWebModule2;?
implementation?
uses?WebReq,InvokeRegistry,DataType,ServicesInterface,dm;??
Type?
TSoapGrade=class(TInvokableClass,ISoapGrade)?
Protected?
Function?GetGrade(Number:Integer):TStudentInfo;StdCall;?
End;?//定義這個(gè)接口類?
Function?TSoapGrade.GetGrade(Number:Integer):TStudentInfo;StdCall;??
Begin?
Result:=TStudentInfo.Create;?
If?(?Not?Assigned(?DataModule3))?Then?
DataModule3:=TDataModule3.Create(Nil);?//如果DataModule3沒有創(chuàng)建,則創(chuàng)建它。?
Try??
With?DataModule3.ADOQuery1?Do?
Begin?
active:=false;?
sql[0]:='select?*?from?Grade?where?StudentID='+inttostr(Number)+';?
active:=true;?
//根據(jù)用戶輸入的學(xué)號(hào)和數(shù)據(jù)庫(kù)連接。?
If?(Not?Eof)?Then?
Begin?
Result.Name:=FieldByName('Name').AsString;?
Result.Grade:=FieldByName('Grade').AsFloat;??
//從數(shù)據(jù)庫(kù)里取得合適的值給要傳遞的信息。?
End?
Else?
Begin?
Result.Name:='未查詢到!';?Result.Grade:=0;?
End;?
Close;?
End;?
Finally?
DataModule3.Free;?DataModule3:=Nil;?
End;?
End;?
initialization?
WebRequestHandler.WebModuleClass:=TWebModule2;?
InvRegistry.RegisterInvokableClass(TSoapGrade);?
end.?
到現(xiàn)在,我們已經(jīng)創(chuàng)建了一個(gè)Web?Services!保存,編譯,運(yùn)行,即在Web?App?Debugger那里完成了此Web?Services的注冊(cè)工作。那么我們這個(gè)Web?Services提供了什么功能?如何調(diào)用它?這些問題可以通過看看它的WSDL來看到。我們啟動(dòng)Web?App?Debugger(在Tools菜單下),然后啟IE,在地址欄里輸入:
http://localhost:1024/server.MyWebServicesTest1/wsdl/IsoapGrade,即可看到用XML語(yǔ)言寫成的WSDL,有了它,服務(wù)請(qǐng)求者就可以調(diào)用我們的服務(wù)了。 ?
2、實(shí)現(xiàn)客戶端,調(diào)用服務(wù)?
我們建立一個(gè)普通的應(yīng)用程序,在form上面放置3個(gè)label、3個(gè)edit和2個(gè)button以及一個(gè)HTTPRIO1(在WebServices組件頁(yè)里),將HTTPRIO1的URL屬性設(shè)為
http://localhost:1024/server.MyWebServicesTest1/soap,以便利用SOAP通信。界面如下圖所示: ?
圖5?客戶端的傳統(tǒng)windows程序界面
接著為了讓這個(gè)客戶端程序知道我們剛才建立的Web?Services的WSDL以便請(qǐng)求服務(wù),我們必須在客戶端那里導(dǎo)入WSDL以便獲得服務(wù)的接口。幸運(yùn)的是,我們根本不必很麻煩的自己編程,Delphi已經(jīng)給我們做了。啟動(dòng)New?|?Web?Services?|Web?Services?Importer,然后輸入WSDL所在URL地址為:
http://localhost:1024/server.MyWebServicesTest1/wsdl/IsoapGrade,接著確定產(chǎn)生,Delphi自動(dòng)會(huì)為我們產(chǎn)生兩個(gè)unit,這樣接口的事情就全部交給Delphi,我們就不必管了。如圖所示: ?
圖6?引入WSDL
最后,在Form1的確定按鈕的OnClick事件里添加如下的代碼:?
procedure?TForm1.Button1Click(Sender:?TObject);?
Var?
Student:TStudentInfo;?
begin?
Student:=(HTTPRIO1?As?ISoapGrade).GetGrade(StrToInt(Edit1.Text));?
If?(Assigned(Student))?Then?
Begin?
Edit2.Text:=Student.Name;?
Edit3.Text:=floattostr(Student.Grade);?
End;?
end;?
并注意要在unit1的uses中添加unit2和unit3。保存,編譯。至此我們的客戶端程序開發(fā)完畢,調(diào)用Web?Services是不是很簡(jiǎn)單?下圖是客戶端調(diào)用的結(jié)果:?
圖7?調(diào)用的執(zhí)行結(jié)果
目前互聯(lián)網(wǎng)上已經(jīng)有一些網(wǎng)站羅列了許多Web?Services,例如
http://www.xmethods.com,上面有關(guān)于各個(gè)Web ?Services說明以及WSDL的描述,讀者若有興趣可以自己編寫客戶端程序引入上面的WSDL。當(dāng)讀者能夠利用自己編寫的客戶端跨越各種平臺(tái)和網(wǎng)絡(luò)結(jié)構(gòu),調(diào)用地球另一側(cè)的人也許用java寫成的Web?Services時(shí),相信你一定為Web?Services的強(qiáng)大而歡欣鼓舞。?
三、小結(jié)?
從上面的例子我們可以看到,只要理解了Web?Services的概念,熟悉了Web?Services的開發(fā)步驟,在Delphi的幫助下,開發(fā)Web?Services將不是一件很困難的事情。Web?Services最適合用于開發(fā)跨平臺(tái)和跨網(wǎng)絡(luò)進(jìn)行通信(因?yàn)槭褂胔ttp協(xié)議為防火墻所允許)的程序,可以跨越異質(zhì)架構(gòu),聯(lián)系客戶、供應(yīng)商、企業(yè)伙伴以及企業(yè)內(nèi)部之信息系統(tǒng),是電子商務(wù)B2B集成的最佳選擇。各個(gè)公司只要把商務(wù)邏輯“暴露”出來,成為Web?Service,就可以讓任何指定的合作伙伴調(diào)用這些商務(wù)邏輯,而不管他們的系統(tǒng)在什么平臺(tái)上運(yùn)行,使用什么開發(fā)語(yǔ)言。但也沒有必要把所有的軟件都做成Web?Services,正如“尺有所短,寸有所長(zhǎng)”一樣,傳統(tǒng)的windows程序也大有用武之地。Web?Services是目前很熱門也是正在迅速發(fā)展著的一項(xiàng)技術(shù),本文只是作者在學(xué)習(xí)中的一點(diǎn)小體會(huì),肯定有理解不深刻甚或錯(cuò)誤的地方,歡迎大家予以指正。?