一只变色鸡 發表於 2022-6-9 08:49:00

delphi面向服务开发解决方案

<p>delphi面向服务开发解决方案</p>
<p>1)服务接口设计</p>
<p>基于openapi3进行接口设计。面向服务设计的接口,支持跨平台和跨语言,支持任何终端设备。</p>
<p>以《商品资料》资源为例。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">unit server.resources.goods;
/// &lt;author&gt;cxg 2022-6-8&lt;/author&gt;

interface

uses
System.SysUtils, WiRL.Core.Registry, WiRL.Core.Attributes,
WiRL.http.Accept.MediaType;

type

TGoods = class
   
    function select(const dbid: string): string;
   
    function insert(const dbid: string; const body: TBytes): string;
   
    function update(const dbid: string;
      const goodsid: string;
      const body: TBytes): string;
   
    function delete(const dbid: string;
      const 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(constdbid: string): string;
begin

end;

function TGoods.update(const dbid, goodsid: string; const body: TBytes): string;
begin

end;

initialization
TWiRLResourceRegistry.Instance.RegisterResource&lt;TGoods&gt;;

end.
</pre>
</div>
<p> 从上面的《商品资料》接口可以看出,接口设计完全不依赖框架,即使是不懂技术的产品经理也能设计接口。</p>
<p> 在云服务器上部署《服务接口中间件》</p>
<p><img src="https://img2022.cnblogs.com/blog/368779/202206/368779-20220609082129211-115830531.png"></p>
<p>客户端浏览器打开:http://42.193.160.160:8080/rest/app/openapi/</p>
<p><img src="https://img2022.cnblogs.com/blog/368779/202206/368779-20220609082302304-1312224337.png"></p>
<p><img src="https://img2022.cnblogs.com/blog/368779/202206/368779-20220609082418329-1022781724.png"></p>
<p>&nbsp;</p>
<p>即可以在浏览器里面在线查看设计好的服务接口。</p>
<p>2)中间件实现《商品资料》业务逻辑</p>
<p>接口设计好以后,就开始实现《商品资料》的业务逻辑。</p>
<p>首先实现《商品资料》的data-model</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">//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;        //商品名称
}
</pre>
</div>
<p>用google protobuf实现data-model,目的是为了支持跨语言。目前所有的主流语言都提供工具,根据 .proto模型文件,自动生成本语言的代码。</p>
<p>运行codegen.bat,根据商品资料model文件goods.proto,自动生成对应的PASCAL code。</p>
<p><img src="https://img2022.cnblogs.com/blog/368779/202206/368779-20220609083032255-696101524.png"></p>
<p>自动生成的PASCAL商品资料 model</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">{ Unit pbGoodsMessages.pas }
{ Generated from goods.proto }
{ Package Goods }

unit pbGoodsMessages;

interface

uses Grijjy.ProtocolBuffers, SysUtils;

{ TGoodsRecord }

type
TGoodsRecord = record
    Goodsid : String;
    Goodsname : String;
    Price : Double;
end;

{ TDynArrayGoodsRecord }

type
TDynArrayGoodsRecord = array of TGoodsRecord;

{ TGoodsArrRecord }

type
TGoodsArrRecord = record
    Goodss : TDynArrayGoodsRecord;
end;

{ TGoodsQueryRecord }

type
TGoodsQueryRecord = record
    Goodsid : String;
    Goodsname : String;
end;

implementation

end.
</pre>
</div>
<p> 中间件编写业务逻辑,以商品资料查询为例,下面是json序列</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">function goodsQry(url: string; body: rawbytestring): string;
var
db: tdb;
pool: tdbpool;
arr: tarray&lt;string&gt;;
serial: TJsonSerializer;
sp: TGoodsrecord;
sps: TDynArrayGoodsRecord;
i: Integer;
err: TResRecord;
begin
serial := TJsonSerializer.Create;
try
    try
      arr := url.Split(['/']);
      pool := GetDBPool(arr);
      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 := sp;
      inc(i);
      db.qry.Next;
      end;
      Result := serial.Serialize&lt;TDynArrayGoodsRecord&gt;(sps);
    except
      on E: Exception do
      begin
      err.ok := False;
      err.err := e.Message;
      Result := serial.Serialize&lt;TResRecord&gt;(err);
      end;
    end;
finally
    pool.Unlock(db);
    serial.Free;
end;
end;</pre>
</div>
<p> 下面是protobuf序列</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">function goodsQry(url: string; body: tbytes): tbytes;
var
db: tdb;
pool: tdbpool;
serial: TgoProtocolBuffer;
arr: tarray&lt;string&gt;;
dw: TUnitsRecord;
sp: TGoodsRecord;
sps: pbGoodsMessages.TGoodsArrRecord;
i: integer;
err: TresRecord;
begin
serial := TgoProtocolBuffer.Create;
try
    try
      arr := url.Split(['/']);
      pool := GetDBPool(arr);
      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.Goodsid := db.qry.FieldByName('goodsid').AsString;
      sps.Goodss.Goodsname := db.qry.FieldByName('goodsname').AsString;
      inc(i);
      db.qry.Next;
      end;
      Result := serial.Serialize&lt;pbGoodsMessages.TGoodsArrRecord&gt;(sps);
    except
      on E: Exception do
      begin
      err.ok := False;
      err.err := e.Message;
      Result := serial.Serialize&lt;TresRecord&gt;(err);
      end;
    end;
finally
    pool.Unlock(db);
    serial.Free;
end;
end;
</pre>
</div>
<p> 客户端查询</p>
<p><img src="https://img2022.cnblogs.com/blog/368779/202206/368779-20220609084818091-964217407.png"></p>
<p>json查询</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">procedure TForm1.Button1Click(Sender: TObject);
//查询 json
begin
var t: TTablesRecord := TRest.qryJson&lt;TTablesRecord&gt;('/rest/tables/qry/1');
//计量单位
FDMemTable1.EmptyDataSet;
FDMemTable1.DisableControls;
for var dw: TUnitsRecord in t.Unitss do
    FDMemTable1.AppendRecord();
FDMemTable1.First;
FDMemTable1.EnableControls;
//商品资料
ClientDataSet1.EmptyDataSet;
ClientDataSet1.DisableControls;
for var sp: TGoodsRecord in t.Goodss do
    ClientDataSet1.AppendRecord();
ClientDataSet1.First;
ClientDataSet1.EnableControls;
end;
</pre>
</div>
<p> google protobuf查询</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">procedure TForm1.Button2Click(Sender: TObject);
//查询 protobuf
begin
var t: TTablesRecord := TRest.qryPB&lt;TTablesRecord&gt;('/protobuf/tables/qry/1');
//计量单位
FDMemTable1.EmptyDataSet;
FDMemTable1.DisableControls;
for var dw: TUnitsRecord in t.Unitss do
    FDMemTable1.AppendRecord();
FDMemTable1.First;
FDMemTable1.EnableControls;
//商品资料
ClientDataSet1.EmptyDataSet;
ClientDataSet1.DisableControls;
for var sp: TGoodsRecord in t.Goodss do
    ClientDataSet1.AppendRecord();
ClientDataSet1.First;
ClientDataSet1.EnableControls;
end;
</pre>
</div>
<p>  </p>

</div>
<div id="MySignature" role="contentinfo">
    <p>本文来自博客园,作者:{咏南中间件},转载请注明原文链接:https://www.cnblogs.com/hnxxcxg/p/16358008.html</p><br><br>
来源:https://www.cnblogs.com/hnxxcxg/p/16358008.html
頁: [1]
查看完整版本: delphi面向服务开发解决方案