BCB开发MIDAS(DataSnap)多层应用程序

来源:互联网 发布:mac 文件权限 去掉加号 编辑:程序博客网 时间:2024/04/30 04:55

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.点击类型库上方的刷新按钮,在新显示的代码框中输入如下代码:

查看源代码
打印帮助
1STDMETHODIMP TMyRDMImpl::SayHello(BSTR strSay,int* nOk)
2{
3    AnsiString str=AnsiString(strSay);
4    AnsiString strOutput=AnsiString("客户端输入的是: ") +str;
5    Form1->Memo1->Lines->Add(strOutput);
6    if(str.AnsiCompare("OK")==0){
7  
8       *nOk=1;
9    }else{
10       *nOk=0;
11    }
12}

并在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事件中输入如下代码:

查看源代码
打印帮助
1void __fastcall TForm1::Button1Click(TObject *Sender)
2{
3      intnOk=-1;
4      WideString wsSay=Form1->Edit1->Text;
5     IDispatch* disp = (IDispatch *)DataModule1->SocketConnection1->AppServer;
6     IMyRDMDisp TheRDM((IMyRDM*)disp);
7     nOk=TheRDM.SayHello(wsSay);
8     if(nOk==-1){
9        ShowMessage("执行出现错误");
10     }elseif(nOk==0){
11        ShowMessage("Edit1中输入的不是OK");
12     }elseif(nOk==1){
13        ShowMessage("Edit1中输入的是OK");
14     }else{
15        ShowMessage("未知错误");
16     }
17}

并在Button1Click所在的文件中添加头文件:#include “MyRDM_TLB.cpp” 和#include “MyDataModule.cpp”
6.运行之。并尝试在Edit1中输入不同的值 ,以观察结果。
如图所示:Client和Server通信

至此,一个简单的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(…)
切切,话说当年本人为此也付出不菲的时间代价。