function TDSHTTPWebDispatcher.DispatchRequest(Sender: TObject;
Request: TWebRequest; Response: TWebResponse): Boolean;
begin
try
if Owner is TWebModule then
DataSnapWebModule := TWebModule(Owner);
try
try
RequiresServer;
TDSHTTPServerWebBroker(Self.FHttpServer).DispatchDataSnap(Request, Response);
Result := True;
except
on E: Exception do
begin
{ Default to 500, like web services. }
Response.StatusCode := ;
Result := True;
end;
end;
except
{ Swallow any unexpected exception, it will bring down some web servers }
Result := False;
end;
finally
{ Reset current DataSnapWebModule }
DataSnapWebModule := nil;
end;
end;

第10行代码中,请求被分配到TDSHTTPServerWebBorker中处理了。

 procedure TDSHTTPServerWebBroker.DispatchDataSnap(ARequest: TWebRequest;
AResponse: TWebResponse);
var
LDispatch: TDSHTTPDispatch;
LContext: TDSHTTPContextWebBroker;
begin
LDispatch := TDSHTTPApplication.Instance.HTTPDispatch;
if LDispatch <> nil then
DoCommand(LDispatch.Context, LDispatch.Request, LDispatch.Response)
else
begin
LContext := TDSHTTPContextWebBroker.Create(ARequest, AResponse);
try
DoCommand(LContext, LContext.FRequest, LContext.FResponse);
finally
LContext.Free;
end;
end;
end;

上面的第14行代码最终会转到TDSRESTServer类处理。

procedure TDSRESTServer.DoCommand(AContext: TDSHTTPContext; ARequestInfo: TDSHTTPRequest;
                                  AResponseInfo: TDSHTTPResponse);

 procedure TDSRESTServer.DoCommand(AContext: TDSHTTPContext; ARequestInfo: TDSHTTPRequest;
AResponseInfo: TDSHTTPResponse);
var
Request: string;
NextRequest: string;
NextContext: string;
RestCtxt: string;
StartDispatch: Boolean;
begin // HTTPDispatch object if necessary
StartDispatch := not TDSHTTPApplication.Instance.Dispatching;
if StartDispatch then
TDSHTTPApplication.Instance.StartDispatch(AContext, ARequestInfo, AResponseInfo);
try
{$IFNDEF POSIX}
if CoInitFlags = - then
CoInitializeEx(nil, COINIT_MULTITHREADED)
else
CoInitializeEx(nil, CoInitFlags);
{$ENDIF}
try
// check for context, if not found send the appropriate error message
Request := ARequestInfo.URI;
if Consume(FDSContext, Request, NextRequest) then
begin
Request := NextRequest;
if Consume(FRESTContext, Request, NextRequest) then
begin
// datasnap/rest
DoDSRESTCommand(ARequestInfo, AResponseInfo, NextRequest);
end
else if ConsumeOtherContext(Request, NextContext, NextRequest) then
begin
DoDSOtherCommand(AContext, ARequestInfo, AResponseInfo, NextContext, NextRequest, FDSServerName <> EmptyStr);
end
else
begin
RestCtxt := Trim(FRESTContext);
if RestCtxt = EmptyStr then
RestCtxt := SProtocolRestEmpty; AResponseInfo.ResponseNo := ; {rest or other service not found in URI}
AResponseInfo.ContentText := Format(SProtocolNotSupported, [Request, RestCtxt]);
AResponseInfo.CloseConnection := true;
end;
end
else
begin
// This may dispatch .js files for example
DoCommandOtherContext(AContext, ARequestInfo, AResponseInfo, Request);
end;
if Assigned(Self.FTrace ) then
begin
FTrace(Self, AContext, ARequestInfo, AResponseInfo);
end;
finally ClearInvocationMetadata();
{$IFNDEF POSIX}
CoUnInitialize;
{$ENDIF}
end;
finally
if StartDispatch then
TDSHTTPApplication.Instance.EndDispatch;
end;
end;

上面阴影的代码,一步一步的推进,先判断URI中是否包括Datasnap,再往判断是否包括REST,然后再继续处理。

到目前,代码已经从TWebModule到TDSHTTPWebDispatcher再到TDSRESTServer类中了。

而Delphi中,我们可以创建三种类型的DataSanp Server程序:

一是DataSanp REST App

二是DataSnap App

三是DataSnap WebBroker App

目前来看, Rest App和WebBroder App是很相似的。而 DataSanp App有些不同:

一是没有WebModule。

二是用 TDSHTTPService 代替了 TDSHTTPWebDispatcher。

三是Form1中代码简化了很多了,虽然project中也出现了  IdHTTPWebBrokerBridge,但也是不同的。(可以和rest app的比较)

 program Project1;

 uses
Vcl.Forms,
Web.WebReq,
IdHTTPWebBrokerBridge,
Unit1 in 'Unit1.pas' {Form1},
ServerMethodsUnit1 in 'ServerMethodsUnit1.pas',
ServerContainerUnit1 in 'ServerContainerUnit1.pas' {ServerContainer1: TDataModule}; {$R *.res} begin
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TForm1, Form1);
Application.CreateForm(TServerContainer1, ServerContainer1);
Application.Run;
end.

机制有何不同?

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

  1. 读DataSnap源代码(一)

    Delphi的DataSnap用了一段时间了,但一直感觉有些地方还不够了解,所以花时间阅读了源代码,特作此烂笔头. Datasnap是在之前的WebBorker基础上搭建的,DataSnap向导自动生 ...

  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. javascript动态加载js文件主流浏览器兼容版

    一.代码示例: <html> <head> <meta http-equiv="Content-Type" content="text/ht ...

  2. java.lang.OutOfMemoryError: GC overhead limit exceeded

    前端请求:{"code":400,"message":"Handler dispatch failed; nested exception is ja ...

  3. foreman ubuntu16快速安装

    Quickstart Guide The Foreman installer is a collection of Puppet modules that installs everything re ...

  4. HDU 6077 17多校4 Time To Get Up 水题

    Problem Description Little Q's clock is alarming! It's time to get up now! However, after reading th ...

  5. 12.2 关闭DLM 自动收集统计信息 (SCM0)ORA-00600之[ksliwat: bad wait time]

    一.报错日志 db_alert ORA-: ??????, ??: [ksliwat: bad wait time], [], [], [], [], [], [], [], [], [], [], ...

  6. Python之路,第十篇:Python入门与基础10

    python3 函数 函数(function) 什么是函数: 函数是可以重复执行的代码块,可以重复使用: 作用: 定义用户级的函数:实现了一个代码块的封装: 语法: def   函数名(参数列表): ...

  7. display: table; 100%的宽度

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  8. ACM 删数问题 SDUT 2072

    http://acm.sdut.edu.cn/onlinejudge2/index.php/Home/Index/problemdetail/pid/2072.html 删数问题 Time Limit ...

  9. PTA——天平找小球

    PTA 7-22 用天平找小球 #include<stdio.h> int main() { int a,b,c; scanf("%d%d%d",&a,& ...

  10. 03 重定向,请求转发,cookie,session

    重定向: /* 之前的写法 response.setStatus(302); response.setHeader("Location", "login_success. ...