Delphi的DataSnap用了一段时间了,但一直感觉有些地方还不够了解,所以花时间阅读了源代码,特作此烂笔头。

Datasnap是在之前的WebBorker基础上搭建的,DataSnap向导自动生成了基础的代码,所以就以基础代码为起点来看看DataSnap的内部机制。

首选创建一个 Stand-alone 的REST App,  向导至少会为我们生成一个Form1和一个WebModule1,

FormUnit1单元如下:

  1. unit FormUnit1;
  2.  
  3. interface
  4.  
  5. uses
  6. Winapi.Messages, System.SysUtils, System.Variants,
  7. System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
  8. Vcl.AppEvnts, Vcl.StdCtrls, IdHTTPWebBrokerBridge, Web.HTTPApp;
  9.  
  10. type
  11. TForm1 = class(TForm)
  12. ButtonStart: TButton;
  13. ButtonStop: TButton;
  14. EditPort: TEdit;
  15. Label1: TLabel;
  16. ApplicationEvents1: TApplicationEvents;
  17. ButtonOpenBrowser: TButton;
  18. procedure FormCreate(Sender: TObject);
  19. procedure ApplicationEvents1Idle(Sender: TObject; var Done: Boolean);
  20. procedure ButtonStartClick(Sender: TObject);
  21. procedure ButtonStopClick(Sender: TObject);
  22. procedure ButtonOpenBrowserClick(Sender: TObject);
  23. private
  24. FServer: TIdHTTPWebBrokerBridge;
  25. procedure StartServer;
  26. { Private declarations }
  27. public
  28. { Public declarations }
  29. end;
  30.  
  31. var
  32. Form1: TForm1;
  33.  
  34. implementation
  35.  
  36. {$R *.dfm}
  37.  
  38. uses
  39. WinApi.Windows, Winapi.ShellApi, Datasnap.DSSession;
  40.  
  41. procedure TForm1.ApplicationEvents1Idle(Sender: TObject; var Done: Boolean);
  42. begin
  43. ButtonStart.Enabled := not FServer.Active;
  44. ButtonStop.Enabled := FServer.Active;
  45. EditPort.Enabled := not FServer.Active;
  46. end;
  47.  
  48. procedure TForm1.ButtonOpenBrowserClick(Sender: TObject);
  49. var
  50. LURL: string;
  51. begin
  52. StartServer;
  53. LURL := Format('http://localhost:%s', [EditPort.Text]);
  54. ShellExecute(0,
  55. nil,
  56. PChar(LURL), nil, nil, SW_SHOWNOACTIVATE);
  57. end;
  58.  
  59. procedure TForm1.ButtonStartClick(Sender: TObject);
  60. begin
  61. StartServer;
  62. end;
  63.  
  64. procedure TerminateThreads;
  65. begin
  66. if TDSSessionManager.Instance <> nil then
  67. TDSSessionManager.Instance.TerminateAllSessions;
  68. end;
  69.  
  70. procedure TForm1.ButtonStopClick(Sender: TObject);
  71. begin
  72. TerminateThreads;
  73. FServer.Active := False;
  74. FServer.Bindings.Clear;
  75. end;
  76.  
  77. procedure TForm1.FormCreate(Sender: TObject);
  78. begin
  79. FServer := TIdHTTPWebBrokerBridge.Create(Self);
  80. end;
  81.  
  82. procedure TForm1.StartServer;
  83. begin
  84. if not FServer.Active then
  85. begin
  86. FServer.Bindings.Clear;
  87. FServer.DefaultPort := StrToInt(EditPort.Text);
  88. FServer.Active := True;
  89. end;
  90. end;
  91.  
  92. 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. 8 procedure DoCommandGet(AThread: TIdContext; ARequestInfo: TIdHTTPRequestInfo;
  9. 9 AResponseInfo: TIdHTTPResponseInfo); override;
  10. 10 procedure DoCommandOther(AThread: TIdContext; ARequestInfo: TIdHTTPRequestInfo;
  11. 11 AResponseInfo: TIdHTTPResponseInfo); override;
  12. procedure InitComponent; override;
  13. public
  14. procedure RegisterWebModuleClass(AClass: TComponentClass);
  15. end;

DoCommandGet的内部代码:

  1. procedure TIdHTTPWebBrokerBridge.DoCommandGet(AThread: TIdContext;
  2. ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
  3. begin
  4. if FWebModuleClass <> nil then begin
  5. // FWebModuleClass, RegisterWebModuleClass supported for backward compatability
  6. RunWebModuleClass(AThread, ARequestInfo, AResponseInfo)
  7. end else
  8. begin
  9. {$IFDEF HAS_CLASSVARS}
  10. TIdHTTPWebBrokerBridgeRequestHandler.FWebRequestHandler.Run(AThread, ARequestInfo, AResponseInfo);
  11. {$ELSE}
  12. IndyWebRequestHandler.Run(AThread, ARequestInfo, AResponseInfo);
  13. {$ENDIF}
  14. end;
  15. end;

TIdHTTPWebBrokerBridgeRequestHandler的定义:

  1. TIdHTTPWebBrokerBridgeRequestHandler = class(TWebRequestHandler)
  2. {$IFDEF HAS_CLASSVARS}
  3. private
  4. 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. 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;

读DataSnap源代码(一)的更多相关文章

  1. 读DataSnap源代码(五)

    function TDSHTTPWebDispatcher.DispatchRequest(Sender: TObject; Request: TWebRequest; Response: TWebR ...

  2. 读DataSnap源代码(六)

    具体分析一下DataSanp App与Rest, WebBroker App的不同,先看TDSHTTPService. **************************************** ...

  3. 读DataSnap源代码(四)

    继续篇中的 function TCustomWebDispatcher.DispatchAction(Request: TWebRequest; Response: TWebResponse): Bo ...

  4. 读DataSnap源代码(三)

    function TWebRequestHandler.HandleRequest(Request: TWebRequest; Response: TWebResponse): Boolean; va ...

  5. 读DataSnap源代码(二)

    program Project1; {$APPTYPE GUI} {$R *.dres} uses Vcl.Forms, Web.WebReq, IdHTTPWebBrokerBridge, Form ...

  6. 读Flask源代码学习Python--config原理

    读Flask源代码学习Python--config原理 个人学习笔记,水平有限.如果理解错误的地方,请大家指出来,谢谢!第一次写文章,发现好累--!. 起因   莫名其妙在第一份工作中使用了从来没有接 ...

  7. session自己定义存储,怎样更好地进行session共享;读tomcat7源代码,org.apache.catalina.session.FileStore可知

    session自己定义存储.怎样更好地进行session共享: 读tomcat源代码,org.apache.catalina.session.FileStore可知 一.详见: 方法1 public ...

  8. dotnet 读 WPF 源代码笔记 布局时 Arrange 如何影响元素渲染坐标

    大家是否好奇,在 WPF 里面,对 UIElement 重写 OnRender 方法进行渲染的内容,是如何受到上层容器控件的布局而进行坐标偏移.如有两个放入到 StackPanel 的自定义 UIEl ...

  9. dotnet 读 WPF 源代码笔记 渲染收集是如何触发

    在 WPF 里面,渲染可以从架构上划分为两层.上层是 WPF 框架的 OnRender 之类的函数,作用是收集应用程序渲染的命令.上层将收集到的应用程序绘制渲染的命令传给下层,下层是 WPF 的 GF ...

随机推荐

  1. Python 默认值字典

    from collections import defaultdict # 默认值字典 dd = defaultdict(lambda: "胡辣汤") # callable 可调用 ...

  2. 重启uwsgi脚本备份

    NAME="identifyImg_uwsgi.init" if [ ! -n "$NAME" ];then echo "no arguments&q ...

  3. Spring Boot 揭秘与实战(二) 数据缓存篇 - EhCache

    文章目录 1. EhCache 集成 2. 源代码 本文,讲解 Spring Boot 如何集成 EhCache,实现缓存. 在阅读「Spring Boot 揭秘与实战(二) 数据缓存篇 - 快速入门 ...

  4. busybox devmem 直接获取、修改内存信息

    /********************************************************************** * busybox devmem 直接获取.修改内存信息 ...

  5. Linux命令学习之路——档案拷贝:cp

    使用权限:所有角色 使用方式:cp [ -arf ] source dest / cp [ -arf ] source... Directory 作用:把一个档案拷贝到另一个档案(档案复制),或将多个 ...

  6. 利用sql语句进行增删改查

    1.查询 函数:raw(sql语句) 语法:Entry.objects.raw(sql) 返回:QuerySet 2.增删改 from django.db import connection def ...

  7. 对Functional Language的认识

    What: A functional language is a programming language built over and around logical functions or pro ...

  8. 利用Git hub创建博客

    1.准备工作 到Git官网 下载Git,并且配置环境变量 2.注册Git Hub账号 到Git Hub官网注册相关账号,比如本文的账号为13627225740L,并至New repository创建仓 ...

  9. 专题--XOR之线性基

    没想到xor居然和线性代数有着那么有趣的联系哎 n个数可以转化为一个上三角矩阵  (线性无关?!) 链接:https://www.nowcoder.com/acm/contest/180/D来源:牛客 ...

  10. PAT-L2-007 家庭房产 (union-find) 小数据 没有什么是暴力解决不了的!!

    题目分析: 典型的union-find 算法 想法: 先不着急 union 因为每一个人的房产信息不知道 所以先输入所有信息 同时保留与自己有关系的每一个人 待初始化每一个人的房产信息后,再union ...