delphi面向服务开发解决方案

delphi面向服务开发解决方案

1)服务接口设计

基于openapi3进行接口设计。面向服务设计的接口,支持跨平台和跨语言,支持任何终端设备。

以《商品资料》资源为例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
{ 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序列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
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序列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
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查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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;

  

posted @   delphi中间件  阅读(779)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示