程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> 讀DataSnap源代碼(一),讀datasnap源代碼

讀DataSnap源代碼(一),讀datasnap源代碼

編輯:Delphi

讀DataSnap源代碼(一),讀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;


 

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved