Delphi的DataSnap用了一段时间了,但一直感觉有些地方还不够了解,所以花时间阅读了源代码,特作此烂笔头。
Datasnap是在之前的WebBorker基础上搭建的,DataSnap向导自动生成了基础的代码,所以就以基础代码为起点来看看DataSnap的内部机制。
首选创建一个 Stand-alone 的REST App, 向导至少会为我们生成一个Form1和一个WebModule1,
FormUnit1单元如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | unit FormUnit1; interface uses Winapi . Messages, System . SysUtils, System . Variants, System . Classes, Vcl . Graphics, Vcl . Controls, Vcl . Forms, Vcl . Dialogs, Vcl . AppEvnts, Vcl . StdCtrls, IdHTTPWebBrokerBridge, Web . HTTPApp; type TForm1 = class (TForm) ButtonStart: TButton; ButtonStop: TButton; EditPort: TEdit; Label1: TLabel; ApplicationEvents1: TApplicationEvents; ButtonOpenBrowser: TButton; procedure FormCreate(Sender: TObject); procedure ApplicationEvents1Idle(Sender: TObject; var Done: Boolean ); procedure ButtonStartClick(Sender: TObject); procedure ButtonStopClick(Sender: TObject); procedure ButtonOpenBrowserClick(Sender: TObject); private FServer: TIdHTTPWebBrokerBridge; procedure StartServer; { Private declarations } public { Public declarations } end ; var Form1: TForm1; implementation {$R *.dfm} uses WinApi . Windows, Winapi . ShellApi, Datasnap . DSSession; procedure TForm1 . ApplicationEvents1Idle(Sender: TObject; var Done: Boolean ); begin ButtonStart . Enabled := not FServer . Active; ButtonStop . Enabled := FServer . Active; EditPort . Enabled := not FServer . Active; end ; procedure TForm1 . ButtonOpenBrowserClick(Sender: TObject); var LURL: string ; begin StartServer; LURL := Format( 'http://localhost:%s' , [EditPort . Text]); ShellExecute( 0 , nil , PChar (LURL), nil , nil , SW_SHOWNOACTIVATE); end ; procedure TForm1 . ButtonStartClick(Sender: TObject); begin StartServer; end ; procedure TerminateThreads; begin if TDSSessionManager . Instance <> nil then TDSSessionManager . Instance . TerminateAllSessions; end ; procedure TForm1 . ButtonStopClick(Sender: TObject); begin TerminateThreads; FServer . Active := False ; FServer . Bindings . Clear; end ; procedure TForm1 . FormCreate(Sender: TObject); begin FServer := TIdHTTPWebBrokerBridge . Create(Self); end ; procedure TForm1 . StartServer; begin if not FServer . Active then begin FServer . Bindings . Clear; FServer . DefaultPort := StrToInt(EditPort . Text); FServer . Active := True ; end ; end ; end . |
在Form1中,有一个FServer ,ButtonStart.Click事件中有FServer.Active := True;
TIdHTTPWebBrokerBridge 是 TIdHTTPWebBrokerBridge = class(TIdCustomHTTPServer)
到目前上为,至少知道Datasanp是基于Id组件的,那么Id(idHttpServer)和WebModule, DSServer, DSHTTPWebDispatcher1 是如何关连上的,又是如何调用到
DDServerClass实例方法呢?
1 TIdHTTPWebBrokerBridge = class(TIdCustomHTTPServer) 2 private 3 procedure RunWebModuleClass(AThread: TIdContext; ARequestInfo: TIdHTTPRequestInfo; 4 AResponseInfo: TIdHTTPResponseInfo); 5 protected 6 FWebModuleClass: TComponentClass; 7 // 8 procedure DoCommandGet(AThread: TIdContext; ARequestInfo: TIdHTTPRequestInfo; 9 AResponseInfo: TIdHTTPResponseInfo); override; 10 procedure DoCommandOther(AThread: TIdContext; ARequestInfo: TIdHTTPRequestInfo; 11 AResponseInfo: TIdHTTPResponseInfo); override; 12 procedure InitComponent; override; 13 public 14 procedure RegisterWebModuleClass(AClass: TComponentClass); 15 end;
DoCommandGet的内部代码:
procedure TIdHTTPWebBrokerBridge.DoCommandGet(AThread: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo); begin if FWebModuleClass <> nil then begin // FWebModuleClass, RegisterWebModuleClass supported for backward compatability RunWebModuleClass(AThread, ARequestInfo, AResponseInfo) end else begin {$IFDEF HAS_CLASSVARS} TIdHTTPWebBrokerBridgeRequestHandler.FWebRequestHandler.Run(AThread, ARequestInfo, AResponseInfo); {$ELSE} IndyWebRequestHandler.Run(AThread, ARequestInfo, AResponseInfo); {$ENDIF} end; end;
TIdHTTPWebBrokerBridgeRequestHandler的定义:
1 TIdHTTPWebBrokerBridgeRequestHandler = class(TWebRequestHandler) 2 {$IFDEF HAS_CLASSVARS} 3 private 4 class var FWebRequestHandler: TIdHTTPWebBrokerBridgeRequestHandler; 5 {$ENDIF} 6 public 7 constructor Create(AOwner: TComponent); override; 8 {$IFDEF HAS_CLASSVARS} 9 {$IFDEF HAS_CLASSDESTRUCTOR} 10 class destructor Destroy; 11 {$ENDIF} 12 {$ENDIF} 13 destructor Destroy; override; 14 procedure Run(AThread: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo); 15 end;
第4行,静态的,唯一的。
第14行 就是TIdHTTPWebBrokerBridge.DoCommandGet中被调用的。
Run内部代码:
1 procedure TIdHTTPWebBrokerBridgeRequestHandler.Run(AThread: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo); 2 var 3 LRequest: TIdHTTPAppRequest; 4 LResponse: TIdHTTPAppResponse; 5 begin 6 try 7 LRequest := TIdHTTPAppRequest.Create(AThread, ARequestInfo, AResponseInfo); 8 try 9 LResponse := TIdHTTPAppResponse.Create(LRequest, AThread, ARequestInfo, AResponseInfo); 10 try 11 // WebBroker will free it and we cannot change this behaviour 12 AResponseInfo.FreeContentStream := False; 13 HandleRequest(LRequest, LResponse); 14 finally 15 FreeAndNil(LResponse); 16 end; 17 finally 18 FreeAndNil(LRequest); 19 end; 20 except 21 // Let Indy handle this exception 22 raise; 23 end; 24 end;
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· C# 深度学习:对抗生成网络(GAN)训练头像生成模型
· .NET 适配 HarmonyOS 进展
· 手把手教你更优雅的享受 DeepSeek
· 腾讯元宝接入 DeepSeek R1 模型,支持深度思考 + 联网搜索,好用不卡机!
· AI工具推荐:领先的开源 AI 代码助手——Continue
· 探秘Transformer系列之(2)---总体架构
· V-Control:一个基于 .NET MAUI 的开箱即用的UI组件库