• 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;
    

      

  • 相关阅读:
    JAVA-JSP内置对象之response对象
    JAVA-JSP内置对象之request对象的其他方法
    JAVA-JSP内置对象之request获得封装所有参数值的Map
    JAVA-JSP内置对象之request获得参数的所有参数值(多个值)
    JAVA-JSP内置对象之request获得参数的参数值(一个值)
    Animator根骨骼运动原始实现代码
    Unity胶囊体的碰撞检测实现
    Animation Play/Stop测试
    texconv下载以及使用命令
    unity替换mesh测试
  • 原文地址:https://www.cnblogs.com/hnxxcxg/p/16358008.html
Copyright © 2020-2023  润新知