Delphi DataSnap 架构与协议解析

Delphi DataSnap 核心架构与开发指南

Delphi DataSnap 是 Embarcadero 提供的多层应用开发框架,起源于 MIDAS 技术,历经 DBX 演变至现代版本,支持构建高性能的三层或多层分布式应用 。其核心优势在于简化了服务端与客户端的通信,支持多种协议(TCP/IP, HTTP/HTTPS),并能够轻松实现 RESTful 服务 。

  1. 技术演进与协议对比

DataSnap 从早期的 scktsrv.exe 中间件发展为完全集成在 Delphi IDE 中的框架,不再依赖外部进程,且深度整合了 FireDAC 和 REST 技术 。

特性维度 传统 DataSnap (DBX) 现代 DataSnap (REST/HTTP) 说明
通信协议 专有 TCP/IP协议 (DBX) HTTP/HTTPS (RESTful) 现代版本更易于穿越防火墙和集成 Web 前端
数据格式 二进制 (dbxjson 等) JSON, XML, PlainText REST 模式默认使用 JSON 进行数据交换
服务端组件 TDSServer, TDSTCPTransport TDSServer, TDSHTTPWebDispatcher HTTP 模式需加载 TDSHTTPWebDispatcher 处理 Web 请求
客户端连接 TDSClientConnection TDSRestConnection / TRESTClient REST 客户端可利用标准 REST 组件或专用 DataSnap 代理
部署依赖 需特定 DBX 驱动 标准 Web 服务器环境 摆脱了对特定中间件进程的依赖
  1. 服务端构建流程 (Server Side)

创建 DataSnap 服务端通常采用 "DataSnap REST Application" 向导。其核心逻辑是通过 TCustomWebDispatcher (具体为 TDSHTTPWebDispatcher) 拦截 HTTP 请求,解析命令并调用远程方法 。

关键组件配置:

  • TDSServer: 管理整个 DataSnap 会话和服务实例。
  • TDSServerClass: 将具体的数据模块类暴露为远程服务。
  • TDSHTTPWebDispatcher: 负责将 HTTP 请求分发给 DataSnap 引擎 。
  • TDatasetProvider : 位于数据模块中,负责打包数据集 (TFDQuery) 供客户端获取 。

服务端数据模块代码示例 (Delphi):

pascal 复制代码
unit ServerModule;

interface

uses
  System.SysUtils, System.Classes, DataSnap.DSProviderConnection, 
  Data.DBXCommon, Data.DBXClient, Data.DBXDataSnap, Data.DBXJSON,  Data.DBXJSONReflect, Data.DBXTDR, Data.DBXLog, Data.DBXError, 
  Data.DBXReaders, Data.DBXWritable, Data.DBXFlatFile, Data.DBXClientConnection, 
 Data.DBXSocketConn, Data.DBXProxy, Data.DBXMsgResp, Data.DBXMetaData, 
  Data.DBXCommonTypes, Data.DBXFilters, Data.DBXDataReader, 
  Data.DBXDynArray, Data.DBXJSONTools, Data.DBXJSONContent,  Data.DBXJsonObject, Data.DBXJSONBridge, Data.DBXIPC,  FireDAC.Stan.Intf, FireDAC.Stan.Option, FireDAC.Stan.Error, 
  FireDAC.UI.Intf, FireDAC.Phys.Intf, FireDAC.Stan.Def,  FireDAC.Stan.Pool, FireDAC.Stan.Async, FireDAC.Phys, 
  FireDAC.Phys.FB, FireDAC.Phys.FBDef, FireDAC.VCLUI.Wait,  FireDAC.Comp.Client, FireDAC.Comp.DataSet, Data.DB, 
  Data.SqlExpr, Data.Provider, Datasnap.DSServer, Datasnap.DSHTTPCommon, 
  Datasnap.DSHTTPWebBroker, Datasnap.DSHTTP;

type
  TServerMethods1 = class(TDataModule)
    FDConnection1: TFDConnection;
    FDQuery1: TFDQuery;
    DataSetProvider1: TDataSetProvider;
    procedure DataModuleCreate(Sender: TObject);
  private
    { Private declarations } public
    { Public declarations }
    function GetData: TDataSet; end;

implementation

{$R *.dfm}

procedure TServerMethods1.DataModuleCreate(Sender: TObject);
begin
  // 初始化数据库连接,实际项目中建议从配置文件读取
  FDConnection1.DriverName := 'FB'; 
  FDConnection1.Params.Add('Database=MyDatabase.fdb');
  FDConnection1.Params.Add('User_Name=sysdba');
  FDConnection1.Params.Add('Password=masterkey');
end;

// 核心业务方法:返回数据集供客户端调用
function TServerMethods1.GetData: TDataSet;
begin
  FDQuery1.Close;
  FDQuery1.SQL.Text := 'SELECT * FROM CUSTOMERS';
  FDQuery1.Open;
  Result := FDQuery1; // DataSnap 自动处理数据集的序列化和传输 
end;

end.
  1. 客户端连接与数据获取 (Client Side)

客户端可通过两种方式获取数据:传统的 TDSClientConnection (适用于同构 Delphi 环境) 或现代的 TDSRestConnection / TRESTClient (适用于跨平台或 Web 集成) 。

方式 A:使用 TDSRestConnection (推荐用于 REST 模式)

此方式利用 TSQLConnection 和 TDataSetProviderConnection 建立连接,支持只读和可更新数据集,并能处理更新冲突 。

pascal 复制代码
unit ClientForm;

interface

uses
  System.SysUtils, System.Classes, Vcl.Forms, Vcl.Controls, Vcl.StdCtrls, 
  Vcl.Grids, Vcl.DBGrids, Data.DB, Data.SqlExpr, Data.DBXClient,  Data.DBXDataSnap, Data.DBXCommon, Data.DBXJSON, Data.DBXJSONTools, 
  Datasnap.DSClientRes, Datasnap.DSProxy, Datasnap.DSHTTPClient, 
  FireDAC.Stan.Intf, FireDAC.Stan.Option, FireDAC.Stan.Error, 
  FireDAC.UI.Intf, FireDAC.Phys.Intf, FireDAC.Stan.Def, 
  FireDAC.Stan.Pool, FireDAC.Stan.Async, FireDAC.Phys, 
  FireDAC.Comp.Client, FireDAC.Comp.DataSet, FireDAC.DatS, 
  FireDAC.DApt, FireDAC.DatS.Json;

type
  TForm1 = class(TForm)
    DSRestConnection1: TDSRestConnection;
    SQLConnection1: TSQLConnection;
    DSPClientConnection1: TDSPClientConnection;    ClientDataSet1: TClientDataSet;
    DataSource1: TDataSource;
    DBGrid1: TDBGrid;
    ButtonFetch: TButton;
    procedure ButtonFetchClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  // 配置 REST 连接参数
  DSRestConnection1.Host := 'localhost';
  DSRestConnection1.Port := 8080; // DataSnap 默认 HTTP 端口
  DSRestConnection1.LoginPrompt := False;
  // 若需认证,设置 UserName 和 Passwordend;

procedure TForm1.ButtonFetchClick(Sender: TObject);
begin
  try
    if not DSRestConnection1.Connected then
      DSRestConnection1.Connect;

    // 调用服务端远程方法 GetData
    // 参数顺序需与服务端方法定义一致
    ClientDataSet1.CommandText := 'GetData'; 
    ClientDataSet1.Execute; 
    
    // 此时 DBGrid1 将显示从服务端获取的数据  except
    on E: Exception do
      ShowMessage('数据获取失败:' + E.Message);
 end;
end;

end.

方式 B:使用 REST Client 直接解析 JSON

对于非 Delphi 客户端或需要更细粒度控制的场景,可直接使用 TRESTClient 配合 TRESTResponseDataSetAdapter 将 JSON 响应转换为数据集 。

pascal 复制代码
// 伪代码逻辑示意:使用 TRESTResponseDataSetAdapter 处理 JSON 流
// var Adapter: TRESTResponseDataSetAdapter;
// Adapter := TRESTResponseDataSetAdapter.Create(nil);
// try
//   Adapter.Dataset := MyLocalFDQuery;
//   Adapter.FieldDefs := MyLocalFDQuery.FieldDefs;
//   Adapter.RestResponse := RestResponse1; // 来自 TRESTClient 的响应
//   Adapter.FillDataset; // 将 JSON 数据填充到本地数据集 
// finally
//   Adapter.Free;
// end;
  1. 关键机制与部署策略
  • 数据更新与冲突处理 :DataSnap 支持客户端离线修改数据并通过 ApplyUpdates 提交。服务端通过 TDatasetProvider 的 OnUpdateError 事件处理并发冲突,支持强制覆盖、取消更新或合并策略 。
  • 过滤器应用 :可在客户端对 TClientDataSet 应用过滤器,减少网络传输量;也可在服务端通过参数化查询实现服务端过滤 。
  • 远程数据模块重用 :设计良好的 DataSnap 服务应将业务逻辑封装在独立的 DataModule 中,通过 TDSServerClass 暴露,确保逻辑层的复用性和维护性 。
  • 部署注意事项 :
    • HTTP 模式 :只需部署生成的 EXE 文件,无需额外安装 scktsrv.exe 或复杂的 DBX 驱动,极大简化了运维 。
    • 线程安全:DataSnap 服务端默认在每个请求中创建数据模块实例(LifeCycle 设置为 Session 或 Invocation),需注意全局变量的线程安全问题 。
    • 防火墙:使用 HTTP/HTTPS 协议(默认端口 8080 或 443)比传统 TCP 端口更容易通过企业防火墙 。

参考来源

相关推荐
passion1 个月前
CnPack IDE专家包发布1.8.1正式版!
ide·delphi·cnpack
pcplayer3 个月前
调试 Delphi 的 Service 工程
delphi·windows系统服务程序
ljklxlj4 个月前
DBLookupComboboxEh修改支持退格弹下拉框
delphi
_lorzl_5 个月前
Delphi 10.4.2 IDE Attach to process... 到宿主进程时死锁的原因与修复
ide·delphi
昆曲之源_娄江河畔6 个月前
DBGridEh Footer的使用
前端·数据库·delphi·dbgrideh
pcplayer6 个月前
非常好用的 Excel 读写控件
excel·delphi·office
月巴月巴白勺合鸟月半7 个月前
从 Delphi 到 FMX:Borland/Embarcadero 跨平台开发三十年兴衰史
跨平台·delphi
START_GAME7 个月前
Delphi 10.3安装与辅助工具uniGUI 配置指南
delphi·delphi10.3
专注VB编程开发20年7 个月前
delphi死嗑Pascal冷门编程语言,Borland不认可 “通用多语言 IDE”,认为 “专有语言才是护城河”
开发语言·ide·delphi