三层程序一直在讨论,但无论我看哪个三层,都觉得不对劲,唯一对劲的就是 WebService实现的三层。三层程序中,我们有一个数据管理层,这一层大家都交给DBMS了,如Sqlserver,Oracle.一层是业务逻辑,这一层我们要考虑,要编码的。还有一层是表现层。三层应是相互独立的。也就是说,逻辑层不知道下面的表现层是用delphi的win32表现还是Web形式的表现,反正只要符合一定的规则,就可以交流。逻辑层负责逻辑完了,与数据库交流,不管数据是什么系统,他都要能交流得上(比如用标准sql与数据库系统连接)这样一来,逻辑层只好用WebService了。
各位,我理解的三层与大众的理解不一定是一致的,这只是我的想法,欢迎拍砖。Ps,拍完砖顺便告诉我一下一直困扰我的 WebService 执行验证,大家是怎么解决的。。
各位,我理解的三层与大众的理解不一定是一致的,这只是我的想法,欢迎拍砖。Ps,拍完砖顺便告诉我一下一直困扰我的 WebService 执行验证,大家是怎么解决的。。
解决方案 »
- TAnimate 在Win7下的显示问题
- TCheckListBox 全部选中
- delphi 自带得 Panel可关闭可停靠demo 是哪个目录?
- TreeView排序
- 怎样可以取得delphi报告的错误信息?
- 问一个简单的SQL问题。
- 高分求解!!!多层应用系统的master/detail数据库,远程数据模块的设置问题!
- 如何调用winapi函数
- 关于语音控件CTTS1.0?
- 高难问题:如何使“TCP/IP配置”恢复到Windows安装完成时的默认状态?
- 求助关于SQL Server 2005 数据库备份还原用Restore Database不能还原问题
- 【100】Delphi获取自身文件名
webservice只是其中的一个组合(xml@http)而已我觉得xml分析起来开销太大,改为ini:
http://blog.csdn.net/sz_haitao/archive/2009/09/10/4539228.aspx
如果用Delphi这破玩意儿写服务器端,线程池、连接池、ORM、SPRING这些都没有(难到不难,还要自己写,自己压力测,够你折腾一段时间的、除非你的项目很简单,不需要考虑以后的维护成本,可以简单地在逻辑层直接写SQL),而且一不小心有个内存泄露,那整个服务器就挂了,别在天真地找到一篇关于Delphi三层的文章就认为你能用它做出很好效果的三层!Delphi开发三层有成功的案例没?有,有多少,不知道!对于答案为"有"的是有前提的,公司必须要有几个牛人历经一年半载的来搭框架,反复测试,在实际上还要不断修改!对于一些动辄就三层三层的贴子,真TMD好笑!
总之来讲:用JAVA写WEBSERVICE,把功能粒度分合适些(千万别搞得有N个service interface),让D端调用就行了!这样整个系统结构就比较松散了!
对于1楼朋友总是把ini吹得神乎其神的,INI这个东西解析是不慢,语意表达上是不是要差一些!更重要的是需要把数据传上来,反序列化后,就是业务对象了,您这个是不是还要写helper类啊,可够累的...
您如何把下面的树型结构用ini表示?<csdn>
<develop tool>
<XXX>
<YYY>
</YYY>
</XXX>
</develop tool>
</csdn>
delphi写isapi,跑在iis下,网络通讯就完全免掉了
所以,瞎费劲的关键在于瞎!不知道怎么借助现成、成熟的东西,自然费劲不讨好了至于ini描述树形,根本不是问题,再复杂的都很好办
<csdn>
<develop tool>
<XXX>
<YYY>
</YYY>
</XXX>
</develop tool>
</csdn>
转为ini就是:
csdn=xxxxxxxx
csdn.develop tool=xxxxxxx
csdn.develop tool.xxx=xxxxxxxx
csdn.develop tool.xxx.yyy=xxxxxxx
分析起来非常直接快捷!
在服务器端的话,用COM+,可以有COM+提供的对象池、Webservice可提供线程池,更正一下!
INI格式的思路则是取自Windows应用程序的配置文件xxxxx.ini,它非常简单,既吸收的XML的灵活性,又保持简单、高效。数据记录集即可以用ini表达为:
[table1]
;以“;”开头的行为说明信息,实际不会出现
FieldCount=5
;数据集table1的字段数为5
;以下描述了该数据集各字段的属性
F1.name=id
F1.type=Int
F1.size=4
F2.name=title
F2.type=String
F2.size=50
……
F5.name=note
F5.type=String
F5.size=200RecordCount=320
;数据集table1的记录数为320
;以下为该数据集各字段的属性
1.1=2345
;第1条记录的第1个字段的值
1.2=关于市场业务的通知
;第1条记录的第2个字段的值
…
1.5=一周内落实
;第1条记录的第5个字段的值2.1=2346
;第2条记录的第1个字段的值
2.2=开展促销活动的效益回报
;第2条记录的第2个字段的值
…
2.5=送各部门负责人
;第2条记录的第5个字段的值……
……320.1=2701
;第320的第1字段的值
320.2=关于市场业务的通知
;第320的第2个字段的值
…
320.5=一周内落实
;第320的第5字段的值
属性和子节点 的确是一样看待的,就像treeview表达xml
不过,一定要区分,也可以:
a.b=xxxx 表示a节点的子节点b
a.#c=xxxx 表示a节点的属性c
http://blog.csdn.net/sz_haitao/archive/2009/10/30/4748629.aspx
http://topic.csdn.net/u/20091112/11/6a337128-ec80-49f6-a1fc-bc0497e9f481.html后来专门实现了一个用stringgrid改造得tree-grid的类:
TTreeGrid=class
private
treecol:Integer;
sg:TStringGrid;
bLine,bReadOnly:Boolean;
cbtnbg,cbtnf,cbg, cf:Tcolor;
//lastRow:Integer;
function isNode(const s:String):Boolean; overload;
function isNode(const r:Integer):Boolean; overload;
public
function getLevel(const s:String):Integer; overload;
function getLevel(const r:Integer):Integer; overload;
function isHided(const r:Integer):Boolean;
procedure hideNode(const r:Integer;const h:Boolean);
function Text2Node(const s:String;const l:Integer;const bHasSon:Boolean=false):String;
function getStat(const s:String):byte; overload; //0: no son; 1: exped; 2: colled;
function getStat(const r:Integer):byte; overload; //0: no son; 1: exped; 2: colled;
procedure setStat(const r:Integer;const bExp:Boolean{;const bChg:Boolean=false});
procedure switchStat(const r:Integer);
procedure showSon(const r:Integer); function getParent(const r:Integer):Integer;
function getSonFirst(const r:Integer):Integer;
function getBrotherUp(const r:Integer):Integer;
function getBrotherDown(const r:Integer):Integer; function GetNodeText(const s:String):String; overload;
function GetNodeText(const r:Integer):String; overload;
procedure setNodeText(const r:Integer;const s:String); function AddNode(const r:Integer;const t:String):Integer;
function AddSon(const r:Integer;const t:String):Integer;
function DelNode(const r:Integer):Integer; procedure DrawTreeNode(ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);
procedure ReDrawNode(r:Integer=-1); procedure OnDrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
procedure OnMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure OnSelectCell(Sender: TObject; ACol, ARow: Integer;
var CanSelect: Boolean);
procedure OnMouseWheel(Sender: TObject;
Shift: TShiftState; MousePos: TPoint; var Handled: Boolean;bUp:Boolean);
procedure OnMouseWheelUp(Sender: TObject;
Shift: TShiftState; MousePos: TPoint; var Handled: Boolean);
procedure OnMouseWheelDown(Sender: TObject;
Shift: TShiftState; MousePos: TPoint; var Handled: Boolean); procedure initStrings;
procedure LoadTreeFrom(ss:TStrings);
procedure SaveTreeTo(ss:TStrings); constructor create; overload;
constructor create(Asg:Tstringgrid;const Atreecol:Integer;ss:TStrings=nil
;const Aline:Boolean=true
;const btnbg:Tcolor=clyellow;const btnf:Tcolor=clblue;const bg:Tcolor=clwhite;const f:Tcolor=clBlack); overload;
procedure init(Asg:Tstringgrid;const Atreecol:Integer;ss:TStrings=nil
;const Aline:Boolean=true
;const btnbg:Tcolor=clyellow;const btnf:Tcolor=clblue;const bg:Tcolor=clwhite;const f:Tcolor=clBlack); procedure ExpNode(const r:Integer;const bExp:Boolean;const bSub:Boolean);
end;
tree-grid里不同节点的属性个数不同 的问题?
xpath好像是一种以xml为处理源的脚本,与显示方式没什么关系吧?
a.b=xxx //a的子节点b
a.#c=yyy //a的属性c
只要约定节点名不能以#开头就行了
这应该也算是解决了
1、自己写一个类似tomcat.exe/php.exe的文件来,自己玩一套。
2、webservice,这个是大家现在一直挂嘴边的。因为它是状态无关的,所以为了通过验证,到哪里都得把口令贴在脑门上。
3、再不济的,就用ActiveX了。
真没分了,请酌情多给点。
【
安全性的实现:由于HTTP协议的上下文无关特性,任何B/W或C/W模式的应用,都离不开如何“以上下文无关的协议实现上下文有关的逻辑”的问题。如:正常的应用流程是“先用户登录,合法用户才可以进行内容访问操作”,而HTTP协议的上下文无关,使得用户登录与内容访问操作不存在必然的关系,即非法用户只要知道了内容访问操作的URL,也可以绕开用户登录而直接进入内容访问操作,这显然是一个很严重的安全漏洞!笨拙的解决办法是:要求内容访问操作也附加用户合法性验证的信息,但是每次操作都附加用户合法性验证的信息,一则数据冗余,二则增加了不安全因素。幸亏B/W模式的应用有了一个巧妙的通用解决措施:通过一次有效的SessionID。服务器维护一个“合法登录用户信息—随机码”的对照表,对于经过用户登录被验证为合法的用户,服务器生成一个随机码(可以是纯数字,也可以是字符串,只要足够长度以致非法用户难以伪造冒认),并将此随机码与该用户信息一起存入“合法登录用户信息—随机码”的对照表,同时将此随机码发给前端(浏览器),以后前端(浏览器)的内容访问操作必须附加这个随机码(而不是原本的用户合法性验证的信息)以供服务器验证,没有随机码或随机码不存在于“合法登录用户信息—随机码”对照表的请求被视为无效请求。“合法登录用户信息—随机码”对照表的内容,在对应用户显式退出或超过指定时间没有操作请求后,自动被服务器删除。这样,即使某个有效的随机码被非法用户截获,那么这个非法用户也只能盗用一段时间,下一次就仍然会拒之门外。
】
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/sz_haitao/archive/2009/09/10/4539228.aspx
如果是“公共”使用的,遵守一定的标准就行了。WebService就是这么出来的。至于怎么“三层”,还是自己定,也就是自己“解析”数据就行了
当时我用了口令,而没有用帐号密码之类的的词汇,想它包括SessionID或者其他各种形式的key,或者是一句“芝麻开门”,我以为做过的人都能想到呢。
MIDAS/DataSnap算不?虽然性能和稳定性上总是被指责对于分层设计,我想有架构设计和部署实现两个层面,两个层面有关联,但关注点不完全一致。
总得说没有最好的设计或实现,只有最适合的。WebService作为一种实现方式最大的优势我想就是标准化。
我的实际应用遇到过最大:3万条记录,7M字节的ini数据,压缩后为2M,异地(同省)接收,客户端等待大约5-15秒,服务器为5M的adsl,客户端是4M的adsl
局域网只会更快,因为一般都是100M的连接。比上面的实例快了10倍。当然仅仅是传输快10倍,数据库的io、组包、压缩的速度是一样的
MIDAS/DataSnap算不?虽然性能和稳定性上总是被指责 对于分层设计,我想有架构设计和部署实现两个层面,两个层面有关联,但关注点不完全一致。
总得说没有最好的设计或实现,只有最适合的。 WebService作为一种实现方式最大的优势我想就是标准化
-------------------------------------------------
不好意思,我01年开始delphi编程两年半就转了dotnet&java了,所以现在只记得大概做法。
ActiveX属于Internet编程,web上最直接的感受是flash player。我们当然可以用它来实现很多功能,因为能嵌入网页,所以偶尔也归于web。
最早称为MIDAS(Multi-tier Distributed Application Services Suite),后来称为DataSnap,那只是一个架构的大概念,具体在delphi开发环境里也就是控件组的名字而已。使用DataSnap组里面的WebConnection控件,其过程就如上我说的第一种,只是我用的话糙点。
不是信息本身累,而是交流方式累。看来我还要坚持“只看不说”的上网风格了,破例是想要点分还怀怀旧。我声明我什么都没说,也不要再有人就我的话回复,因为你一回我又得打字。
這中模式比較好, 可以跨平臺服務, 中間層用java些,
利用XML 壓縮傳輸,速度嘛,還比較可以的,我從上海傳遞1萬條數據 到深圳,
1、20秒吧。具體沒有測試研究。主要是 中間層的java強大 ,使用 java 比較靈活, 而客戶端使用Delphi 那是不爭的事實。兩者優點相互結合,我趨向于這中模式,至于使用socket 或者 ini什么的,我沒有試驗過。
XML是通用網絡傳輸標準語言,還是跟標準走好。
另外也可以用Soap + WebService + COM+ 数据库
扯鸡8蛋。 我一直占着 这个 SessionID,一直发心跳包,不就可以不拉屎啦,这个盗用“一段时间”,从历史的长河中看,还真是一段。