• 读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实例方法呢?

     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;


     

  • 相关阅读:
    django class类即视图类添加装饰器的几种方法
    django 如何在HMTL中使用媒体media_url
    django 对models中上传的文件或图片改名
    常用工具链接网址
    verifycode验证码模版
    shell 一些常用命令
    用 openresty 编写 lua
    centos7 安装python虚拟环境
    django url配置-反向解析-视图函数-HttpRequest对象-HttpResponse对象-cookies-session-redis缓存session
    PWN题搭建
  • 原文地址:https://www.cnblogs.com/Jiaojiawang/p/4818454.html
Copyright © 2020-2023  润新知