开发DataSnapserver
在上次的文章中讨论了怎样把传统的Delphi 主从架构应用程序逐渐转换为DataSnap JSONserver。在本篇文章中让我们正式讨论怎样使用Delphi XE开发DataSnap/RESTserver。因为这当中牵涉到许多的技术,因此我们将花数篇的篇幅来讨论。
如今就让我们从DataSnap/RESTserver開始。
开发DataSnapserver
Delphi XE版的DataSnap同意开发者同一时候在DataSnapserver中实作RESTful架构的server,如此一来DataSnapserver不但能够在网络内
部做为多层的服务server,也能够让网络外部的client使用REST的方式来存取服务。 要在Delphi XE中建立DataSnap/RESTserver,请点选Files|New菜单,在DataSnap Server选项中选择DataSnap
Server图像。例如以下图所看到的:
Delphi XE提供三种不同的server型态。各自是以VCL应用程序实作的server,实作为主控程序的server以及实作成Windows服务应用程序的server。开发者可依据自己的需求选择建立适当的server型态。在本篇文章中让我们建立VCL应用程序型态的server:
点选Nextbutton之后DataSnap精灵会例如以下图询问须要支持的通讯协议。是否使用安全验证功能以及是否要预先建立范例服务方法,让我们点选下方的Select
All以选择建立全部的功能。例如以下图所看到的:
点选Nextbutton,DataSnap精灵会例如以下图询问TCP/IP和HTTP使用的通信埠,内定上TCP/IP使用211而HTTP则使用
8080,开发者可依据自己的需求设定这两个通信埠,或是点选Find Open Portbutton让DataSnap精灵帮忙搜寻可使用的通信埠:
接着DataSnap精灵会询问开发者实作服务方法的类别,开发者能够选择实作于TComponent类别,TDataModule类别或是TDSServerModule类别,在本文章中我们选择实作于TDSServerModule:
点选Finishbutton之后,Delphi XE便会建立相相应的项目。我们开启ServerContainerUnit的话就能够看到当中包括了例如以下组件,当中的
TDSServer,TDSTCPServerTransport以及TDSServerClass类别组件在Delphi 2010中就存在了,新的TDSHTTPService类别组件则提供了HTTP/HTTPS通讯协议的支持,而新的
TDSAuthenticationManager类别组件则提供安全验证功能,在稍后的文章中我们会说明怎样使用它。
如今DataSnap精灵会在项目的ServerMethodsUnit程序单元中产生两个范例方法,EchoString和ReverseString。
如今让我们在这个程序单元中增加一个新的服务方法『取得部落格文章名称』。例如以下所看到的:
public
{ Public declarations }
function EchoString(Value: string): string;
function ReverseString(Value: string): string;
function
取得部落格文章名称 : TJSONArray;
接着实作『取得部落格文章名称』方法,例如以下所看到的:
function TServerMethods2.取得部落格文章名称:
TJSONArray;
begin
Result := TJSONArray.Create;
Result.AddElement(TJSONString.Create(‘Delphi XE程序设计系列
1-主从架构, 多层到JSON和REST’));
Result.AddElement(TJSONString.Create(‘从原生API到REST
API – 使用C++Builder XE开发REST应用程序’));
Result.AddElement(TJSONString.Create(‘Delphi XE程序设计系列
2-DataSnap/RESTserver’));
end;
『取得部落格文章名称』方法建立TJSONArray对象,而且把三篇文章名称以TJSONString对象储存在元素中。最后回传TJSONArray对象给client。
最后开启ServerMethodsUnit程序单元的设计接口,在当中放入dbExpress组件以存取储存在MS SQL
Server数据库中的范例数据表FishFacts,稍后我们将说明这个DataSnap/RESTserver怎样同一时候以传统DataSnap的架构让用户端使用dbExpress组件存取数据。以及怎样以REST的架构让client存取它提供的服务。
如今编译而且运行这个DataSnap/RESTserver。
因为如今这个server同一时候可提供DataSnap和RESTserver的功能。因此如今我们能够试着使用浏览器来使用存取这个server的服务。
让我们使用以下的URI来呼叫『取得部落格文章名称』方法:
http://localhost:8085/datasnap/rest/TServerMethods2/取得部落格文章名称
我们能够在下图中看到,我们果然能够在浏览器中使用上面的URI成功的呼叫server的服务:
并且我们从上图中能够清楚的看到回传的结果是使用JSON格式封装的JSON数组,每个数组元素是Unicode编码的JSON字符串
。
连结使用DataSnapserver
如今让我们建立一个clientVCL应用程序项目。放入TSQLConnection组件。然后设定它的特性值例如以下(此时DataSnap/RESTserver必须是在运行状态):
特性 |
特性值 |
Driver |
Datasnap |
Connected |
True |
点选鼠标右键,选择建立『Generate DataSnap Client Classes』菜单,例如以下所看到的,再把产生的程序单元储存为ServerProxy程序单元。
然后在主窗口中放入例如以下的dbExpress和VCL组件:
设定TDSProviderConnection组件的特性值例如以下:
特性 |
特性值 |
SQLConnection |
SQLConnection1 |
ServerClassName |
TServerMethods2 |
再设定TClientDataSet的特性值例如以下:
特性 |
特性值 |
RemoteServer |
DSProviderConnection1 |
Provider |
dspFishFacts |
当我们在设定TClientDataSet的Provider特性值时,client应用程序就会连结到DataSnap/RESTserver而且显示ServerMethodsUnit程序单元中输出的TDataSetProvider组件。
让我们在『更新』button的OnClick事件处理函式中撰写例如以下的程序代码:
procedure TForm10.Button3Click(Sender: TObject);
begin
if (cdsFishFacts.ChangeCount > 0) then
cdsFishFacts.ApplyUpdates(0);
end;
编译而且运行client应用程序,我们就能够看到类似例如以下的画面:
DataSnap/RESTserver就如同曾经的DataSnap/Midasserver一样能够提供二层和多层的开发架构,client应用程序也能够使用dbExpress组件来异动DataSnap/RESTserver中的数据。
如今我们已经展示了这个DataSnap/RESTserver能够同一时候使用二层/多层和REST的架构来使用它。
如今再让我们看看怎样在client使用程序代码来存取server的服务。在前面我们已经藉由TSQLConnection组件自己主动产生了ServerProxy程序单元,假设我们开启ServerProxy,便会看到以下的类别宣告:
TServerMethods2Client = class(TDSAdminClient)
private
FEchoStringCommand: TDBXCommand;
FReverseStringCommand: TDBXCommand;
F取得部落格文章名称Command: TDBXCommand;
public
constructor Create(ADBXConnection: TDBXConnection); overload;
constructor Create(ADBXConnection: TDBXConnection; AInstanceOwner: Boolean); overload;
destructor Destroy; override;
function EchoString(Value: string): string;
function ReverseString(Value: string): string;
function
取得部落格文章名称: TJSONArray;
end;
假设我们观察ServerProxy程序单元中的『取得部落格文章名称』方法,就能够看到它也使用dbExpress技术来存取server的服务:
function TServerMethods2Client.取得部落格文章名称:
TJSONArray;
begin
if F取得部落格文章名称Command = nil
then
begin
F取得部落格文章名称Command := FDBXConnection.CreateCommand;
F取得部落格文章名称Command.CommandType
:= TDBXCommandTypes.DSServerMethod;
F取得部落格文章名称Command.Text :=
‘TServerMethods2.取得部落格文章名称’;
F取得部落格文章名称Command.Prepare;
end;
F取得部落格文章名称Command.ExecuteUpdate;
Result := TJSONArray(F取得部落格文章名称Command.Parameters[0].Value.GetJSONValue(FInstanceOwner));
end;
因此在client。我们能够使用以下的程序代码藉由ServerProxy程序单元中的『取得部落格文章名称』方法来取得部落格文章信息:
procedure TForm10.Button1Click(Sender: TObject);
var
aServer: TServerMethods2Client;
ja : TJSONArray;
iIndex: Integer;
begin
aServer := TServerMethods2Client.Create(Self.SQLConnection1.DBXConnection);
try
ja := aServer.取得部落格文章名称;
for iIndex := 0 to ja.Size – 1 do
ListBox1.Items.Add(ja.Get(iIndex).ToString);
finally
aServer.Free;
end;
end;
下图是client应用程序运行上面程序代码的结果:
可是除了dbExpress技术之外。我们也能够使用REST。JavaScript等技术来存取server服务,由于这个server就是一个RESTserver。因此让我们更深入的讨论一下怎样在client自己主动产生程序代码来支持REST和JavaScript等技术。
client程序代码产生器
DataSnap XE版眼下可自己主动产生四种client程序代码让不同的client可以连结和使用DataSnap/RESTserver。这四种是:
DataSnap XE支持的四种client程序代码 |
说明 |
Delphi DBX |
使用dbExpress技术呼叫DataSnap/RESTserver的clientDelphi程序代码 |
C++Builder DBX |
使用dbExpress技术呼叫DataSnap/RESTserver的clientC/C++程序代码 |
Java Script REST |
使用REST/JSON技术呼叫DataSnap/RESTserver的clientJavaScript程序代码 |
Delphi REST |
使用REST/JSON技术呼叫DataSnap/RESTserver的clientDelphi程序代码 |
我们可以轻易的使用以下的程序代码来取得眼下可以产生的client程序代码:
procedure TForm10.ListRegisteredWriter;
var
sa : TDBXStringArray;
iIndex : Integer;
begin
sa := DSProxyWriter.TDSProxyWriterFactory.RegisteredWritersList;
for iIndex := 0 to Length(sa) – 1 do
ComboBox1.Items.Add(sa[iIndex]);
ComboBox1.ItemIndex := 0;
end;
DSProxyWriter程序单元中
TDSProxyWriterFactory类别的类别方法RegisteredWritersList能够回传眼下注冊的client程序代码种类,眼下上表列出的四种client程序代码产生器分别位于DSProxyDelphi,DSProxyCpp, DSProxyJavaScript和DSProxyDelphiRest程序单元中。
当我们要产生上表四种client程序代码以呼叫特定的DataSnap/RESTserver时,我们须要使用IDSProxyMetaDataLoader接口以及TDSProxyGenerator类别。
IDSProxyMetaDataLoader接口是由TDSProxyMetaDataLoader类别实作的,我们能够使用
TDBXConnection对象建立TDSProxyMetaDataLoader对象。取得它的IDSProxyMetaDataLoader接口, 再建立TDSProxyGenerator对象。设定要产生的特定client程序代码目标。最后呼叫TDSProxyGenerator对象的Write方法,
如此一来DataSnap框架就会自己主动产生连结特定DataSnap/RESTserver的client程序代码。
比如,如今让我们来看看怎样可以要求DataSnap框架自己主动产生Delphi REST或是JavaScript的client程序代码。
以下的程序代码首先呼叫GetMetaDataLoader方法取得IDSProxyMetaDataLoader接口,再呼叫GenerateFile藉由IDSProxyMetaDataLoader接口产生使用者特定的client程序代码:
procedure TForm10.Button2Click(Sender: TObject);
var
LMetaDataLoader: IDSProxyMetaDataLoader;
begin
LMetaDataLoader := GetMetaDataLoader;
GenerateFile(LMetaDataLoader);
ShowGeneratedFiles;
end;
GetMetaDataLoader方法藉由程序中的
TSQLConnection的TDBXConnection对象建立TDSProxyMetaDataLoader对象,再回传 TDSProxyMetaDataLoader对象实作的IDSProxyMetaDataLoader接口:
function TForm10.GetMetaDataLoader : IDSProxyMetaDataLoader;
begin
Result := TDSProxyMetaDataLoader.Create(
function: TDBXConnection
begin
OpenConnection;
Result := SQLConnection1.DBXConnection;
end,
procedure(AConnection: TDBXConnection)
begin
SQLConnection1.Close;
end
);
end;
而GenerateFile方法先建立 TDSProxyGenerator对象,设定它的Writer特性值为稍后使用者在程序中设定的特定的client程序代码的名称。比如是『Delphi
DBX』产生使用dbExpress技术的client程序代码,或是『Java Script REST』产生使用REST/JSON的JavaScript程序代码,最后呼叫Write方法实际的产生client程序代码:
procedure TForm10.GenerateFile(AMetaDataLoader: IDSProxyMetaDataLoader);
var
LProxyGenerator: TDSProxyGenerator;
begin
LProxyGenerator := TDSProxyGenerator.Create(nil);
try
LProxyGenerator.Writer := ComboBox1.Text;
LProxyGenerator.TargetUnitName := ‘GeneratedServerProxy’;
LProxyGenerator.ExcludeMethods :=
』;
LProxyGenerator.ExcludeClasses :=
』;
LProxyGenerator.TargetDirectory := ‘.’;
LProxyGenerator.OnCreatingFiles := ACreatingFiles;
LProxyGenerator.OnCreatedFiles := ACreatedFiles;
LProxyGenerator.Write(AMetaDataLoader);
finally
LProxyGenerator.Free;
end;
end;
如今假设我们运行client应用程序。能够看到例如以下的画面,在以下中我选择产生Delphi REST的client程序代码:
那么这个范例client应用程序便会自己主动产生使用REST的clientDelphi程序代码,比如它产生的呼叫范例DataSnap/RESTserver的『取得部落格文章名称』方法的程序代码例如以下:
function TServerMethods2Client.取得部落格文章名称(const
ARequestFilter: string): TJSONArray;
begin
if F取得部落格文章名称Command = nil
then
begin
F取得部落格文章名称Command := FConnection.CreateCommand;
F取得部落格文章名称Command.RequestType
:= ‘GET’;
F取得部落格文章名称Command.Text :=
‘TServerMethods2.取得部落格文章名称’;
F取得部落格文章名称Command.Prepare(TServerMethods2_取得部落格文章名称);
end;
F取得部落格文章名称Command.Execute(ARequestFilter);
Result := TJSONArray(F取得部落格文章名称Command.Parameters[0].Value.GetJSONValue(FInstanceOwner));
end;
看到如今它是使用HTTP的Get命令,藉由REST呼叫惯例来呼叫DataSnap/RESTserver的『取得部落格文章名称』方法了。
假设我是选择产生Java Script REST。
那么以下就是DataSnap框架自己主动产生的clientJavaScript程序代码:
/*
* @return result – Type on server: TJSONArray
*/
this.取得部落格文章名称 = function()
{
var returnObject = this.executor.executeMethod(‘取得部落格文章名称’,
『GET』, [], arguments[0], true, arguments[1], arguments[2]);
if (arguments[0] == null) {
if (returnObject != null && returnObject.result != null && isArray(returnObject.result)) {
var resultArray = returnObject.result;
var resultObject = new Object();
resultObject.result = resultArray[0];
if (returnObject.cacheId != null && returnObject.cmdIndex != null) {
resultObject._cacheId = returnObject.cacheId;
resultObject._cmdIndex = returnObject.cmdIndex;
}
return resultObject;
}
return returnObject;
}
};
this.取得部落格文章名称_URL = function()
{
return this.executor.getMethodURL(『取得部落格文章名称』,
『GET』, [], arguments[0])[0];
};
}
var JSProxyClassList = {
『TServerMethods2″: ["DSServerModuleCreate","DSServerModuleDestroy","EchoString","ReverseString","取得部落格文章名称"]
};
最后我试着同一时候使用Delphiclient应用程序以及浏览器两个不同的client来呼叫和使用范例DataSnap/RESTserver,看起来一切都很的美好:
当然,我也能够使用纯粹的Webclient应用程序来呼叫和使用范例DataSnap/RESTserver。比例如以下图就是我使用VCL
For Web XI来使用范例DataSnap/RESTserver的结果。全部的服务仍然工作良好:
DataSnap XE版藉由扩充多层架构到REST和JSON的技术领域。让DataSnap
XE瞬间突破了平台的限制。同意Delphi,C/C++Builder,JavaScript,PHP,Ruby和移动设备等各种client可以使用它的服 务,再次赋予了DataSnap框架无限的发展潜能。
好了,时间已晚,我们也下次再见了。
开发DataSnapserver的更多相关文章
- 避免重复造轮子的UI自动化测试框架开发
一懒起来就好久没更新文章了,其实懒也还是因为忙,今年上半年的加班赶上了去年一年的加班,加班不息啊,好了吐槽完就写写一直打算继续的自动化开发 目前各种UI测试框架层出不穷,但是万变不离其宗,驱动PC浏览 ...
- App开发:模拟服务器数据接口 - MockApi
为了方便app开发过程中,不受服务器接口的限制,便于客户端功能的快速测试,可以在客户端实现一个模拟服务器数据接口的MockApi模块.本篇文章就尝试为使用gradle的android项目设计实现Moc ...
- 使用HTML5开发Kinect体感游戏
一.简介 我们要做的是怎样一款游戏? 在前不久成都TGC2016展会上,我们开发了一款<火影忍者手游>的体感游戏,主要模拟手游章节<九尾袭来 >,用户化身四代,与九尾进行对决, ...
- Android SwipeRefreshLayout 下拉刷新——Hi_博客 Android App 开发笔记
以前写下拉刷新 感觉好费劲,要判断ListView是否滚到顶部,还要加载头布局,还要控制 头布局的状态,等等一大堆.感觉麻烦死了.今天学习了SwipeRefreshLayout 的用法,来分享一下,有 ...
- Android Studio配置 AndroidAnnotations——Hi_博客 Android App 开发笔记
以前用Eclicps 用习惯了现在 想学学 用Android Studio 两天的钻研终于 在我电脑上装了一个Android Studio 并完成了AndroidAnnotations 的配置. An ...
- Android请求网络共通类——Hi_博客 Android App 开发笔记
今天 ,来分享一下 ,一个博客App的开发过程,以前也没开发过这种类型App 的经验,求大神们轻点喷. 首先我们要创建一个Andriod 项目 因为要从网络请求数据所以我们先来一个请求网络的共通类. ...
- Angular2入门系列教程1-使用Angular-cli搭建Angular2开发环境
一直在学Angular2,百忙之中抽点时间来写个简单的教程. 2016年是前端飞速发展的一年,前端越来越形成了(web component)组件化的编程模式:以前Jquery通吃一切的田园时代一去不复 ...
- 构建一个基本的前端自动化开发环境 —— 基于 Gulp 的前端集成解决方案(四)
通过前面几节的准备工作,对于 npm / node / gulp 应该已经有了基本的认识,本节主要介绍如何构建一个基本的前端自动化开发环境. 下面将逐步构建一个可以自动编译 sass 文件.压缩 ja ...
- 读书笔记:《HTML5开发手册》--HTML5新的结构元素
读书笔记:<HTML5开发手册> (HTML5 Developer's CookBook) 虽然从事前端开发已有很长一段时间,对HTML5标签也有使用,但在语义化上面理解还不够清晰.之前在 ...
随机推荐
- 如何扒取一个网站的HTML和CSS源码
一个好的前端开发,当看到一个很炫的页面的时候会本着学习的心态,想知道网站的源码.以下内容只是为了大家更好的学习,拒绝抄袭,支持正版. 1 首先我们要有一个chrome浏览器 2 在本地创建相关文件夹 ...
- drupal 8——在CKEditor中导入video media时添加caption会导致video缩小至消失
在CKEditor中,我点击media browser,选择video型的media,并在caption中输入video的名字.当我保存后发现在前台页面的video消失了,只留下video的名字,点击 ...
- 第一次android混淆实战
第一次混淆,主要是因为引用本地第三方jar包的问题.虽然说本地第三方jar包自动避免混淆,但一些本地第三方jar包下的一些包要避免混淆.比如: 文中的com.org 这些包名都要避免混淆. 下面是我用 ...
- Win32基础知识整理
1.定义字符串 在资源新建String table,增加新字符串: (win32加载) TCHAR tcIDName[255]=_T(""); LoadString(hInstan ...
- jQuery——属相操作
属性获取:attr(属性名), 属性设置:attr(属性名,具体值) 移除属性:removeAttr(属性名) 特殊情况:prop(属性名).prop(属性名,具体值):表单中状态属性checked. ...
- SQL基本操作——UNION
UNION 操作符:用于合并两个或多个 SELECT 语句的结果集.请注意,UNION 内部的 SELECT 语句必须拥有相同数量的列.列也必须拥有相似的数据类型.同时,每条 SELECT 语句中的列 ...
- 集合Set、List、Map的遍历方法
package com.shellway.javase; import java.util.ArrayList; import java.util.Collection; import java.ut ...
- Java中内部类详解—匿名内部类
什么是内部类? 将一个类A定义在另一个类B里面,里面的那个类A就称为内部类,B则称为外部类. 成员内部类 定义在类中方法外的类. 定义格式: class 外部类 { class 内部类{ } } ...
- Idea 创建maven web项目(手工创建)
参考链接:https://www.cnblogs.com/justuntil/p/7511787.html 话不多说,直接上图: 1.创建maven项目 创建项目完成,项目结构如下: 2.项目部署配置 ...
- 刽子手游戏(Hangman Judge, UVa 489)
刽子手游戏其实是一款猜单词游戏,游戏规则是这样的:计算机想一个单词让你猜,你每次可以猜一个字母.如果单词里有那个字母,所有该字母会显示出来:如果没有那个字母,则计算机会在一幅“刽子手”画上填一笔.这幅 ...