读DataSnap源代码(五)

 1 function TDSHTTPWebDispatcher.DispatchRequest(Sender: TObject;
 2   Request: TWebRequest; Response: TWebResponse): Boolean;
 3 begin
 4   try
 5     if Owner is TWebModule then
 6       DataSnapWebModule := TWebModule(Owner);
 7     try
 8       try
 9         RequiresServer;
10         TDSHTTPServerWebBroker(Self.FHttpServer).DispatchDataSnap(Request, Response);
11         Result := True;
12       except
13         on E: Exception do
14         begin
15           { Default to 500, like web services. }
16           Response.StatusCode := 500;
17           Result := True;
18         end;
19       end;
20     except
21       { Swallow any unexpected exception, it will bring down some web servers }
22       Result := False;
23     end;
24   finally
25     { Reset current DataSnapWebModule }
26     DataSnapWebModule := nil;
27   end;
28 end;

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

 1 procedure TDSHTTPServerWebBroker.DispatchDataSnap(ARequest: TWebRequest;
 2   AResponse: TWebResponse);
 3 var
 4   LDispatch: TDSHTTPDispatch;
 5   LContext: TDSHTTPContextWebBroker;
 6 begin
 7   LDispatch := TDSHTTPApplication.Instance.HTTPDispatch;
 8   if LDispatch <> nil then
 9     DoCommand(LDispatch.Context, LDispatch.Request, LDispatch.Response)
10   else
11   begin
12     LContext := TDSHTTPContextWebBroker.Create(ARequest, AResponse);
13     try
14       DoCommand(LContext, LContext.FRequest, LContext.FResponse);
15     finally
16       LContext.Free;
17     end;
18   end;
19 end;

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

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

 1 procedure TDSRESTServer.DoCommand(AContext: TDSHTTPContext; ARequestInfo: TDSHTTPRequest;
 2                                   AResponseInfo: TDSHTTPResponse);
 3 var
 4   Request: string;
 5   NextRequest: string;
 6   NextContext: string;
 7   RestCtxt: string;
 8   StartDispatch: Boolean;
 9 begin
10
11   // HTTPDispatch object if necessary
12   StartDispatch := not TDSHTTPApplication.Instance.Dispatching;
13   if StartDispatch then
14     TDSHTTPApplication.Instance.StartDispatch(AContext, ARequestInfo, AResponseInfo);
15   try
16 {$IFNDEF POSIX}
17   if CoInitFlags = -1 then
18     CoInitializeEx(nil, COINIT_MULTITHREADED)
19   else
20     CoInitializeEx(nil, CoInitFlags);
21 {$ENDIF}
22   try
23     // check for context, if not found send the appropriate error message
24     Request := ARequestInfo.URI;
25     if Consume(FDSContext, Request, NextRequest) then
26     begin
27       Request := NextRequest;
28       if Consume(FRESTContext, Request, NextRequest) then
29       begin
30         // datasnap/rest
31         DoDSRESTCommand(ARequestInfo, AResponseInfo, NextRequest);
32       end
33       else if ConsumeOtherContext(Request, NextContext, NextRequest) then
34       begin
35         DoDSOtherCommand(AContext, ARequestInfo, AResponseInfo, NextContext, NextRequest, FDSServerName <> EmptyStr);
36       end
37       else
38       begin
39         RestCtxt := Trim(FRESTContext);
40         if RestCtxt = EmptyStr then
41           RestCtxt := SProtocolRestEmpty;
42
43         AResponseInfo.ResponseNo := 501; {rest or other service not found in URI}
44         AResponseInfo.ContentText := Format(SProtocolNotSupported, [Request, RestCtxt]);
45         AResponseInfo.CloseConnection := true;
46       end;
47     end
48     else
49     begin
50       // This may dispatch .js files for example
51       DoCommandOtherContext(AContext, ARequestInfo, AResponseInfo, Request);
52     end;
53     if Assigned(Self.FTrace ) then
54     begin
55       FTrace(Self, AContext, ARequestInfo, AResponseInfo);
56     end;
57   finally
58
59     ClearInvocationMetadata();
60 {$IFNDEF POSIX}
61     CoUnInitialize;
62 {$ENDIF}
63   end;
64   finally
65     if StartDispatch then
66       TDSHTTPApplication.Instance.EndDispatch;
67   end;
68 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的比较)

 1 program Project1;
 2
 3 uses
 4   Vcl.Forms,
 5   Web.WebReq,
 6   IdHTTPWebBrokerBridge,
 7   Unit1 in ‘Unit1.pas‘ {Form1},
 8   ServerMethodsUnit1 in ‘ServerMethodsUnit1.pas‘,
 9   ServerContainerUnit1 in ‘ServerContainerUnit1.pas‘ {ServerContainer1: TDataModule};
10
11 {$R *.res}
12
13 begin
14   Application.Initialize;
15   Application.MainFormOnTaskbar := True;
16   Application.CreateForm(TForm1, Form1);
17   Application.CreateForm(TServerContainer1, ServerContainer1);
18   Application.Run;
19 end.

机制有何不同?

时间: 2024-08-28 18:11:29

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

读DataSnap源代码(一)

Delphi的DataSnap用了一段时间了,但一直感觉有些地方还不够了解,所以花时间阅读了源代码,特作此烂笔头. Datasnap是在之前的WebBorker基础上搭建的,DataSnap向导自动生成了基础的代码,所以就以基础代码为起点来看看DataSnap的内部机制. 首选创建一个 Stand-alone 的REST App,  向导至少会为我们生成一个Form1和一个WebModule1, FormUnit1单元如下: unit FormUnit1; interface uses Wina

读DataSnap源代码(二)

program Project1; {$APPTYPE GUI} {$R *.dres} uses Vcl.Forms, Web.WebReq, IdHTTPWebBrokerBridge, FormUnit1 in 'FormUnit1.pas' {Form1}, ServerMethodsUnit1 in 'ServerMethodsUnit1.pas', WebModuleUnit1 in 'WebModuleUnit1.pas' {WebModule1: TWebModule}; {$R

读DataSnap源代码(三)

1 function TWebRequestHandler.HandleRequest(Request: TWebRequest; 2 Response: TWebResponse): Boolean; 3 var 4 I: Integer; 5 LWebModule: TComponent; 6 LWebAppServices: IWebAppServices; 7 LGetWebAppServices: IGetWebAppServices; 8 LComponent: TComponent

读DataSnap源代码(四)

继续篇中的 1 function TCustomWebDispatcher.DispatchAction(Request: TWebRequest; 2 Response: TWebResponse): Boolean; 3 var 4 I: Integer; 5 Action, Default: TWebActionItem; 6 Dispatch: IWebDispatch; 7 begin 8 FRequest := Request; 9 FResponse := Response; 10

最近读cocoaui源代码有感

上半年为了做一个ios的应用,引入了cocoaui库,主要是用来布局ios界面,发现简化了不少代码和工作量.因为在写第一个ios应用的时候,用的代码布局,在适配4s和6的机型时候,几乎被搞死,大量的约束定义充斥在代码中,惨不忍睹. cocoaui的作者是ssdb的作者ideawu,在微博里面比较活跃,有问题at他一般很快就会有回应.ssdb是一个类似于redis的nosql数据库:像这样一个在客户端和服务器领域都有建树的人还是很少的.我等普普通通的程序员,距离这种大神还是有一些距离,不过不能气馁

读博士的五个阶段

The motivation during your PhD is not constant, and it resembles the phases that entrepreneurs experience and that Tim Ferriss describes in his post Harnessing Entrepreneurial Manic Depression: Making The Rollercoaster Work for You. Tim provides grea

MYSQL 源代码 编译原理 AST和解析树 代码语法解析

MYSQL 源代码 编译原理 AST和解析树 代码语法解析 http://blog.csdn.net/wfp458113181wfp/article/details/17082355 使用AST树 分类:             antlr              2013-12-02 22:39     255人阅读     评论(0)     收藏     举报 目录(?)[+] 第五章使用AST树中间结果来计算表达式值 创建ASTS 第五章.使用AST树中间结果来计算表达式值 现在我们已

【JUnit4.10源代码分析】6.1 排序和过滤

abstract class ParentRunner<T> extends Runner implements Filterable,Sortable 本节介绍排序和过滤.(虽然JUnit4.8.2源代码分析-6.1 排序和过滤中演示了客户使用排序和过滤的方式,也有些不明白其设计意图,但是,先读懂源代码为妙.说不定看着看着就明白了.) org.junit.runner.manipulation包 排序和过滤的相关类型,在org.junit.runner.manipulation包中. 1.例

学计算机的值得一看的文章,跟帖也很有水平啊

转自http://blog.csdn.net/Xviewee/article/details/1606247 回复CSDN和KAOYAN诸位网友的几点看法,(为避免吵架,郑重声明,本人不是高手,只是有感而发的一点个人陋见,欢迎指正,事先感谢): 就我自己的理解,谈谈我对读研和软件学院的看法,不妥之处一笑了之即可. 如果你有实际开发工作经验,感觉自己的水平和实力进入了一个高原期,迫切需要从理论上提高,那么计算机学院是唯一选择.因为计算机学院才能让你在理论上更上一层楼.软件学院从教学计划上就没有