【架构简介】

*本架构以delphi作为客户端,Java作为服务端,oracle作为后台数据库数据。其中delphi客户端的封装为了保持与原来的开发方式兼容都是基于TclientDataSet实现的;

*本架构选择基于阻塞模式的Indy通信套件作为通信工具;以tcp/ip作为通信协议 ,直接以流的的形式与Java服务端进行交互;

*本架构的通信过程如下:

请求开始->打包压缩请求数据->发送请求数据->delphi端阻塞等待->Java端多线程响应请求->解压解包请求数据->处理请求->打包压缩处理结果->发送处理结果->

delphi端停止阻塞接收处理结果->解压解包处理结果->显示结果

*本架构主要解决以下问题:

1.如何将Java从数据库中读出来的数据打包成TClientDataSet可以读取的数据包;要解决这个问题就需要深入了解TclientDataSet的DataPackage的xml格式。

2.如何将新增-修改-删除后的TClientDataSet数据通过Java保存到数据库中;要解决这个问题就需要深入了解TclientDataSet的Delta属性。

3.如何处理Oracle的大对象字段类型(clob或blob)。

4.delphi端如何调用Java端定义的对应的业务逻辑供。

5.Java端多用户并发处理效率问题。

6.数据包的格式定义‘打包解包‘压缩解压’加密解密问题。

1.【TclientDataSet的DataPackage格式】

TclientDataSet的DataPackage格式一般如下:

-

-

-

-

2.【DataPackage的结构分析】

整个XML定义了一个DataPacket;DataPacket包括两个部分:MetaData和RowData。MetaData包括Fields和Params,即包括数据字段定义和数据集参数。

RowData为具体记录。 下面详细分析数据字段定义的方法。

Field节点的定义主要包括:

1>attrname指FieldName

2>fieldtype指字段类型

3>width指需要宽度的字段类型的宽度或数字的有效位数;

4>decimals指小数点右边的位数;

Oracle主要字段类型具体的对应信息如下表:

_____________________________________________________________________

OracleType | fieldtype   | WIDHT | SUBTYPE      | DECIMALS | READONLY

---------------------------------------------------------------------

Char              | string       |     1            FixedChar

---------------------------------------------------------------------

Char(n)         | string       |     n            FixedChar

---------------------------------------------------------------------

Varchar(n)    | string       |      n

---------------------------------------------------------------------

Varchar2(n)  | string       |      n

---------------------------------------------------------------------

data              | dateTime |

---------------------------------------------------------------------

Number(s,p) | fixed        |      s                                       p

---------------------------------------------------------------------

Number(*,p) | fixed       |      38                                     p

----------------------------------------------------------------------

Number(s)    | fixed       |        s

----------------------------------------------------------------------

Number        | fixed       |        38

----------------------------------------------------------------------

int                | fixed        |       38

----------------------------------------------------------------------

Smallint       | fixed        |        38

----------------------------------------------------------------------

Dec(s,p)      | fixed        |         s                                     p

----------------------------------------------------------------------

Float            | R8           |

----------------------------------------------------------------------

Real             | R8           |

----------------------------------------------------------------------

其中用SubType属性来帮助决定类型。表中没有值的单元格,表示该属性没有用到。

并且DataPakage中如果想包含中文的话,记得要在第一句的中间加上encoding=”GB2312”,否则用数据库相关控件读出来的只会是乱码。

记住位置很重要的。你必须写成下面的形式:

如果写成下面的也是不满足形式良好的规范的:

3.【XML的转义字符】

在XML语言中,用实体对特殊字符进行转义.

如果在XML文档中使用类似"

所以不应该像下面那样书写代码:

if salary < 1000 then

为了避免出现这种情况,必须将字符"

if salary < 1000 then

下面是五个在XML文档中预定义好的实体:

---------------------

<  | < | 小于号

---------------------

>  | > | 大于号

---------------------

&  | & | 和

---------------------

' | ' | 单引号

---------------------

" | " | 双引号

---------------------

实体必须以符号"&"开头,以符号";"结尾。

注意: 只有"

4.【Oracle的大对象字段类型(clob和blob)】

因为TclientDataSet不支持clob和blob等大对象字段类型,所以我们要使用别的方法来实现相应的读写操作;

5.【关于TClientDataSet的Delta属性】

TClientDataSet.Delta属性表示当前操作的ClientDataSet中记录变化的信息

Delta信息可以用另外的ClientDataSet来显示;如myCDS.Data := OrgCDS.Delta

TclientDataSe的UpdateStatus属性反映当前记录的更新状态; 根据更新数据的情况其可能的值分别为:

1.新增一条记录时,在Delta中会有一条记录,标记为usInserted;

2.修改记录时,在Delta中对于同一条记录会产生且仅产生两条记录:第一条为原始记录,标记为usUnmodified,第二条只有修改过的字段才有值,标记为usModified

3.刪除记录时,在Delta中会产生一条记录,标记为usDeleted;

根据以上Delta属性就可以生成相应的更新SQL语句;

6.【数据包的格式定义】

6.1.数据包采用变长字符串的方式组织,一般由数据节点和分隔符及结束符组成。具体结构如下图:

|  数据节点  |分隔符 |  数据节点  |分隔符 |  数据节点  |分隔符 | ... |结束符 |

6.2.数据节点一般由数据长度和数据值组成。

6.3.当数据值的长度小于等于999时数据节点的组成如下图:

|数据长度 |  数据值  |分隔符 |数据长度 |  数据值    |分隔符 | ... |结束符 |

6.4.当数据值的长度大于999时数据节点的组成如下图:

|003  |数据长度的长度 |  /   |数据长度 |  数据值    |分隔符 | ... |结束符 |

6.5数据包格式定义说明:

#数据长度为数据值长度的长度字符串;

#数据长度的长度为数据值长度的长度字符串的长度字符串;

#分隔符一般为冒号;当数据值的长度大于999时分隔符为"/";

7.【JAVA应用服务器】

应用服务器最重要的就是稳定,支持高效的多用户并发处理;所以应用服务器应该是无状态的;然后是易于部署的;

java天生就是用来编写服务器的;成熟的j2ee企业级应用;丰富的开源思想;于是java就成了实现应用服务器的不二选择;

JAVA应用服务器具体实现以下功能:

1>使用一个ServerSocket监听Delphi客户端发送请求的命令;

2>针对每个Delphi客户端发送的请求开启线程解析处理请求;通过JAVA端的多线程来达到高效处理多用户并发的情况。

3>通过反射和command设计模式来分派Delphi端请求的相应的业务逻辑对象进行处理;

3>通过JDBC与Oracle数据库交互;

其实只要数据到了java端,那么只要你愿意你可以选择任意的中间件技术:weblogic,websphere,jboss等等作为应用服务器,

而尽想其提供的丰富的管理功能;

8.【接口规划】

*************************************************************************************************************************

函数功能: 发送操作命令和数据到应用服务器

函数声明: function StreamCommand(ASendText:WideString;ASendStream:TStream=nil):TStream;stdcall;external Communication;

参数说明: -------------------------------------------------------

参数名称                      描述

-------------------------------------------------------

ASendText       要发送的字节数据(一般应包括命令信息)

-------------------------------------------------------

ASendStream     要发送的内存流或文件流等数据(默认为nil)

-------------------------------------------------------

函数说明:正常返回字节流数据(可能返回空串);异常返回nil;此函数一般供DLL中的接口函数调用;

用例:Result:=StreamCommand('013SelectCommand:045SELECT * FROM CRM_CUSTOMER WHERE B_COMPANY=1 :');

这个语句的意思是发送一个查询命令到AppServer,命令的内容为SELECT * FROM CRM_CUSTOMER WHERE B_COMPANY=1;

如果命令能正确执行,那么AppServer会把查询的结果打包发送到客户端,以字节流的形式返回.

**************************************************************************************************************************

函数功能: 查询单个数据集

函数声明: function SelectCommand(ACDS: TClientDataSet;const ASelectText: string):Boolean;stdcall;external Communication;

参数说明: -------------------------------------------------------

参数名称                      描述

-------------------------------------------------------

ACDS           存放查询结果集的TClientDataSet

-------------------------------------------------------

ASelectText     要发送的单条查询语句

-------------------------------------------------------

函数说明: 成功返回[true](包括只有数据元的空数据集);失败返回[false]

用例: Result:=SelectCommand(cdsTemp,'SELECT * FROM CRM_CUSTOMER');这个语句的意思是:

发送一个查询语句到AppServer,如果命令能正确执行,那么AppServer会把查询的结果集打包发送到客户端事先创建好的cdsTemp中.

*************************************************************************************************************************************

函数功能:同时查询多个数据集

函数声明:function SelectCommands(ACDS:Array of TClientDataSet;const ASelectText: TStringList):Boolean;stdcall;external Communication;

参数说明:-------------------------------------------------------

参数名称                      描述

-------------------------------------------------------

ACDS           存放查询结果集的多个TClientDataSet列表

-------------------------------------------------------

ASelectText     要发送的多条查询语句列表

-------------------------------------------------------

函数说明:成功返回[true](包括只有数据元的空数据集);失败返回[false]

用例:

var

sSql:string;

sList:TStringList;

cdsTemp1,cdsTemp2,cdsTemp3:TClientDataSet;

begin

try

cdsTemp1:=TClientDataSet.Create(nil);

cdsTemp2:=TClientDataSet.Create(nil);

cdsTemp3:=TClientDataSet.Create(nil);

sList:=TStringList.Create;

try

sSql:='SELECT * FROM Table1';

sList.Add(sSql);

sSql:='SELECT * FROM Table2';

sList.Add(sSql);

sSql:='SELECT * FROM Table3';

sList.Add(sSql);

//把第一条查询语句的结果集存放到cdsTemp1,把第二条查询语句的结果集存放到cdsTemp2,依次类推存放顺序

SelectCommands([cdsTemp1,cdsTemp2,cdsTemp3],sList);

finally

if Assigned(cdsTemp1) then FreeAndNil(cdsTemp1);

if Assigned(cdsTemp2) then FreeAndNil(cdsTemp2);

if Assigned(cdsTemp3) then FreeAndNil(cdsTemp3);

if Assigned(sList) then FreeAndNil(sList);

end;

except

end;

end;

**************************************************************************************************************************

函数功能: 发送一条或多条update or insert or delete类型的SQL语句到应用服务器执行

函数声明: function ExecuteCommands(const AExecuteText: TStringList): integer;stdcall;external Communication;

参数说明: -------------------------------------------------------

参数名称                      描述

-------------------------------------------------------

AExecuteText     AppServer能解析的SQL语句

-------------------------------------------------------

函数说明: 正常返回0;异常返回非0;本函数主要供ApplyUpdates函数调用;

用例:

**************************************************************************************************************************

函数功能: 发送一条update or insert or delete类型的SQL语句到应用服务器执行

函数声明: function ExecuteCommand(const ACommandText:WideString):integer; stdcall;external Communication;

参数说明: -------------------------------------------------------

参数名称                      描述

-------------------------------------------------------

ACommandText     要执行的SQL语句

-------------------------------------------------------

函数说明: 正常返回0;异常返回非0;

用例:

**************************************************************************************************************************

函数功能: 根据数据集列表的修改信息自动生成相应的SQL语句

函数声明: function CreateUpdates(const ATableNames: array of string ;ACDS:array of TClientDataSet;var sSqlList:string): Boolean;stdcall; external Communication;

参数说明: -------------------------------------------------------

参数名称                      描述

-------------------------------------------------------

ATableNames     数据集列表对应的表名列表

-------------------------------------------------------

ACDS            修改过的数据集列表

-------------------------------------------------------

sSqlList         存放对应生成的SQL语句

-------------------------------------------------------

函数说明: 成功返回[true];失败返回[false]

本函数根据数据集中的修改信息自动生成Insert,Update,Delete类型的多条SQL语句.

用例: 1>Result:=CreateStatement(['TableName1','TableName2','TableName3','TableName4'],[cds1,cds2,cds3,cds4]); 或者

2>Result:=CreateStatement(['TableName1'],[cds1]);

本用例会根据数据集列表中每个数据集的修改信息自动生成相应的SQL语句,这样就完成了操作界面到SQL语句之间的直接映射.

**************************************************************************************************************************

函数功能: 更新多个数据集

函数声明: function ApplyUpdates(const ATableNames: array of string ; ACDS:array of TClientDataSet): Boolean;stdcall; external Communication;

参数说明: -------------------------------------------------------

参数名称               描述

-------------------------------------------------------

ACDS           要更新的数据集列表

-------------------------------------------------------

ATableNames     要更新的表名列表

-------------------------------------------------------

函数说明: 成功返回[true];失败返回[false]

表名列表与数据集列表应该一一对应

用例: Result:=ApplyUpdates(['TableName1','TableName2','TableName3','TableName4'],

[cds1,cds2,cds3,cds4]);

本用例会根据数据集列表中每个数据集的修改信息自动生成相应SQL语句,然后把所有的SQL语句一起发送到AppServer进行事务处理.

*****************************************************************************************************************

函数功能: 保存Oracle大对象字段类型(clob或blob)

函数声明: function SaveBlob(SqlText:WideString;LobID:WideString;LobContent:TStream):integer;stdcall; external Communication;

参数说明: -------------------------------------------------------

参数名称               描述

-------------------------------------------------------

SqlText           保存前要执行的SQL语句

-------------------------------------------------------

LobID             包含Oracle大对象字段类型的记录的ID

-------------------------------------------------------

LobContent        要保存的Oracle大对象字段类型的内容

-------------------------------------------------------

函数说明: 成功返回[0];失败返回[非0]

用例:

*****************************************************************************************************************

函数功能: 显示Oracle大对象字段类型(clob或blob)

函数声明: function SelectBlob(LobID:WideString):TStream;stdcall; external Communication;

参数说明: -------------------------------------------------------

参数名称               描述

-------------------------------------------------------

LobID         包含Oracle大对象字段类型的记录的ID

-------------------------------------------------------

函数说明: 成功返回Oracle大对象字段类型对应的流;失败返回[nil];

用例:

9.【扩展功能】

1>客户端数据缓存机制保证运行的高效性:客户端可以缓存大量的客户端数据,并提供了一定程度的离线操作功能;

这样在提高户交互效率的同时,减少网络数据通讯量;还能降低服务器的负载。

2>客户端自动更新机制:便于客户端的部署和版本更新

3>权限管理:包括功能权限和数据权限;

4>客户端采用模块化(DLL)设计保证系统的可扩展性;

5>运行时自定义报表;

6>JAVA应用服务器可采用数据库连接池来提高访问效率;

java delphi 三层_三层架构delphi+Java+Oracle模式的实现相关推荐

  1. java基础巩固_(一)Java基础巩固

    Java的三种技术架构: JAVAEE:Java Platform Enterprise Edition,开发企业环境下的应用程序,主要针对web程序开发: JAVASE:Java Platform  ...

  2. java python算法_用Python,Java和C ++示例解释的排序算法

    java python算法 什么是排序算法? (What is a Sorting Algorithm?) Sorting algorithms are a set of instructions t ...

  3. java 判断类型_如何快速入门Java编程学习(干货)

    一.初识Java 1.生活中的程序: 从起床到教室上课的过程 穿衣打扮>起床>洗漱>出宿舍>>吃早餐>到教室 按照特定的顺序去完成某一件事的过程我们叫做生活中的程序 ...

  4. 支持java虚拟主机_为何缺乏支持Java的虚拟主机

    现在很多站长们,都青睐于香港虚拟主机建站.现在常见的是asp和PHP的程序空间很多,但是Java的少之又少,下面小编我给大家聊一聊! 一.香港Java虚拟主机成本高 使用Java程序建站,就必须要用支 ...

  5. java必读书籍_最佳5本Java性能调优书籍–精选,必读

    java必读书籍 为什么Java开发人员应该阅读有关性能调优的书? 当我很久以前第一次面对这个问题时,我以为以后会做,但是我很长一段时间都没有回过头来. 仅当我在用Java编写的任务关键型服务器端财务 ...

  6. delphi7aes加密解密与java互转_跨语言(java vs python vs nodejs)的RSA加解密问题探讨

    多次被问到这样的问题: java服务端的rsa加密操作已经完成,返回一个16进制的字符串给python平台,但是在python进行私钥解密的时候发现行不通.... 前端python加密,后端用java ...

  7. java logger使用_这才是JAVA中打印日志的正确姿势

    作者:lrwin 原文链接:http://t.cn/E9BkD7a 使用slf4j 1. 使用门面模式的日志框架,有利于维护和各个类的日志处理方式统一 2. 实现方式统一使用: Logback框架 打 ...

  8. java毕业论文云笔记_开题报告基于Java云笔记管理系统.doc

    开题报告基于Java云笔记管理系统 淮 阴 工 学 院 毕业设计(论文)开题报告 学 生 姓 名:秦鹏学 号:1131301136专 业:计算机与软件工程学院设计(论文)题目:基于Java云笔记:徐成 ...

  9. java 下载加速_一种基于Java的大文件下载加速方法与流程

    本发明涉及java/多线程技术领域,涉及一种加速文件下载装置,具体提供一种基于java的大文件下载加速方法. 背景技术: 现有的常用下载方式是基于浏览器的单线程下载.这种单线程下载的方式,是通过htt ...

最新文章

  1. 自定义字体——自带常见图标,以后就省的切图了
  2. document对象详解
  3. 第 16 章 MySQL Cluster
  4. shell中单引号的嵌套
  5. “AlphaGo之父”获最新一届ACM计算奖
  6. C++中最好不要在构造函数和析构函数中调用虚函数
  7. 微机总线地址,物理地址 ,虚拟地址
  8. Visual Studio 2017全面上市
  9. mysql 跨域_解决go echo后端处理跨域的两种操作方式
  10. numpy合并两个ndarry或多个
  11. 如何让地面不起灰_解决水泥地面起灰的省钱方法
  12. 保存数组类型数据_「Java」基础12:什么叫数组?
  13. kali linux捉肉鸡教程,使用Kali中的Metasploit生成木马控制Windows系统
  14. ibm x3850装oracle,Oracle数据库服务器:x3850 X5
  15. Qt Quick综合实例之文件查看器
  16. 服务器lsass状态代码c0000005,lsass.exe是什么进程?Win7系统提示Lsass.exe系统错误的原因及解决方法...
  17. vs2013编译 解决 error c1083 无法打开文件 'winsock2.h' 等问题记录
  18. iOS组件化:从零开始搭设私有库
  19. linux系统bcast,Linux系统下取IP地址的几种方法
  20. 数据分析中,还有哪些好用实用的方法论?

热门文章

  1. 绝了!电容这样理解真的简单!
  2. c语言多线程 视频教程,如何用C语言实现多线程
  3. 2016php技术面试题,一个php的面试题,大家看看
  4. tpcc mysql下载_tpcc-mysql 试用
  5. python random包含尾部吗_你真的了解Python的random模块吗?
  6. upload-labs_pass14_pass15_pass16_图片马的制作_结合文件包含漏洞_getimagesize_exif_imagetype
  7. [地球人]BlogEngine.NET[Appwo.com版]+采集器
  8. tomcat多个端口对应多个web应用
  9. Apache和Nginx的区别
  10. Django的自带认证系统——auth模块