[DIOCP3/MyBean/QDAC开源项目] DataModule-DB例子基于MyBean的插件实例<三层数据库方案>
【说明】
这个例子答应大家很久了,一直没有时间弄,现在正式结合MyBean插件可以很方便的在客户端共享操作连接,执行数据库的各项工作,屏蔽了底层的通信解码器编码等工作,直接传递Variant,给了开发者足够的领活和自由。
【服务端使用技术】
diocp3:担当底层的通信任务。
qworker/iocpTask:担当业务逻辑的处理工作,diocp3接受数据解码后用qworker/iocpTask将数据包投递出来,这样不用占用通信线程。
qmsgpack:负责将传递的将variant数据打包到流,从流中解码成variant
dataModule:对应连接的对象,方便进行开发。
【客户端】
myBean:制作基于MyBean框架的插件,可以在MyBean的框架模块中直接使用。
RawTcpClient:用于和服务端进行通信,阻塞的tcp客户端,类似IdTcpClient的精简版本,操作容易。
【DEMO使用】
说 明:客户端依赖diocp_bean.dll插件与服务器进行数据交换,DIOCP_DBDEMO.dll是演示窗体插件的宿主。
存放路径:MyBean\samples\diocp-DBDEMO
启动服务:SERVER_EXE\diocp3Server.exe <点击start按钮启动服务>
服务器是基于DIOCP3的。可以在DIOCP3项目中找到源码[diocp3\samples\socket-Coder\DataModuleDEMO]
启动客户端:打开 [simpleConsole.exe], 依次点击下面的按钮就可以看到效果了
【DEMO说明】
服务端处理:
服务端基于DIOCP3通信,该DEMO做了简单的封装,使用户可以专注于逻辑的实现,和客户端交互使用variant类型进行。
dmMain,是和客户端连接想对应的一个对象[和客户端的连接是一对一的关系]。
我在里面稍微做了下逻辑处理的演示:
function TdmMain.Execute(pvCmdIndex: Integer; var vData: OleVariant): Boolean;
begin
case pvCmdIndex of
:
begin
// 返回服务端时间给客户端
vData := Now();
Result := true;
end;
: // 查询数据
begin
// vData 认为是传入的SQL语句
// 执行后, vData为查询的数据,可以用于对ClientData.Data的赋值 qryMain.Close;
qryMain.SQL.Clear;
qryMain.SQL.Add(vData);
qryMain.Open; vData := dspMain.Data;
Result := true;
qryMain.Close;
end;
:
begin
// vData 为执行的语句
conMain.BeginTrans;
try
qryMain.Close;
qryMain.SQL.Clear;
qryMain.SQL.Add(vData);
qryMain.ExecSQL;
conMain.CommitTrans; VarClear(vData); Result := true; except
conMain.RollbackTrans;
raise;
end;
end;
end;
end;
vData,是客户端传递过来的参数,也是返回给客户端的数据。vData是OleVariant可以容纳任何的数据<配合qmsgPack可以达到任何的数据格式要求>, 如果还达不到你的格式要求,你可以在MyClientContext的dataReceived函数做些修改,下面代码的处理过程依次是:
解压收到的数据->QmsgPack解包->取出客户端传入的参数->调用dmMain.Execute处理逻辑->qmsgPack编码数据->压缩数据->回传数据到客户端
procedure TMyClientContext.dataReceived(const pvDataObject: TObject);
var
lvMsgPack:TQMsgPack;
lvStream :TStream;
lvStream2:TMemoryStream;
vData:OleVariant;
lvResult:Boolean;
begin
lvMsgPack := TQMsgPack.Create;
try
try
if FdmMain = nil then FdmMain := TdmMain.Create(nil); lvStream := TStream(pvDataObject);
lvStream.Position := ; // upZip
TZipTools.unCompressStreamEX(lvStream); lvStream.Position := ; // unpack
lvMsgPack.LoadFromStream(lvStream); // get param
vData := lvMsgPack.ForcePath('cmd.data').AsVariant; // invoke dataModule function
lvResult := FdmMain.Execute(lvMsgPack.ForcePath('cmd.index').AsInteger, vData); // write result info
lvMsgPack.Clear;
lvMsgPack.ForcePath('__result.result').AsBoolean := lvResult;
lvMsgPack.ForcePath('__result.data').AsVariant := vData;
except
on E:Exception do
begin
lvMsgPack.Clear;
lvMsgPack.ForcePath('__result.result').AsBoolean := false;
lvMsgPack.ForcePath('__result.msg').AsString := e.Message;
end;
end; lvStream.Size := ;
lvMsgPack.SaveToStream(lvStream); lvStream.Position := ; // zipStream
TZipTools.compressStreamEX(lvStream);
lvStream.Position := ; // send to client
self.writeObject(lvStream);
finally
lvMsgPack.Free;
end; end;
客户端处理:
编译的 DLL 放到和EXE同一个目录下面就可以进行自动加载。
客户端diocp_bean工程中
library diocp_bean; uses
SysUtils,
Classes,
mybean.core.beanFactoryForNoVcl,
uRemoteServerDIOCPImpl in 'Service\uRemoteServerDIOCPImpl.pas'; {$R *.res} begin
beanFactory.RegisterBean('diocpRemoteSvr', TRemoteServerDIOCPImpl).Singleton := true;
end.
注册的diocpRemoteSvr插件实现了IRemoteServer接口和IRemoteServerConnector接口,而且该插件为单件模式。其他任何地方调用都只会产生一个连接实例。
type
IRemoteServer = interface(IInterface)
['{20B5F070-461C-41F4-AA0C-E500A36E18E4}'] /// <summary>
/// 执行远程动作
/// </summary>
function Execute(pvCmdIndex: Integer; var vData: OleVariant): Boolean; stdcall;
end; IRemoteServerConnector = interface(IInterface)
['{65931F56-07BA-42F8-BD5C-7409053F5B2C}']
procedure setHost(pvHost: PAnsiChar);
procedure setPort(pvPort:Integer);
procedure open;
end;
演示操作窗体:<服务端是13K的成语记录>
相应按钮代码:
constructor TfrmMain.Create(AOwner: TComponent);
begin
inherited;
// 通过注册的插件ID获取单实例的远程连接操作接口
FRemoteSvr := TMyBeanFactoryTools.getBean('diocpRemoteSvr') as IRemoteServer;
end; procedure TfrmMain.btnConnectClick(Sender: TObject);
begin
// 打开远程连接,如果打开过可以不用打开,其他插件中可以直接使用
(FRemoteSvr as IRemoteServerConnector).setHost(PAnsiChar(AnsiString(edtHost.Text)));
(FRemoteSvr as IRemoteServerConnector).setPort(StrToInt(edtPort.Text));
(FRemoteSvr as IRemoteServerConnector).open;
ShowMessage('open succ!');
end; procedure TfrmMain.btnOpenClick(Sender: TObject);
var
vData:OleVariant;
l : Cardinal;
begin
vData := mmoSQL.Lines.Text; l := GetTickCount; // 在远程打开SQL
if FRemoteSvr.Execute(, vData) then
begin
self.cdsMain.Data := vData;
Self.Caption := Format('query: count:%d, time:%d',
[self.cdsMain.RecordCount, GetTickCount - l]);
end;
end;
PS: 其他功能大家自己去实现,该文章写了好几个中午,希望对大家有用。
由于qdac开源项目 >=D2007,所以D7下面不能编译服务端,和diocp_bean.项目(你可以在D2007中编译好diocp_bean和服务端工程,其他插件可以在d7中完成)
-----------------------------------------------------------------------------------------------------
MyBean 轻量级配置开源框架 开源地址
https://git.oschina.net/ymofen/delphi-framework-MyBean
DIOCP3开源地址
https://github.com/ymofen/diocp3
qdac项目信息
官方网站:http://www.qdac.cc
官方QQ群:250530692
QDAC项目网址:http://sourceforge.net/p/qdac3
在线源码浏览:http://sourceforge.net/p/qdac3/code/HEAD/tree/
SVN检出地址:
http://svn.code.sf.net/p/qdac3/code/
svn://svn.code.sf.net/p/qdac3/code/
[DIOCP3/MyBean/QDAC开源项目] DataModule-DB例子基于MyBean的插件实例<三层数据库方案>的更多相关文章
- 【Github开源项目体验】- ZFile 基于 Java 的在线网盘
[Github开源项目体验]- ZFile 基于 Java 的在线网盘 在线云盘.网盘.OneDrive.云存储.私有云.对象存储.h5ai.上传.下载 date: 2022-08-02 addres ...
- BootCDN 开源项目免费 CDN 加速服务,Jquery插件库
2017-11-17 19:38:32 免费好用的在线 css js 文件引用 BootCDN - Bootstrap 中文网开源项目免费 CDN 加速服务 Jquery插件库 .
- 基于EasyDarwin开源流媒体服务器框架实现EasyNVR H5无插件直播流媒体服务器方案
背景分析 在之前的一篇博客<web无插件播放RTSP摄像机方案,拒绝插件,拥抱H5!>中,描述了实现一套H5无插件直播方案的各个组件的参考建议,又在博客<EasyNVR H5流媒体服 ...
- 开源项目kcws代码分析--基于深度学习的分词技术
http://blog.csdn.net/pirage/article/details/53424544 分词原理 本小节内容参考待字闺中的两篇博文: 97.5%准确率的深度学习中文分词(字嵌入+Bi ...
- 【开源项目系列】如何基于 Spring Cache 实现多级缓存(同时整合本地缓存 Ehcache 和分布式缓存 Redis)
一.缓存 当系统的并发量上来了,如果我们频繁地去访问数据库,那么会使数据库的压力不断增大,在高峰时甚至可以出现数据库崩溃的现象.所以一般我们会使用缓存来解决这个数据库并发访问问题,用户访问进来,会先从 ...
- 又一开源项目爆火于GitHub,Android高级插件化强化实战
一.插件化起源 插件化技术最初源于免安装运行 Apk的想法,这个免安装的 Apk 就可以理解为插件,而支持插件的 app 我们一般叫 宿主. 想必大家都知道,在 Android 系统中,应用是以 Ap ...
- (2)从实际项目谈起,基于MEF的插件框架之总体设计
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.MEF框架简介 MEF的全称是Managed Extensibil ...
- DIOCP开源项目-高效稳定的服务端解决方案(DIOCP + 无锁队列 + ZeroMQ + QWorkers) 出炉了
[概述] 自从上次发布了[DIOCP开源项目-利用队列+0MQ+多进程逻辑处理,搭建稳定,高效,分布式的服务端]文章后,得到了很多朋友的支持和肯定.这加大了我的开发动力,经过几个晚上的熬夜,终于在昨天 ...
- [转]Android开源项目收藏分享
转自:http://blog.csdn.net/dianyueneo/article/details/40683285 Android开源项目分类汇总 如果你也对开源实现库的实现原理感兴趣,欢迎 St ...
随机推荐
- iOS与H5交互
H5与App原生交互,一般会是前端页面中的JavaScript与App使用的原生开发语言的交互.技术方案应能达到以下要求: 在js与原生进行交互的时候能保证正常的正向调用逻辑返回,反向可以处理异步回调 ...
- “医疗信息化行业之中的联发科”- 我们在医疗行业中的定位及目标 想做一个面对中小企业的专业上游软件供应商 台湾联发科技颠覆掉的是一个封闭的手机产业系统 解决方案,即AgileHIS.NET数字化医院基础方案
“医疗信息化行业之中的联发科”- 我们在医疗行业中的定位及目标 我们做中国医疗信息化行业之中的联发科 ---我们在医疗行业中的定位及目标 从我个人来讲,我从2001年到现在这10年之间基本上一直在 ...
- Linux CentOS 7.x/6.x/5.x 导入epel源
How to Enable EPEL Repository for RHEL/CentOS 7.x/6.x/5.x vim /etc/yum.repos.d/CentOS-Base.repo 取消注释 ...
- spring 使用注解注入 list 或 map
1.定义一个接口或抽象类AClass 2.定义两个类实现或继承AClass,(BClass,MClass) 3.在第三个类XClass 中注入List 形如: @Autowired private L ...
- iOS 图标
iOS icon是一件很头疼的事情 大致多少张呢,忘记了,下面开发者中心给的一个文档,自己捋捋有多少张 180934.jpg 幸亏不是自己画的,不然要骂姥姥,但是多数的UI是妹子啊,让人家做人家会说: ...
- android 控件各种颜色的半透明效果配置
格式: android:background="#XXxxxxxx"(颜色可以写在color中) 说明:半透明颜色值不同于平时使用的颜色,半透明颜色值共8位,前2位是透明度,后6位 ...
- [转]Spring Boot应用的后台运行配置
转自:http://blog.didispace.com/spring-boot-run-backend/ 酱油一篇,整理一下关于Spring Boot后台运行的一些配置方式.在介绍后台运行配置之前, ...
- 在ToolStrip中加入具有更好体验性的DateTimePicker
一. 需求的产生 很多时候,需要根据年月或日期来检索数据.在我的数据库中,如果只需要以月为单位,我一般按照200801这样的格式(yyyyMM)保存为int类型.在做数据检索时,是根据工具栏 ...
- appium通过同级别(兄弟关系)元素找到元素
在做appium测试用例的时候,要获取金额值,用uiautomatorviewer查看该元素,该元素没有特别明显的个性特点,唯一有特点的定位是有content-desc值,但是该值是变动的,所以无法通 ...
- 如何利用IPv6进行远程桌面连接
如何利用IPv6进行远程桌面连接 学校是教育网,其中寝室和实验室的IPv4地址被划分成了两个VLAN,所以没法使用windows的远程连接功能.今天突然想到学校的IPv6地址可能并未划分成两个VLAN ...