DataSnap提供了实现C/S应用的技术。
一、实现一个基本的DataSnap服务端。
1. 实现DataSnap服务端的几个基本控件:TDSServer控件、TDSServerClass控件和TDSTCPServerTransport控件。
TDSServer控件:DataSnap服务端程序的逻辑核心,用来启动和停止服务。AutoStart属性默认设置为true,程序一运行就自动启动服务。
TDSServerClass控件:代表一个服务器类,服务端的方法由它来引出供客户端远程调用。DataSnap Server自动创建和销毁一个服务器类的实例。这个实例的生命周期受TDSServerClass的LifeCycle属性控制。LifeCycle有三种选择:Server, Session 和 Invocation.
- Server模式: 为所有的客户端只创建一个实例,这种模式下要注意线程安全,因为只有一个实例来同时处理多个客户端请求。
- Sessionm模式:这是LifeCycle的默认设置,为每一个连接到服务端的客户端创建一个服务器实例。
- Invocation模式:客户端的每一次连接(服务器方法调用)都回创建一个服务器实例。
(为了让客户端和服务端进行通讯,引入了TDSTCPServerTransport控件. 当然也可以通过HTTP协议来通讯。)
TDSTCPServerTransport控件:实现一个多线程的TCP服务器,多线程监听客户端连接。
2. 服务端实现步骤:
(1). File > New > VCL Forms Application - Delphi, 加入三个控件,TDSServer控件、TDSServerClass控件和TDSTCPServerTransport控件。将TDSServerClass和TDSTCPServerTransport的Server属性都设置成TDSServer控件的名字,比如DSServer1。
(2). File > New > Unit - Delphi生成一个新的Delphi文件,存为MyClass,代码如下:
unit MyClass;
interface
uses Classes;
Type
{$METHODINFO ON}
TMyClass = class(TComponent)
function Sum(const A,B: Double):Double;
end;
{$METHODINFO OFF}
implementation
function TMyClass.Sum(const A: Double; const B: Double): Double;
begin
result := A + B;
end;
end.
代码中的{$METHODINFO ON}会为DataSnap Server产生运行时信息,这是必须的,而不仅仅是一个注释。
(3). 将MyClass单元引入服务器主程序单元,并在TDSServerClass控件的GetClass事件中引入MyClass。
procedure TForm2.DSServerClass1GetClass(DSServerClass: TDSServerClass;
var PersistentClass: TPersistentClass);
begin
PersistentClass := TMyClass;
end;
DataSnap架构最重要的一个概念就是将一个类的引用赋给PersistentClass,而不是一个Object。
一个简单的但是完整的服务器程序建立完毕。
二、实现一个基本的DataSnap客户端。
在实现一个客户端前,先编译并运行上面完成的服务端。
1. File > New > VCL Forms Application - Delphi, 加入几个编辑和显示控件,如下图:
2. 设置SQLConnection1的Driver为DataSnap,因为现在服务端和客户端都在同一台机器上,所以DataSnap下面的参数可以选用默认的参数。
3. 勾选SQLConnection1的Connected为True, SQLConnection1会自动连接到已经在运行的服务端上,右键点击SQLConnection1控件,选择Generate DataSnap Client Classes. 程序会自动产生一个从服务端导出的Delphi单元文件,文件描述了要远程调用的服务端类及函数。这里保存为MyDSClient.Pas,里面导入了服务端的类MyClass.
4. 客户端主程序引入这个单元文件,并在Calculate按钮的onclick事件中远程调用服务端的函数Sum.
procedure TClientForm.btnExecuteClick(Sender: TObject);
var
Temp: TMyClassClient;
A,B: Double;
begin
Temp := TMyClassClient.Create(SQLConnection1.DBXConnection);
try
A := StrToFloat(edA.Text);
B := StrToFloat(edB.Text);
edResult.Text := floatToStr(Temp.Sum(A,B));
finally
Temp.Free;
end;
end;
运行客户端并测试。