Delphi XE程序设计系列 1-主从架构, 多层到JSON和REST

2024-02-03 08:40

本文主要是介绍Delphi XE程序设计系列 1-主从架构, 多层到JSON和REST,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

从桌面开发,主从架构,一直到多层架构,虽然都是广泛被接受的观念和技术,但在信息技术的实作上却从不是开放, 相容的世界。Delphi从桌面开发到主从架构都是使用自己的数据传递格式以及通讯传递架构,到了多层架构虽然使用了Windows平台上的通讯协议,例 如COM/DCOM/COM+,但是在传递的数据格式方面仍然是使用自己的架构,COM/DCOM/COM+也是MS专属的通讯协议,和其它平台上使用的 通讯协议也不一样。当然,不光是Delphi/BCB,大部份的开发工具也是采用类似的方式,那就是都支持桌面开发,主从架构或是多层架构等通用观念的架 构,但使用来传递数据和沟通通讯协议都是封闭的架构。

直到JSONREST的出现以及Delphi/BCB确定走向原生,跨平台的道路之后,Delphi/BCB 2010版便开始走向以JSON封装数据,以REST做为通讯架构的方向。因此Delphi/BCB除了仍然支持原有的数据封装格式以及通讯协议之外,也允许开发人员选择使用JSONREST,使用JSONREST的好处是除了可以让JSONREST拥抱最新的信息技术之外,也可以让 Delphi/BCB在不同的平台中使用相同的技术来开发主从架构,分布式多层以及Web应用,也可以更容易的和其它的程序语言,框架和技术整合在一起。

现在让我们重温旧梦一下,看看如何把一个简单的主从架构应用程序转换为使用JSON的架构。

主从架构

下图是一个简单的主从架构的主窗体,

它藉由下图的dbExpress组件从数据库的FishFacts数据表中取得数据,并且使用数据感知组件显示在应用程序的主窗体中。

虽然从BDEdbExpress都使用专属的格式封装资料,但BDEdbExpress也可以把数据封装成较开放的XML格式,因此要把上图中TClientDataSet中的数据转换为XML的格式,我们只需要存取它的XMLData特性值即可:

dssmFishFact.cdsFishFact.XMLData;

XMLData特性值会回传以下面格式封装的XML数据:

<?xml version=1.0″ encoding=UTF-8″ standalone=yes?> <DATAPACKET Version=2.0″><METADATA><FIELDS><FIELD attrname=Category fieldtype=string WIDTH=15″/><FIELD fieldname=Species Name attrname=Species_Name fieldtype=string WIDTH=40″/><FIELD fieldname=Length (cm) attrname=Length__cm_ fieldtype=r8″/><FIELD attrname=Length_In fieldtype=r8″/><FIELD attrname=Common_Name fieldtype=string WIDTH=30″/><FIELD attrname=Notes fieldtype=string WIDTH=50″/><FIELD attrname=Graphic fieldtype=bin.hex SUBTYPE=Binary WIDTH=1″/><FIELD fieldname=Species No attrname=Species_No fieldtype=r8″/></FIELDS><PARAMS LCID=0″/></METADATA><ROWDATA><ROW Category=Triggerfish Species_Name=Ballistoides conspicillum Length__cm_=50″ Length_In=19.68503937007874″ Common_Name=Clown Triggerfish Notes=Also known as the big spotted triggerfish. Inhabi

然而BDE/dbExpress虽然能够把数据封装成XML格式,但使用XML封装数据时仍然会因为不同的数据存取使用不同的XML元素来封装资 料,因此在交换数据时仍然会造成许多的困扰,而且使用XML格式封装数据的成本比起JSON来要昂贵许多(XML使用较多元素,较为复杂的规则封装数据所 致)

因此Delphi/BCB要支持JSON/REST技术,其中一个工作就是必须能够把数据封装成JSON的格式,因此从Delphi/BCB 2010版开始便在VCLRTL中加入了许多和JSON相关的类别以执行这项工作。到了XEDelphi/BCB基本上不但能够把数据封装成JSON 的格式,甚至提供了RESTAPI允许DelphiBCB和任何支持JSONREST的客户端和使用Delphi/BCB开发的DataSnap伺 服器整合在一起,下图叙述了Delphi/BCB XE版支持的架构:

OK,现在先让我们看看Delphi/BCB XE如何能够把数据封装成JSON的格式,以及提供解析,处理JSON封包的相关类别。稍后我们再讨论Delphi/BCB XE如何支持REST API的使用和呼叫。

其实要把dbExpress中的数据封装成JSON非常的简单,就以直觉来说,我们只需要一个单向,只读的数据集,这个单向,只读的资料集可以直接从dbExpress的数据集组件建立,接着再一一的从这个单向,只读的数据集中读取数据,根据JSON规则封装即可。

因此在VCL中提供了TDBXDataSetReader这个单向,只读的资料集,它可以从dbExpress数据集组件建立,接着在TDBXJSONTools类别中提供了TableToJSON类别方法,它接受一个TDBXReader对象为第一个参数,第二个参数为要从第一个参数中封装的记录笔数,最后一个参数则代表在TableToJSON执行完毕之后是否需要释放第一个参数对象:

class function TableToJSON(const Value: TDBXReader; const RowCount: Integer; const IsLocalConnection: Boolean): TJSONObject; static;

因此要封装范例FishFacts数据表中的2笔资料为JSON格式,我们就可以使用下面的程序代码来完成这个工作。

在下面的程序代码中我们首先藉由数据模块中的TClientDataSet组件建立TDBXDataSetReader组件,接着呼叫TDBXJSONTools类别的TableToJSON类别方法把数据封装成JSON格式:

procedure TForm1.btnToJSONClick(Sender: TObject);

var

aDBXReader : TDBXReader;

aJSonObj : TJSONObject;

begin

aDBXReader := TDBXDataSetReader.Create(dssmFishFact.cdsFishFact, False);

try

aJSonObj := TDBXJSONTools.TableToJSON(aDBXReader, 2, False);

Memo2.Lines.Text := aJSonObj.ToString;

ParseData(aJSonObj);

finally

aJSonObj.Free;

aDBXReader.Free;

end;

end;

下图是执行

dssmFishFact.cdsFishFact.XMLData;

之后得到的XML格式的结果:

而下图则是藉由TableToJSON转换为JSON格式的结果:

如果我们观察JSON格式的结果可以看到DataSnap是以JSON对象封装数据,而每一个字段则是以JSON数组来封装:

{table:[["Category",1,0,0,15,16,0,0,false,false,0,false,false],["Species Name",1,1,0,40,41,0,0,false,false,0,false,false]….

由于使用JSON格式封装数据比较简单而且在解析上也比XML容易,我们可以使用VCLJSON相关的类别很容易的解析出其中封装的数据。例如下面的ParseData从前面TableToJSON建立的JSON对象中解析其中封装的FishFacts数据表的数据:

procedure TForm1.ParseData(aJSONObj: TJSONObject);

var

iPair : Integer;

aPair : TJSONPair;

begin

for iPair := 0 to aJSONObj.Size – 1 do

begin

aPair := aJSONObj.Get(iPair);

if (aPair.JsonString.ToString <> ‘Graphic‘) then

Memo3.Lines.Add(Format(‘%s : %s’, [aPair.JsonString.ToString, aPair.JsonValue.ToString]));

end;

end;

下图即是ParseData执行后的结果:

由于DataSnap可以使用JSON封装数据,因此任何支持JSON的程序语言或是框架都可以处理DataSnap封装的数据,这也代表任何支持JSON的客户端都可以连结到Delphi/BCB XE建立的DataSnap JSON服务器并且呼叫它提供的服务。

OK,现在我们了解了如何使用DataSnap封装数据为JSON格式,因此我们现在可以很容易的把这个传统的主从架构应用程序转换为DataSnap JSON服务器,如此一来我们就提供了如何把传统主从架构架逐渐构转换为分布式JSON架构的可能性。

我们的第一步是把这个主从架构应用程序转换为DataSnap JSON服务器,要如此做我们需要让这个主从架构把数据以JSON的格式输出,以便客户端能够存取,使用。

转换主从架构应用程序为DataSnap JSON服务器

为了输出主从架构应用程序的数据,让我们首先在这个主从架构项目中建立一个Server Module,如下所示。Server Module能够自动把包含它的应用程序的数据或是服务输出给客户端使用。

由于我们现在需要把主从架构应用程序中的数据输出以便让客户端应用程序能够存取,因此我们需要把原本主从架构中数据模块中的dbExpress相关组件移动这个建立的Server Module中,接着在原本主从架构的数据模块中加入TDSServerTDSTCPServerTransportTDSServerClass组件,如下所示:

接着在TDSServerClass组件的GetClass事件处理函式中设定它的PersistentClass参数为Server Module中的TClientDataSet组件类别:

procedure TdmFishFact.dsscFishFactGetClass(DSServerClass: TDSServerClass;

var PersistentClass: TPersistentClass);

begin

PersistentClass := usmFishFact.TdssmFishFact;

end;

完成了这个简单的工作之后,现在如果我们编译并且再次执行这个主从架构应用程序,那么现在它不但仍然可以做为传统主从架构应用程序来使用,它现在也已经成为了一个DataSnap JSON服务器,现在我们就可以建立一个DataSnap客户端来连结它并且取得FishFacts的资料。

建立Delphi DataSnap客户端

建立一个VCL Form应用程序项目,在主窗体中加入如下的组件:

要连结前面的范例DataSnap服务器,我们只需要加入TSQLConnection组件,并且设定它的特性如下:

特性

特性值

Driver

Datasnap

加入一个TDSProviderConnection组件,设定它的特性值如下:

特性

特性值

SQLConnection

SQLConnection1

ServerClassName

TdssmFishFact

Name

DSPCFishFact

加入一个TClientDataSet组件,设定它的特性值如下:

特性

特性值

RemoteServer

DSPCFishFact

ProviderName

dspFishFact

在上面的设定中关键的两个设定是TDSProviderConnection组件的ServerClassName特性值必须设定为DataSnap服务器中Server Module的类别名称,以及TClientDataSet组件的ProviderName必须设定为Server Module中的TDataSetProvider组件。而在这个范例DataSnap服务器中的Server Module的类别名称就是TdssmFishFact,而Server Module中的TDataSetProvider组件名称则是dspFishFact

下图就是设定TDSProviderConnection组件画面:

而下面则是设定TClientDataSet组件的对象检视器:

设定好了之后只要再连结相关的数据感知组件就可以完成客户端应用程序了。

现在如果我们执行范例主从架构应用程序兼DataSnap服务器,再执行DataSnap客户端应用程序,那么我们可以看到类似下面的画面:

上图中范例主从架构应用程序兼DataSnap服务器执行时既是传统的主从架构,也是DataSnap服务器,因此右下方的DataSnap客户端应用程序执行之后才能够从这个主从架构应用程序兼DataSnap服务器取得FishFacts数据。

如何? 了解了dbExpress/DataSnap如何使用JSON封装数据的原理之后我们就可以容易的把它转换为DataSnap服务器。读者可以使用类似的方式在保留主从架构架构的同时又逐渐的把主从架构转换为DataSnap的分布式JSON架构。

我们下次再谈谈Delphi如何支持REST API,如此一来我们就可以让其它的JSON客户端连结并且使用DelphiDataSnap JSON服务器提供的服务,再见了。

转载于:https://www.cnblogs.com/MaxWoods/archive/2011/08/11/2135564.html

这篇关于Delphi XE程序设计系列 1-主从架构, 多层到JSON和REST的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/673582

相关文章

Python进行JSON和Excel文件转换处理指南

《Python进行JSON和Excel文件转换处理指南》在数据交换与系统集成中,JSON与Excel是两种极为常见的数据格式,本文将介绍如何使用Python实现将JSON转换为格式化的Excel文件,... 目录将 jsON 导入为格式化 Excel将 Excel 导出为结构化 JSON处理嵌套 JSON:

详解MySQL中JSON数据类型用法及与传统JSON字符串对比

《详解MySQL中JSON数据类型用法及与传统JSON字符串对比》MySQL从5.7版本开始引入了JSON数据类型,专门用于存储JSON格式的数据,本文将为大家简单介绍一下MySQL中JSON数据类型... 目录前言基本用法jsON数据类型 vs 传统JSON字符串1. 存储方式2. 查询方式对比3. 索引

C#解析JSON数据全攻略指南

《C#解析JSON数据全攻略指南》这篇文章主要为大家详细介绍了使用C#解析JSON数据全攻略指南,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、为什么jsON是C#开发必修课?二、四步搞定网络JSON数据1. 获取数据 - HttpClient最佳实践2. 动态解析 - 快速

MySQL 8 中的一个强大功能 JSON_TABLE示例详解

《MySQL8中的一个强大功能JSON_TABLE示例详解》JSON_TABLE是MySQL8中引入的一个强大功能,它允许用户将JSON数据转换为关系表格式,从而可以更方便地在SQL查询中处理J... 目录基本语法示例示例查询解释应用场景不适用场景1. ‌jsON 数据结构过于复杂或动态变化‌2. ‌性能要

Spring的RedisTemplate的json反序列泛型丢失问题解决

《Spring的RedisTemplate的json反序列泛型丢失问题解决》本文主要介绍了SpringRedisTemplate中使用JSON序列化时泛型信息丢失的问题及其提出三种解决方案,可以根据性... 目录背景解决方案方案一方案二方案三总结背景在使用RedisTemplate操作redis时我们针对

Knife4j+Axios+Redis前后端分离架构下的 API 管理与会话方案(最新推荐)

《Knife4j+Axios+Redis前后端分离架构下的API管理与会话方案(最新推荐)》本文主要介绍了Swagger与Knife4j的配置要点、前后端对接方法以及分布式Session实现原理,... 目录一、Swagger 与 Knife4j 的深度理解及配置要点Knife4j 配置关键要点1.Spri

MySQL查询JSON数组字段包含特定字符串的方法

《MySQL查询JSON数组字段包含特定字符串的方法》在MySQL数据库中,当某个字段存储的是JSON数组,需要查询数组中包含特定字符串的记录时传统的LIKE语句无法直接使用,下面小编就为大家介绍两种... 目录问题背景解决方案对比1. 精确匹配方案(推荐)2. 模糊匹配方案参数化查询示例使用场景建议性能优

mysql中的服务器架构详解

《mysql中的服务器架构详解》:本文主要介绍mysql中的服务器架构,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、mysql服务器架构解释3、总结1、背景简单理解一下mysqphpl的服务器架构。2、mysjsql服务器架构解释mysql的架

解决未解析的依赖项:‘net.sf.json-lib:json-lib:jar:2.4‘问题

《解决未解析的依赖项:‘net.sf.json-lib:json-lib:jar:2.4‘问题》:本文主要介绍解决未解析的依赖项:‘net.sf.json-lib:json-lib:jar:2.4... 目录未解析的依赖项:‘net.sf.json-lib:json-lib:jar:2.4‘打开pom.XM

k8s上运行的mysql、mariadb数据库的备份记录(支持x86和arm两种架构)

《k8s上运行的mysql、mariadb数据库的备份记录(支持x86和arm两种架构)》本文记录在K8s上运行的MySQL/MariaDB备份方案,通过工具容器执行mysqldump,结合定时任务实... 目录前言一、获取需要备份的数据库的信息二、备份步骤1.准备工作(X86)1.准备工作(arm)2.手