BCB開發MIDAS(DataSnap)多層應用程式
作者: vrknights 日期: 2012 年 2 月 11 日
很多時候我們需要編製這樣的程式,即多個用戶端訪問並動作伺服器上的資料庫中的資料。若你想使用的方式不是WEB網站,則通常我們可以有兩種方式,1.用戶端直接連接遠端資料庫,登入並操作資料。2.用戶端不能直接連接遠端資料庫,而是串連到遠程伺服器上的服務端程式,將需要進行的操作以指令形式發送給服務端以實現操作資料.
第一種,商務邏輯全部位於用戶端程式中,一則不夠安全,二則不利於商務邏輯的變更。舉一個非常簡單的例子,V1.0的程式有註冊功能,可以儲存使用者名稱、密碼、設定檔等資訊。但如果這時你需要為程式增加一個“註冊時間”的欄位,你就需要升級所有的用戶端程式,以修改操作資料庫的關鍵性SQL語句。
第二種,商務邏輯可位於中間服務端程式中,用戶端僅僅負責提交申請和資料,使業務更加安全,同時也利於邏輯的變更。仍依上例,用戶端將使用者填寫的資料打包,調用服務端的遠程方法AddUser(MyPackget *)。而這時你僅僅需要修改服務端程式中的“AddUser(MyPackget*)”函數內的SQL即可。
第二種實現方式即典型的三層應用體繫結構。這種體系不僅實現了“瘦”用戶端,同時也可以很方便的實現分布式,你可以將伺服器分成多個登入伺服器及應用伺服器,根據當前伺服器承載狀態實現負載平衡。
MIDAS即多層應用體繫結構的關鍵技術。在Borland C++ Builder中,提供了DataSnap組件組,可以很簡單的實現多層應用體系。下面就來操作一下,簡單實現一下多層體系Client和Server的函數調用和訊息傳遞。
服務端方面:
1.在你的工作資料夾下,建立好Server目錄和Client目錄.
2.開啟BCB,選擇建立應用程式(Application),點擊儲存,將表單檔案儲存為MyServerFrm.cpp,將工作檔案儲存為MyServerPrj.cpp。當然,你也可以另取名稱。
3.在表單Form1上拖入一個文本組件Memo1,這個文本組件將用於顯示用戶端傳遞過來的訊息。
4.菜單上選擇 建立(New)->其他(Other)->多層(Muilter),選擇其中的”遠端資料模組”(Remote Data Module),在類名”CoClass Name”中填入”MyRDM”(你也可以另取名稱,但在後面如有用到MyRDM的,請使用你自己的名稱替代。),線程模式(Threading Model)保持Apartment不變。點擊確定(Ok)。將資料模組儲存為MyRDMImpl.cpp
5.開啟查看(View)->類型庫(Classes Libary,英文介面是不是顯示這個。我的介面是中文版的),在其中的IMyRDM上點擊右鍵,選擇New->Method建立一個方法。
6.將該方法命名為”SayHello”。在Parameters中,添加兩個參數。一個是訊息內容,Name是strSay,類型是BSTR,方式是:in
另外一個是傳回值,Name是nOk,類型是:int*,方式是:out,RetVal
如圖:
7.點擊類型庫上方的重新整理按鈕,在新顯示的代碼框中輸入如下代碼: 查看原始碼 列印 協助
| 1 |
STDMETHODIMP TMyRDMImpl::SayHello(BSTR strSay, int* nOk) |
| 3 |
AnsiString str=AnsiString(strSay); |
| 4 |
AnsiString strOutput=AnsiString("用戶端輸入的是: ") +str; |
| 5 |
Form1->Memo1->Lines->Add(strOutput); |
| 6 |
if(str.AnsiCompare("OK")==0){ |
並在SayHello函數所在的檔案中添加標頭檔,#include “MyServerFrm.h” (否則會Form1未定義)
8.執行一下程式,使之在系統中註冊。以便用戶端遠端連線。
9.在你的BCB安裝資料夾下的BIN目錄中,找到scksrvr.exe程式,運行之。
用戶端:
1.建立一個應用程式,將主表單儲存為:MyClientFrm.cpp,將工程檔案儲存為:MyClientPrj.cpp
2.點擊工程(Project)->添加到工程(Add to project),將Server目錄下的MyRDM_TLB.cpp添加到工程中。
3.檔案->建立(New)->資料模組(Data Module),建立一個資料模組,將檔案儲存為MyDataModule1.cpp.
4.向資料模組表單中,拖入DataSnap組件組中的SocketConnection組件。並將SocketConnection1的Address為127.0.0.1(即本機),SocketConnection1->ServerName找到XXX.MyRDM,GUID會根據ServerName自動擷取。連接埠保持211不變(除非你在scksrvr.exe中更改過連接埠)。並且,注意將SocketConnection1->Active改成True。此時,如果正常的話,服務端程式如未開啟,將會自動 運行。
5.向主表單Form1中添加 一個Edit1和一個按鈕Button1,雙擊Button1,在Button1Click事件中輸入如下代碼: 查看原始碼 列印 協助
| 1 |
void __fastcall TForm1::Button1Click(TObject *Sender) |
| 4 |
WideString wsSay=Form1->Edit1->Text; |
| 5 |
IDispatch* disp = (IDispatch *)DataModule1->SocketConnection1->AppServer; |
| 6 |
IMyRDMDisp TheRDM((IMyRDM*)disp); |
| 7 |
nOk=TheRDM.SayHello(wsSay); |
| 11 |
ShowMessage("Edit1中輸入的不是OK"); |
| 13 |
ShowMessage("Edit1中輸入的是OK"); |
並在Button1Click所在的檔案中添加標頭檔:#include “MyRDM_TLB.cpp” 和#include “MyDataModule.cpp”
6.運行之。並嘗試在Edit1中輸入不同的值 ,以觀察結果。
如圖所示:
至此,一個簡單的MIDAS結構就完成了。為了完善它,你只需要在Server端->MyRDM(遠端資料模組)中添加ADOConnection、ADOQuery、DatasetProvider、ADOTable等資料庫元件連線並操作資料庫,即可實現三層體繫結構。
對了,最後忘了一點沒有說。Apartment模式下的Remote Data Module 遠端資料模組的工作狀態是這樣的,在Server程式開始運行時,即建立第一個RDM,用於接受Client端的串連請求。當Server端和Client端正式串連上時,SERVER端會建立一個Remote Data Module,以接受新的用戶端串連請求。所以,每一個用戶端,都會有自己獨立、私人的的一個Remote Data Module.
那麼,問題來了。當你需要調用RDM的其他成員(如ADOQuery)時,需要使用m_DataModule以指定操作自己私人的遠端資料模組。即應該用:m_DataModule->ADOQuery1->SQL->Add(“select count(1) from users where username=:username and password=:password”); 而非TMyRDMImpl::ADOQuery1->SQL->Add(…)
切切,話說當年本人為此也付出不菲的時間代價。