在之前的博文中,我提到了存根生成器框架,将具有生成Delphi客户端存根代码的能力,使得开发Delphi智能客户端变的更容易,完全支持编译时的类型检查和IDE类/属性帮助。

本不想把这个新功能包含在即将发布的kbmMW版本中,但我无法自控.... 必须添加它才能生成相当完整的客户端存根代码。

存根生成器将生成普通的Delphi代码,需要kbmMW智能客户端功能进行编译。但代码已完成,并包含所需的所有单元引用。如果您使用的是包含对象的自定义单元,则必须将这些单元与生成的存根代码一起提供给Delphi客户端开发人员。

除OpenAPI支持外,SimpleInvocation服务器还支持通过REST接口直接返回Delphi存根代码。

让我们称之为:http://localhost:888/myserver/delphi

这将返回给你一个类似于这样的对话框:

保存它,将得一个单元文件:

unit uSMARTDEMO;

interface

uses
kbmMWGlobal,
kbmMWSmartUtils,
kbmMWSmartClient,
kbmMWClient,
kbmMWClientDataset
,uObjects
,System.Generics.Collections
,kbmMWDateTime
,kbmMemTable
; type
// Name.......: SMARTDEMO
// Version....: kbmMW_1.0
// Abstract...: HTTP smart service supp. FastCGI
// Description: Smart HTTP service (with optional FastCGI and URL rewrite support) which use annotations for publishing methods for both regular clients and REST clients.
//-------------------------------------
TSMARTDEMO = class
private
FClient:IkbmMWSmartClient;
public
constructor Create(const ATransport:TkbmMWCustomClientTransport); overload; virtual;
constructor Create(const AConnectionPool:TkbmMWClientConnectionPool); overload; virtual;
constructor Create(const AClient:IkbmMWSmartClient); overload; virtual;
function StorePerson(const APerson:TPerson):Integer;
function EchoPerson(const APerson:TPerson):TPerson;
function EchoURL:string;
function AddNumbers(const AValue1:Integer; const AValue2:Integer):Integer;
function EchoString(const AString:string):string;
function GetPersons:TObjectList<uObjects.TPerson>;
function GetPerson(const id:Integer):TPerson;
function ServerNow1:TkbmMWDateTime;
function ServerNow2:TDateTime;
function GetPerson3:TPerson3;
function StorePerson3(const APerson:IPerson2):Integer;
function StorePerson2(const APerson:TPerson):Integer;
function ReverseString(const AString:string):string;
function EchoBytes(const ABytes:TArray<System.Byte>):TArray<System.Byte>;
function GetMemTable:TkbmMemTable;
function ReverseStringFromConfig:string;
end; implementation constructor TSMARTDEMO.Create(const ATransport:TkbmMWCustomClientTransport);
begin
inherited Create;
FClient:=TkbmMWSmartRemoteClientFactory.GetClient(ATransport,'SMARTDEMO');
end; constructor TSMARTDEMO.Create(const AConnectionPool:TkbmMWClientConnectionPool);
begin
inherited Create;
FClient:=TkbmMWSmartRemoteClientFactory.GetClient(AConnectionPool,'SMARTDEMO');
end; constructor TSMARTDEMO.Create(const AClient:IkbmMWSmartClient);
begin
inherited Create;
FClient:=AClient;
end; function TSMARTDEMO.StorePerson(const APerson:TPerson):Integer;
var
v0:variant;
begin
v0:=Use.AsVariant(APerson,false);
Result:=FClient.Service.StorePerson(v0);
end; function TSMARTDEMO.EchoPerson(const APerson:TPerson):TPerson;
var
v0:variant;
begin
v0:=Use.AsVariant(APerson,false);
Result:=Use.AsMyObject<TPerson>(FClient.Service.EchoPerson(v0));
end; function TSMARTDEMO.EchoURL:string;
begin
Result:=FClient.Service.EchoURL;
end; function TSMARTDEMO.AddNumbers(const AValue1:Integer; const AValue2:Integer):Integer;
begin
Result:=FClient.Service.AddNumbers(AValue1,AValue2);
end; function TSMARTDEMO.EchoString(const AString:string):string;
begin
Result:=FClient.Service.EchoString(AString);
end; function TSMARTDEMO.GetPersons:TObjectList<uObjects.TPerson>;
begin
Result:=Use.AsMyObject<TObjectList<uObjects.TPerson>>(FClient.Service.GetPersons);
end; function TSMARTDEMO.GetPerson(const id:Integer):TPerson;
begin
Result:=Use.AsMyObject<TPerson>(FClient.Service.GetPerson(id));
end; function TSMARTDEMO.ServerNow1:TkbmMWDateTime;
begin
Result:=Use.AsType<TkbmMWDateTime>(FClient.Service.ServerNow1);
end; function TSMARTDEMO.ServerNow2:TDateTime;
begin
Result:=FClient.Service.ServerNow2;
end; function TSMARTDEMO.GetPerson3:TPerson3;
begin
Result:=Use.AsMyObject<TPerson3>(FClient.Service.GetPerson3);
end; function TSMARTDEMO.StorePerson3(const APerson:IPerson2):Integer;
var
v0:variant;
begin
v0:=Use.AsVariant(APerson);
Result:=FClient.Service.StorePerson3(v0);
end; function TSMARTDEMO.StorePerson2(const APerson:TPerson):Integer;
var
v0:variant;
begin
v0:=Use.AsVariant(APerson,false);
Result:=FClient.Service.StorePerson2(v0);
end; function TSMARTDEMO.ReverseString(const AString:string):string;
begin
Result:=FClient.Service.ReverseString(AString);
end; function TSMARTDEMO.EchoBytes(const ABytes:TArray<System.Byte>):TArray<System.Byte>;
var
v0:variant;
begin
v0:=Use.AsVariant(ABytes);
Result:=Use.AsBytes(FClient.Service.EchoBytes(v0));
end; function TSMARTDEMO.GetMemTable:TkbmMemTable;
begin
Result:=Use.AsMyObject<TkbmMemTable>(FClient.Service.GetMemTable);
end; function TSMARTDEMO.ReverseStringFromConfig:string;
begin
Result:=FClient.Service.ReverseStringFromConfig;
end; end.

您可能已经注意到,SmartInvocation服务中已使用kbmMW_Method属性标记的所有方法都在存根代码中生成了。

存根生成器自动检测编译所需的各种其他单元,如kbmMemTable和uObjects,并添加到uses子句中。

那么我们是如何从REST接口返回存根代码的呢?

在包含REST服务的单元中,我们只添加了一个返回字符串的函数,并使其可以从REST访问。

     [kbmMW_Rest('method:get, path: "delphi", responseMimeType:"text/plain"')]
function DelphiAPI:string;

功能实现非常简单

// Return Delphi stub.
function TkbmMWCustomService2.DelphiAPI:string;
var
unitName:string;
begin
// Return Delphi client stub unit for all methods in this service marked with
// kbmMW_Method attribute.
// Add 'servers: [ "url1", "url2",.. "urln" ]' to ASettings if you want to
// embed server location information in the comments of the returned unit.
Result:=TkbmMWSmartDelphiStubGenerator.GenerateDelphi('',self,unitName);
SetResponseFileName(unitName);
end;

显然你可以从你想要的任何单位调用GenerateDelphi,你可以参考任何kbmMW Smartservice。GenerateDelphi的第一个参数是可选的单元命名前缀。如果未指定任何内容,则单元名将以“u”开头。在这种情况下,我们将收到一个名为uSMARTDEMO.pas的文件,因为它是在Delphi客户端存根中描述的SMARTDEMO服务。

让我们尝试在客户端中使用生成的代码。我们创建了一个基于VCL的标准客户端(kbmMW也可以与Firemonkey一起使用,以便跨平台使用)。我们添加了一个客户端传输(在本例中为TkbmMWTCPIPIndyClientTransport),一个客户端连接池和一些将激活这些调用的按钮。此外,还有一个编辑框,用于键入我们要连接的服务器的IP地址(如果它未在本地主机上运行)。

然后确保将uSMARTDEMO.pas添加到单元的uses子句中。现在我们可以访问存根代码,这样可以轻松调用kbmMW应用程序服务器托管的智能服务。

StorePerson 1的事件处理程序可能如下所示:

procedure TForm1.Button1Click(Sender: TObject);
var
i:integer;
person:IPerson2;
demo:TSMARTDEMO;
begin
Transport.Host:=eIP.Text; demo:=TSMARTDEMO.Create(Transport);
try
person:=TPerson2.Create;
person.Name:='Frank Borland Jr';
person.Address:='California';
person.Age:=;
i:=demo.StorePerson3(person);
finally
demo.Free;
end;
end;

这里的示例使用我们想要使用的传输实例化TSMARTDEMO实例。如果我们愿意,我们可以提供连接池或智能客户端。存根代码支持所有3种变体。

此按钮显示如何将接口对象发送到服务器。

StorePerson 2的事件处理程序可能如下所示:

procedure TForm1.Button2Click(Sender: TObject);
var
person:TPerson;
i:integer;
demo:TSMARTDEMO;
begin
Transport.Host:=eIP.Text; demo:=TSMARTDEMO.Create(Transport);
try
person:=TPerson.Create;
try
person.Name:='Trudy Borland';
person.Address:='California';
person.Age:=;
i:=demo.StorePerson(person);
finally
person.Free;
end;
finally
demo.Free;
end;
end;

略有不同的是,我们为呼叫提供了一个对象。通话结束后,我们释放了对象。所有完全正常的Delphi代码。

Simple Calls的事件处理程序可能如下所示:

procedure TForm1.Button3Click(Sender: TObject);
var
dt1:TkbmMWDateTime;
dt2:TDateTime;
s:string;
i:integer;
demo:TSMARTDEMO;
ba,ba1:TArray<System.Byte>;
begin
Transport.Host:=eIP.Text; demo:=TSMARTDEMO.Create(Transport);
try
s:=demo.EchoString('abc'); SetLength(ba1,);
ba1[]:=;
ba1[]:=;
ba1[]:=;
ba1[]:=;
ba1[]:=;
ba:=demo.EchoBytes(ba1); i:=demo.AddNumbers(,);
dt1:=demo.ServerNow1;
dt2:=demo.ServerNow2;
finally
demo.Free;
end;
end;

它显示了发送和接收的各种类型。

GetPerson的事件处理程序可能如下所示:

procedure TForm1.Button4Click(Sender: TObject);
var
person:TPerson;
person3:TPerson3;
persons:TObjectList<TPerson>;
demo:TSMARTDEMO;
begin
Transport.Host:=eIP.Text; demo:=TSMARTDEMO.Create(Transport);
try
person:=demo.GetPerson();
person.Free; person3:=demo.GetPerson3;
person3.Free; persons:=demo.GetPersons;
persons.Free;
finally
demo.Free;
end;
end;

再次......只显示如何接收各种类型的对象(不使用kbmMWNullable的常规对象,使用kbmMWNullable的对象和对象列表)。

最后,事件处理程序GetMemTable可能如下所示:

procedure TForm1.Button5Click(Sender: TObject);
var
mt:TkbmMemtable;
demo:TSMARTDEMO;
begin
Transport.Host:=eIP.Text; demo:=TSMARTDEMO.Create(Transport);
try
mt:=demo.GetMemTable;
mt.Free;
finally
demo.Free;
end;
end;

此示例显示如何在服务器上生成包含5条记录的内存表实例,从服务器返回到客户端。

在Delphi中制作高级应用程序服务器是否更容易?Delphi通过REST或本机Delphi代码支持各种客户端?我不这么认为

所以......如果你喜欢你所看到的,请分享这个词。转发博客帖子,让其他人了解该产品!

https://components4developers.blog/2019/01/13/rest-easy-with-kbmmw-21-delphi_client_stubs/

REST easy with kbmMW #21 – Delphi client stubs的更多相关文章

  1. REST easy with kbmMW #3 – SSL

    我在前两篇文章中展示了“REST easy with kbmMW”文章,如何使用kbmMW制作REST服务器,以及如何使用该REST服务器轻松地从数据库返回和存储数据,所有这些都在不到30行的真实数据 ...

  2. REST easy with kbmMW #14 – DB Controlled login

    介绍 关于如何使用授权和登录管理来构建应用服务器还存在一些问题,其中之一就是用户及其角色如何在在数据库中定义.该文将解释使用TkbmMWAuthorizationManager解决此问题的一种方法.有 ...

  3. REST easy with kbmMW #20 – OpenAPI and Swagger UI

    即将推出的kbmMW更新不仅是一些bug修正,同时将包含一个新的主要功能:客户端存根生成器框架. 那什么是客户端存根生成器框架呢? 他是一个基于kbmMW smart services,可以生成由各种 ...

  4. REST easy with kbmMW #1

    kbmMW 5.0支持REST服务器的开发,并且非常简单,下面看看如何实作一个REST服务器. 首先我们制作一个服务器应用程序,增加一个简单的Form,并放置kbmMW组件. 在Delphi中单击Fi ...

  5. REST easy with kbmMW #24 使用kbmMW实现JSON/XML/YAML转换成对象

    你想过没有,把一个给定的xml或json生成一个Delphi类,并通过这个类完成对xml或json的读写操作吗? 不管有没有,现在kbmMW为我们实现了,看下面这行代码: var s:string; ...

  6. REST easy with kbmMW #17 – Database 6 – Existing databases

    kbmMW已经包含了非常精细的功能来确定和解释数据库中表的元数据. 在下一版本中,这个功能将得到进一步加强,可以导入现有数据库中的表,自动创建与表相匹配的ORM实体类. 这意味着你能够使用kbmMW的 ...

  7. REST easy with kbmMW #15 – Handling HTTP POST

    我被问到有关如何通过基于kbmMW智能服务(Smart Service)的REST处理POST的问题. 这篇博客文章解释了典型的POST各种形式的访问,以及如何在kbmMW中处理它们. POST变种W ...

  8. REST easy with kbmMW #16 – Multiple servers using HTTP.sys transport

    前文写过使用HTTP.sys转输层(TkbmMWHTTPSysServerTransport),实现一个kbmMW应用服务器. 如果在一台服务器上,同时运行多个,基于TkbmMWHTTPSysServ ...

  9. REST easy with kbmMW #4 – Access management

    在前面有关如何使用kbmMW创建REST服务器的基础上,现在已经到了考虑该如何控制用户的访问.什么是访问管理?就是“允许谁做什么"的问题. 显然,这个世界中存在数据,应该保护他而不被未授权的 ...

随机推荐

  1. python基础之变量以及if语句

    1.变量 1.1定义:变量是一种介质,是将一些值暂时存储在内存中,方便后续程序调用.可将其看作容器但其内部的东西是可变化的. 1.2 变量的命名规则: 1.变量的命名只能由数字,字母,下划线构成. 2 ...

  2. Pandas读取文件

    如何使用pandas的read_csv模块以及其他读取文件的模块?? 一起来看一看 Pandas中read_csv和read_table的区别 注:使用pandas读取文件格式为pandas特有的da ...

  3. Find the duplicate Number (鸽巢原理) leetcode java

    问题描述: Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive ...

  4. SQL SERVER 字符合并多行为一列

    [字符合并多行为一列] 思路1:行转列,在与字符拼接(适用每组列数名相同) 思路2:转xml,去掉多余字符(适用所有) 假设兴趣表Hobbys Name Hobby 小张 打篮球 小张 踢足球 Nam ...

  5. 牛客小白赛1 F题三视图

    链接:https://www.nowcoder.com/acm/contest/85/F来源:牛客网 题目描述 Etéreo 拿出家里的许多的立方体积木,堆成了一个三维空间中的模型.既然你高考选了技术 ...

  6. 第二阶段——个人工作总结DAY09

    1.昨天做了什么:昨天学习了有关后台的知识. 2.今天打算做什么:实现后台. 3.遇到的困难:还是不知道该如何来做.

  7. Matlab-10:Ritz-Galerkin方法求解二阶常微分方程

    一.代数多项式法: tic; clear clc % N=input('please key in the value of ''N'''); N=10; M=100; h=1/M; X=0:h:1; ...

  8. php值传递和引用传递

    1,参数传值方式有两种,第一种是值传递,第二种引用传递.值传递比较简单,也就是在php中,数组是当一个普通变量,值传递是要一个实参的一个拷贝副本,跟实参无关,而引用传递后可以改变实参的值而类的对象是无 ...

  9. 2017-5-19&5-23/系统性能指标

    1. 系统性能指标包括哪些? 业务指标.资源指标.中间件指标.数据库指标.前端指标.稳定性指标.批量处理指标.可扩展性指标.可靠性指标. 1)业务指标:主要包括并发用户数.响应时间.处理能力. 指标 ...

  10. Zabbix监控系统

    前言: 一个初略自动化运维平台,应该实现以下3个层面自动化: 1.操作系统层面自动化 如果想要万台服务器共舞,没有操作系统这个舞台还怎么舞? 1.1:物理环境: OS预备自动安装(Pxe/KickSt ...