begin
Result := Data; // log outgoing data end;
function TLogFilter.Id: UnicodeString; begin
Result := LogFilterName; end;
最后,重要的实现部分是在initialization和finalization中注册DataSnap传输过滤器.确保客户端可以找到这个传 输过滤器,并在请求时自动使用. initialization
TTransportFilterFactory.RegisterFilter(LogFilterName, TLogFilter); finalization
TTransportFilterFactory.UnregisterFilter(LogFilterName); end.
为了在DataSnap服务端使用这个传输过滤器,我们需要将其加入到TDSTCPServer或DSHTTPService组件
的Filters属性中,非常简单.在设计时,已知存在一个ZLibCompression过滤器,但无法感知新的过滤器(除非将其
添加到设计时包中并安装).幸运的是我们也可以在运行时添加过滤器,在ServerContainerUnitDemo单元中引用
过滤器单元,然后手动向Filters属性中添加过滤器.如.
procedure TServerContainer1.DataModuleCreate(Sender: TObject); begin
DSTCPServerTransport1.Filters.AddFilter(LogFilterName); DSHTTPService1.Filters.AddFilter(LogFilterName);
DSHTTPService1.Active := True; end;
这将确保服务端使用LogFilter,客户端只要在单元中引用LogFilter单元就会自动使用LogFilter.否则将抛出 错误信息:
注意DataSnap客户端和服务端将获取各自的logfile实例.虽然使用的同一个过滤器,但是却不需用
ParamStr(0)来区分日志信息. 4.3. 加密过滤器
即使是一个如4.2中的一个简单的过滤器,也需要自己去扩展,很复杂.DataSnap提供的过滤器不太完整.事实
上,有大量的三方过滤器可以使用,有Daniele Teti开发的DataSnap Filters Compendium可以
在http://www.danieleteti.it/?p=168中获取,其中不少于9个用于DataSnap2010的附加过滤器,分成三个
组.Hash组支持MD5,MD4,SHA1和SHA512,Cipher组支持Blowfish,Rijndael, 3TDES 和 3DES, Compress 组支持LZO.并且是全源码版. 5. 如何构建DATASNAP WEB项目
除了生成Windows项目,还提供了生成ISAPI,CGI或Web App Debugger目标项目的向导.首先我们讨论
一下每种项目类型的优缺点,并展示如何在一个项目组中同时创建出这三个项目,并让他们共享公共的单元
文件.这样我们就可以为同一个DataSnap项目产生三个不同的部署目标. 虽然到目前为止我们构建的DataSnap服务应用程序运行良好.但是在有些情况下就无法部署服务程序.例
如如果你不能或不允许在防火墙中打开请求的端口让客户端连接服务器.幸运的是,这种情况下我们可以使
用Web服务来部署,而80端口号一直都是打开的.如果我们使用IIS来作为Web服务器,我们就可以使用新的
DataSnap WebBroker应用程序向导来创建一个可部署在IIS上的应用.
DataSnap WebBroker应用程序向导提供了三个选项,第一个选项实际上不是真正的WebBroker应用,但
仅仅Web App Debugger可执行文件,这是用于调试目的的. Web App Debugger
可执行文件很强大,允许我 们使用Web App Debugger(Delphi IDE Tooles菜单中)作为调试Web App Debugger应用程序的宿主程序.
调试CGI或ISAPI/NSAPI Web应用非常不方便,因此在开发过程中最好选择Web App Debugger模式.
而ISAPI/NSAPI Dynamic Link Library 和 CGI Stand-alone executable 类型项目可用于真正部署的 DataSnap服务项目上.
注意,选择CGI Stand-alone executable不是一个好主意,因为这个可执行文件将在每次请求中加载卸载.
在加上要连接到数据库执行一些任务,你必须要考虑到应用程序的执行效率.使用ISAPI的DLL形式,只需要
加载一次,保存在内存中,后续请求(可能来自其他用户)不需要再次加载.ISAPI DLL的主要缺点是升级困难
(如果你用FTP连接到Web服务器).但可以联系Web服务供应商.
ISAPI DLL的另一个缺点是调试不方便—必须用IIS作为宿主应用,不能总是按计划的那样运行.但可以用
Web App Debugger executable来解决这个问题—同时创建两个项目,他们使用公共的DataSnap方法和代
码.第一个范例就是这种形式,加入一些实用的功能构建一个框架. 5.3. 服务方法,部署,客户端
增加功能时只需要修改被两个项目共享的ServerMethodUnit1.pas单元.默认有一个范例函数,就是上面的
范例,我们包含多个方法(组件说明和源码见2.1.4.).服务端方法实现后,我们就可以将ISAPI DLL部署到IIS. 详细信息可见
http://blogs.embarcadero.com/jimtierney/2009/08/20/31502.
本例中如你没有Web服务可用于部署,可以使用我已部署的DataSnap ISAPI.注意我没有发布
TDataSetProvider,也没有实现返回数据的GetEmployees方法,但是ServerTime和EchoString方法都运行
良好,可以用来测试DataSnap客户端了.
在客户端连接ISAPI DataSnap服务端前,可以使用Data Explorer检查一下是否可以连接到ISAPI
DataSnap服务. Data Explorer上有一个新的叫做DATASNAP的目录,展开后,第
一个连接叫做
DataSnapConnection,右键修改连接.在这个对话框中我们可以选择协议,主机(如你没有自己的Web服务可
以使用www.bobswart.nl),端口号,以及ISAPI DataSnap服务应用程序在Web服务器上的URL路径,这里是
cgi-bin/DSISAPIServer.dll.点击测试连接.
点击OK关闭窗口,在Data Explorer,展开DATASNAPCONNECTION节点查看表,视图,过程,函数和
同义词.下图中,过程包括DSAdmin,DSMetaData,TServerMethods1.AS_XXX及我们自定义的三个函数
EchoString,ServerTime 和 GetEmployees.
不需要写DataSnap客户端,现在就可以测试这些方法.例如EchoString方法(发送什么返回什么).右键点击
TServerMethods1.GetEmployees方法,选择View Parameters,弹出一个新窗口,输入参数(例如42).在这个新
窗口中右击,选择”执行远程服务方法”.运行结果将显示在ReturnValue中.
这样我们就可以调用远程DataSnap服务方法.为了在客户端连接到远程服务端,我们只需要修改
TSQLConnection组件的属性.原来我们连接都Windows版本的DataSnap服务,现在我们需要修改设置连接到 Web版本.
注意,如果你使用的是我发布的DSISAPIServer.dll,我已经禁用了TDataSetProvider,而且GetEmployees方法
不返回任何数据.但你可以使用ServerTime 和 EchoString方法. 6.如何使用REST和JSON
DataSnap2010支持REST和JSON.DataSnap2010特性REST支持DataSnap HTTP请求.例如,如果
DataSnap服务的URI是http://www.bobswart.nl/cgi-bin/DSISAPIServer.dll.我们可以在此URL后
加 /datasnap/rest,后跟服务类名称,方法名称和参数.语法如下: http://server/datasnap/rest/
对于我的服务器上的TServerMethod1模块中的ServerTime方法,URL如下: http://www.bobswart.nl/cgi-bin/DSISAPIServer.dll/datasnap/rest/TServerMethods1/ServerTime
在浏览器中输入这个REST支持的URL,如下图: 在浏览器中返回结果是JSON结构: {\
更多信息见Marco Cantù的Delphi2010和REST客户端白页. 6.1. 回调
除了用REST支持调用DataSnap服务方法外,JSON还用于实现回调方法.DataSnap2010支持客户端回调
函数,使其执行在服务方法上下文中.这样就可以实现客户端调用服务端方法时,服务端就可以调用由客户端传 递好参数的回调函数.
例如,我们修改EchoString方法,向其中添加回调支持.修改后的EchoString方法如下:
function EchoString(Value: string; callback: TDBXcallback): string; TDBXcallback类定义在DBXJSON单元.在我们实现EchoString方法前,先搞清楚如何在客户端定义回调函
数(毕竟,这是一个可以让服务端调用的客户端方法).
在客户端,我们必须定义一个新类,继承在TDBXCallback,重写其Execute方法. type
TCallbackClient = class(TDBXCallback) public
function Execute(const Arg: TJSONValue): TJSONValue; override; end;