使用http.sys,让delphi的多层服务真的飞起来【第二部】
2021-04-07 03:25
标签:close pre 类型 字节 ... date tao unlock 属性 这是本专题的续集,没读过第一部的看这里: 之所以要搞第二部是因为第一部跟贴太多,读起来不方便,浪费大家的时间。 今天咱们聊的主题是:Delphi的DataSnap实质分析 明白了这个道理,我们完全可以抛开Delphi那个复杂的DataSnap不理,自己来构建简单可靠而且高效的多层框架。 Data与Delta都是Variant,无法在网络上传输,我们需要这俩变成字符串,先来两个函数: {$IFNDEF UNICODE} function VariantArrayToString(const V: OleVariant): RawByteString; function StringToVariantArray(const S: RawByteString): OleVariant; 看明白了吗?Data与Delta内部存储的都是字节流。变成字节流以后有两种传送方式,一种是以Stream方式,ContentType设置成application/octet-stream;另一种将字节流base64编码成纯文本。大数据流可以加入压缩/减压机制,保密数据可以加入加密/解密机制。 base64编码与解码,Delphi自带,单元名为EncdDecd。里面有EncodeString与DecodeString两个函数。 unit DP2CDSMain; interface uses type var implementation uses SysUtils, Variants, EncdDecd; {$R *.dfm} {$IFNDEF UNICODE} function VariantArrayToString(const V: OleVariant): RawByteString; function StringToVariantArray(const S: RawByteString): OleVariant; procedure TForm2.Button1Click(Sender: TObject); //模拟网络传送 vDataOut := StringToVariantArray(cDataOut); end. 我这里转载了一篇文章细说CDS的用法: 没仔细看过手机版的CDS,不知道是不是完全实现了PC版的功能,用过的朋友多发帖。 说点题外话,CDS鼠标右键菜单有一项“Assign Local Data...”,可以将相同窗体上的任何TDataset的数据复制到CDS中,如何实现的呢?我猜想就是用到了DP, 应该是这样写的: var DP:TDatasetProvider; 使用http.sys,让delphi的多层服务真的飞起来【第二部】 标签:close pre 类型 字节 ... date tao unlock 属性 原文地址:https://www.cnblogs.com/c5soft/p/9123923.html
http://bbs.2ccc.com/topic.asp?topicid=548153
先说DataSnap中文应该翻译成什么,我个人的译法是:数据快照。
大家不要被这么多介绍DataSnap的资料弄晕了,其实原理非常简单。
要把DataSnap搞明白,必须先把客户端的TClientDataset控件搞明白,不会,找度娘。下面简称CDS。
CDS有两个OleVarient属性,一个叫Data,一个叫Delta。Delphi的多层框架全靠这哥俩。Data用于客户端从服务器端获取数据,Delta用于客户端将修改的数据保存到服务器端。
那么,这就简单了,服务器端只要能实现输出Data,接收Delta,三层应用就搞起来了。服务器端这项工作安排给谁呢?TDatasetProvider,下面简称DP。
DP有一个Data属性,也是OleVariant类型,还有一个ApplyUpdate方法,接受Delta作为输入参数。
服务器端自然用mORMot来稿,用THttpApiServer+DP,充分发挥http.sys的威力,站在巨人的肩膀上,呼风唤雨。
客户端我们用Delphi10.2.3来做,支持PC/Android/iOS, 用CDS+TNetHTTPRequest来做。
不考虑手机的,继续用Delphi7做PC应用的铁粉,用CDS+THttpClientSocket(mORMot自带)。
type
RawByteString = AnsiString;
{$ENDIF}
var
P: Pointer;
Size: Integer;
begin
Result := ‘‘;
if VarIsArray(V) and (VarType(V) and varTypeMask = varByte) then begin
Size := VarArrayHighBound(V, 1) - VarArrayLowBound(V, 1) + 1;
if Size > 0 then begin
SetLength(Result, Size);
P := VarArrayLock(V);
try
Move(P^, Result[1], Size);
finally
VarArrayUnlock(V);
end;
end;
end;
end;
var
P: Pointer;
begin
Result := NULL;
if Length(S) > 0 then begin
Result := VarArrayCreate([0, Length(S) - 1], varByte);
P := VarArrayLock(Result);
try
Move(S[1], P^, Length(S));
finally
VarArrayUnlock(Result);
end;
end;
end;
为了让大家把原理搞懂,我们先抛开网络传输层,将CDS与DP放在一个屋子里让他俩亲热一把。
Forms, DBClient, DB, Provider, ADODB, Controls, Grids, DBGrids, ComCtrls,
Classes, StdCtrls;
TForm2 = class(TForm)
ServerData: TADODataSet;
Button1: TButton;
ClientData: TClientDataSet;
ServerDataSetProvider: TDataSetProvider;
PageControl1: TPageControl;
TabSheet2: TTabSheet;
DataSource1: TDataSource;
DBGrid1: TDBGrid;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
Form2: TForm2;
type
RawByteString = AnsiString;
{$ENDIF}
var
P: Pointer;
Size: Integer;
begin
Result := ‘‘;
if VarIsArray(V) and (VarType(V) and varTypeMask = varByte) then begin
Size := VarArrayHighBound(V, 1) - VarArrayLowBound(V, 1) + 1;
if Size > 0 then begin
SetLength(Result, Size);
P := VarArrayLock(V);
try
Move(P^, Result[1], Size);
finally
VarArrayUnlock(V);
end;
end;
end;
end;
var
P: Pointer;
begin
Result := NULL;
if Length(S) > 0 then begin
Result := VarArrayCreate([0, Length(S) - 1], varByte);
P := VarArrayLock(Result);
try
Move(S[1], P^, Length(S));
finally
VarArrayUnlock(Result);
end;
end;
end;
var
vDataIn, vDataOut: OleVariant;
cDataIn, cDataOut: RawByteString;
begin
ClientData.Close;
vDataIn := ServerDataSetProvider.Data;
cDataIn := VariantArrayToString(vDataIn);
cDataOut:=cDataIn;
ClientData.Data := vDataOut;
end;
https://www.cnblogs.com/c5soft/p/9121775.html
begin
DP:=TDatasetProvider.Create;
DP.Dataset=ADODataset1;
ClientDataset1.Data:=DP.Data;
DP.Free
end;
下一篇:C# 8.0的计划特性
文章标题:使用http.sys,让delphi的多层服务真的飞起来【第二部】
文章链接:http://soscw.com/index.php/essay/72235.html