delphi面向服务开发解决方案
delphi面向服务开发解决方案
1)服务接口设计
基于openapi3进行接口设计。面向服务设计的接口,支持跨平台和跨语言,支持任何终端设备。
以《商品资料》资源为例。
unit server.resources.goods;
/// <author>cxg 2022-6-8</author>
interface
uses
System.SysUtils, WiRL.Core.Registry, WiRL.Core.Attributes,
WiRL.http.Accept.MediaType;
type
[Path('goods')]
TGoods = class
[post, path('/select/{dbid}'), Produces(TMediaType.APPLICATION_JSON)]
function select(const [PathParam('dbid')] dbid: string): string;
[post, path('/insert/{dbid}'), Produces(TMediaType.APPLICATION_JSON)]
function insert(const [PathParam('dbid')] dbid: string; const [BodyParam] body: TBytes): string;
[post, path('/update/{dbid}/{goodsid}'), Produces(TMediaType.APPLICATION_JSON)]
function update(const [PathParam('dbid')] dbid: string;
const [PathParam('goodsid')] goodsid: string;
const [BodyParam] body: TBytes): string;
[post, path('/delete/{dbid}/{goodsid}'), Produces(TMediaType.APPLICATION_JSON)]
function delete(const [PathParam('dbid')] dbid: string;
const [PathParam('goodsid')] goodsid: string): string;
end;
implementation
{ TGoods }
function TGoods.delete(const dbid, goodsid: string): string;
begin
end;
function TGoods.insert(const dbid: string; const body: TBytes): string;
begin
end;
function TGoods.select(const dbid: string): string;
begin
end;
function TGoods.update(const dbid, goodsid: string; const body: TBytes): string;
begin
end;
initialization
TWiRLResourceRegistry.Instance.RegisterResource<TGoods>;
end.
从上面的《商品资料》接口可以看出,接口设计完全不依赖框架,即使是不懂技术的产品经理也能设计接口。
在云服务器上部署《服务接口中间件》

客户端浏览器打开:http://42.193.160.160:8080/rest/app/openapi/


即可以在浏览器里面在线查看设计好的服务接口。
2)中间件实现《商品资料》业务逻辑
接口设计好以后,就开始实现《商品资料》的业务逻辑。
首先实现《商品资料》的data-model
//protobuf模板文件
syntax="proto3";
package goods;
//商品资料
message Goods {
string goodsid = 1; //商品编号
string goodsname = 2; //商品名称
double price = 3; //价格
}
//商品资料数组
message GoodsArr {
repeated Goods Goodss = 1;
}
//查询条件
message GoodsQuery {
string goodsid = 1; //商品编号
string goodsname = 2; //商品名称
}
用google protobuf实现data-model,目的是为了支持跨语言。目前所有的主流语言都提供工具,根据 .proto模型文件,自动生成本语言的代码。
运行codegen.bat,根据商品资料model文件goods.proto,自动生成对应的PASCAL code。

自动生成的PASCAL商品资料 model
{ Unit pbGoodsMessages.pas }
{ Generated from goods.proto }
{ Package Goods }
unit pbGoodsMessages;
interface
uses Grijjy.ProtocolBuffers, SysUtils;
{ TGoodsRecord }
type
TGoodsRecord = record
[Serialize(1)] Goodsid : String;
[Serialize(2)] Goodsname : String;
[Serialize(3)] Price : Double;
end;
{ TDynArrayGoodsRecord }
type
TDynArrayGoodsRecord = array of TGoodsRecord;
{ TGoodsArrRecord }
type
TGoodsArrRecord = record
[Serialize(1)] Goodss : TDynArrayGoodsRecord;
end;
{ TGoodsQueryRecord }
type
TGoodsQueryRecord = record
[Serialize(1)] Goodsid : String;
[Serialize(2)] Goodsname : String;
end;
implementation
end.
中间件编写业务逻辑,以商品资料查询为例,下面是json序列
function goodsQry(url: string; body: rawbytestring): string;
var
db: tdb;
pool: tdbpool;
arr: tarray<string>;
serial: TJsonSerializer;
sp: TGoodsrecord;
sps: TDynArrayGoodsRecord;
i: Integer;
err: TResRecord;
begin
serial := TJsonSerializer.Create;
try
try
arr := url.Split(['/']);
pool := GetDBPool(arr[4]);
db := pool.Lock;
db.qry.Close;
db.qry.SQL.Clear;
db.qry.SQL.Text := 'select * from tgoods';
db.qry.Open;
SetLength(sps, db.qry.RecordCount);
db.qry.First;
i := 0;
while not db.qry.Eof do
begin
sp.goodsid := db.qry.FieldByName('goodsid').AsString;
sp.goodsname := db.qry.FieldByName('goodsname').AsString;
sps[i] := sp;
inc(i);
db.qry.Next;
end;
Result := serial.Serialize<TDynArrayGoodsRecord>(sps);
except
on E: Exception do
begin
err.ok := False;
err.err := e.Message;
Result := serial.Serialize<TResRecord>(err);
end;
end;
finally
pool.Unlock(db);
serial.Free;
end;
end;
下面是protobuf序列
function goodsQry(url: string; body: tbytes): tbytes;
var
db: tdb;
pool: tdbpool;
serial: TgoProtocolBuffer;
arr: tarray<string>;
dw: TUnitsRecord;
sp: TGoodsRecord;
sps: pbGoodsMessages.TGoodsArrRecord;
i: integer;
err: TresRecord;
begin
serial := TgoProtocolBuffer.Create;
try
try
arr := url.Split(['/']);
pool := GetDBPool(arr[4]);
db := pool.Lock;
db.qry.Close;
db.qry.SQL.Clear;
db.qry.SQL.Text := 'select * from tgoods';
db.qry.Open;
SetLength(sps.Goodss, db.qry.RecordCount);
db.qry.First;
i := 0;
while not db.qry.Eof do
begin
sps.Goodss[i].Goodsid := db.qry.FieldByName('goodsid').AsString;
sps.Goodss[i].Goodsname := db.qry.FieldByName('goodsname').AsString;
inc(i);
db.qry.Next;
end;
Result := serial.Serialize<pbGoodsMessages.TGoodsArrRecord>(sps);
except
on E: Exception do
begin
err.ok := False;
err.err := e.Message;
Result := serial.Serialize<TresRecord>(err);
end;
end;
finally
pool.Unlock(db);
serial.Free;
end;
end;
客户端查询

json查询
procedure TForm1.Button1Click(Sender: TObject);
//查询 json
begin
var t: TTablesRecord := TRest.qryJson<TTablesRecord>('/rest/tables/qry/1');
//计量单位
FDMemTable1.EmptyDataSet;
FDMemTable1.DisableControls;
for var dw: TUnitsRecord in t.Unitss do
FDMemTable1.AppendRecord([dw.Unitid, dw.Unitname]);
FDMemTable1.First;
FDMemTable1.EnableControls;
//商品资料
ClientDataSet1.EmptyDataSet;
ClientDataSet1.DisableControls;
for var sp: TGoodsRecord in t.Goodss do
ClientDataSet1.AppendRecord([sp.Goodsid, sp.Goodsname]);
ClientDataSet1.First;
ClientDataSet1.EnableControls;
end;
google protobuf查询
procedure TForm1.Button2Click(Sender: TObject);
//查询 protobuf
begin
var t: TTablesRecord := TRest.qryPB<TTablesRecord>('/protobuf/tables/qry/1');
//计量单位
FDMemTable1.EmptyDataSet;
FDMemTable1.DisableControls;
for var dw: TUnitsRecord in t.Unitss do
FDMemTable1.AppendRecord([dw.Unitid, dw.Unitname]);
FDMemTable1.First;
FDMemTable1.EnableControls;
//商品资料
ClientDataSet1.EmptyDataSet;
ClientDataSet1.DisableControls;
for var sp: TGoodsRecord in t.Goodss do
ClientDataSet1.AppendRecord([sp.Goodsid, sp.Goodsname]);
ClientDataSet1.First;
ClientDataSet1.EnableControls;
end;
本文来自博客园,作者:{咏南中间件},转载请注明原文链接:https://www.cnblogs.com/hnxxcxg/p/16358008.html

浙公网安备 33010602011771号