读DataSnap源代码(一)
Delphi的DataSnap用了一段时间了,但一直感觉有些地方还不够了解,所以花时间阅读了源代码,特作此烂笔头。
Datasnap是在之前的WebBorker基础上搭建的,DataSnap向导自动生成了基础的代码,所以就以基础代码为起点来看看DataSnap的内部机制。
首选创建一个 Stand-alone 的REST App, 向导至少会为我们生成一个Form1和一个WebModule1,
FormUnit1单元如下:
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实例方法呢?
TIdHTTPWebBrokerBridge = class(TIdCustomHTTPServer)
private
procedure RunWebModuleClass(AThread: TIdContext; ARequestInfo: TIdHTTPRequestInfo;
AResponseInfo: TIdHTTPResponseInfo);
protected
FWebModuleClass: TComponentClass;
//
8 procedure DoCommandGet(AThread: TIdContext; ARequestInfo: TIdHTTPRequestInfo;
9 AResponseInfo: TIdHTTPResponseInfo); override;
10 procedure DoCommandOther(AThread: TIdContext; ARequestInfo: TIdHTTPRequestInfo;
11 AResponseInfo: TIdHTTPResponseInfo); override;
procedure InitComponent; override;
public
procedure RegisterWebModuleClass(AClass: TComponentClass);
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的定义:
TIdHTTPWebBrokerBridgeRequestHandler = class(TWebRequestHandler)
{$IFDEF HAS_CLASSVARS}
private
4 class var FWebRequestHandler: TIdHTTPWebBrokerBridgeRequestHandler;
{$ENDIF}
public
constructor Create(AOwner: TComponent); override;
{$IFDEF HAS_CLASSVARS}
{$IFDEF HAS_CLASSDESTRUCTOR}
class destructor Destroy;
{$ENDIF}
{$ENDIF}
destructor Destroy; override;
14 procedure Run(AThread: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
end;
第4行,静态的,唯一的。
第14行 就是TIdHTTPWebBrokerBridge.DoCommandGet中被调用的。
Run内部代码:
procedure TIdHTTPWebBrokerBridgeRequestHandler.Run(AThread: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
var
LRequest: TIdHTTPAppRequest;
LResponse: TIdHTTPAppResponse;
begin
try
LRequest := TIdHTTPAppRequest.Create(AThread, ARequestInfo, AResponseInfo);
try
LResponse := TIdHTTPAppResponse.Create(LRequest, AThread, ARequestInfo, AResponseInfo);
try
// WebBroker will free it and we cannot change this behaviour
AResponseInfo.FreeContentStream := False;
HandleRequest(LRequest, LResponse);
finally
FreeAndNil(LResponse);
end;
finally
FreeAndNil(LRequest);
end;
except
// Let Indy handle this exception
raise;
end;
end;
读DataSnap源代码(一)的更多相关文章
- 读DataSnap源代码(五)
function TDSHTTPWebDispatcher.DispatchRequest(Sender: TObject; Request: TWebRequest; Response: TWebR ...
- 读DataSnap源代码(六)
具体分析一下DataSanp App与Rest, WebBroker App的不同,先看TDSHTTPService. **************************************** ...
- 读DataSnap源代码(四)
继续篇中的 function TCustomWebDispatcher.DispatchAction(Request: TWebRequest; Response: TWebResponse): Bo ...
- 读DataSnap源代码(三)
function TWebRequestHandler.HandleRequest(Request: TWebRequest; Response: TWebResponse): Boolean; va ...
- 读DataSnap源代码(二)
program Project1; {$APPTYPE GUI} {$R *.dres} uses Vcl.Forms, Web.WebReq, IdHTTPWebBrokerBridge, Form ...
- 读Flask源代码学习Python--config原理
读Flask源代码学习Python--config原理 个人学习笔记,水平有限.如果理解错误的地方,请大家指出来,谢谢!第一次写文章,发现好累--!. 起因 莫名其妙在第一份工作中使用了从来没有接 ...
- session自己定义存储,怎样更好地进行session共享;读tomcat7源代码,org.apache.catalina.session.FileStore可知
session自己定义存储.怎样更好地进行session共享: 读tomcat源代码,org.apache.catalina.session.FileStore可知 一.详见: 方法1 public ...
- dotnet 读 WPF 源代码笔记 布局时 Arrange 如何影响元素渲染坐标
大家是否好奇,在 WPF 里面,对 UIElement 重写 OnRender 方法进行渲染的内容,是如何受到上层容器控件的布局而进行坐标偏移.如有两个放入到 StackPanel 的自定义 UIEl ...
- dotnet 读 WPF 源代码笔记 渲染收集是如何触发
在 WPF 里面,渲染可以从架构上划分为两层.上层是 WPF 框架的 OnRender 之类的函数,作用是收集应用程序渲染的命令.上层将收集到的应用程序绘制渲染的命令传给下层,下层是 WPF 的 GF ...
随机推荐
- Python中列表、元组、集合、字典
Python 列表(List) 列表是最常用的Python数据类型: 列表中的数据项不需要具有相同的类型: 列表也叫做数组,定义时使用[]: 通过下标访问列表中的元素,下标从 0 开始计数 列表的增 ...
- python--selenium简单模拟百度搜索点击器
python--selenium简单模拟百度搜索点击器 发布时间:2018-02-28 来源:网络 上传者:用户 关键字: selenium 模拟 简单 点击 搜索 百度 发表文章摘要:用途:简单模拟 ...
- Linux运维命令总结(-)
Linux运维命令总结(-) 此次整理linux运维常用命令13个,常用linux运维命令大概有150个,约占百分之十,大牛见笑,本人菜鸟一枚不才整理如下,如有不正确之处,请多多指正. 1.创建目录 ...
- scrollIntoView()方法
该方法用于建立一个锚点,点击锚点,会跳到相应的内容,且该内容头部与浏览器头部平齐 实例: <html> <head> <title>TODO supply a ti ...
- 使用Chrome调试工具抢阿里云免费套餐
活动地址如下: https://free.aliyun.com/ntms/free/experience/getTrial.html 首先打开地址,需要登录,登陆后看到如下页面: 选择个人免费套餐,这 ...
- wx小程序入门&坑
1.腾讯云的nodejs版服务代码,在本地用吹cnpm install安装依赖之后,初始化数据库不成功: 换成npm install 并 npm run initdb 之后 可以了.... 2.屏蔽页 ...
- SpringBatch Sample (二)(CSV文件操作)
本文将通过一个完整的实例,与大家一起讨论运用Spring Batch对CSV文件的读写操作.此实例的流程是:读取一个含有四个字段的CSV文件(ID,Name,Age,Score),对读取的字段做简单的 ...
- Python学习笔记第四周
目录 一.基础概念 1.装饰器 1.装饰器本质就是函数 2.实现装饰器知识储备 1.函数即变量 2.高阶函数 3.嵌套函数 例子 1.将一个函数名作为实参传递给另外一个函数 2.返回值为函数名 3.函 ...
- Android ADT 工具下载地址
/********************************************************************************* * Android ADT 工具下 ...
- Java简单双向链表实现 @version 1.0
package com.list; /** * 数据结构和算法Java表示 双向链表 * * @version 1.0 * @author 小明 * */ public class MyDoublel ...