Delphi SOAP WebService 服务器端多个 SoapDataModule 要注意的问题

前情提要

本人之前有篇博客文章,讲到在 Delphi 的 Soap WebService 程序服务器端,使用多个 TSoapDataModule 的方法。

文章地址在这里:https://blog.csdn.net/pcplayer/article/details/110178123

要点

内置 IdHTTPServer 的独立的 WebService 服务器端,内部有多个 TSoapDataModule,服务器端运行时,在 Delphi IDE 里面,通过 TSoapConnection 连接服务器端,ClientDataSet 的 Remote Server 设置为这个 SoapConnection,则 ClientDataSet 的属性里面,ProviderName 下拉,就能看到服务器端的 DataSetProvider。选好 Provider 以后,就可以为 ClientDataSet 在设计期增加固定字段 -- 字段窗口里面右键菜单选择 Add All Fields 菜单就出来了。

当服务器端有多个 TSoapDataModule 的时候,客户端看到的 DataSetProvider 究竟是服务器端哪个 SoapDataModule 的呢?

答案是,在工程文件里面,对工程的每个单元的声明,哪一个 SoapDataModule 排前面,设计期看到的就是哪一个 。因此,设计期相应看到另外一个,就把服务器端的工程文件里面的声明代码的前后顺序调整一下。

问题

上述做法,一直有效。直到有一天,我把想要在设计期看到的 SoapDataModule 排到前面,重新编译服务器端然后运行,在 IDE 里面的 ClientDataSet 下拉它的 Provider Name 属性,依然显示其它 SoapDataModule 而不是当前排第一的哪个。查了很久才找到原因。

问题的原因

原来,是我想让它排第一的那个  SoapDataModule ,在这里我把它叫 A 模块, 需要一个功能,就引用了一个其它的单元,这里我叫它 M 模块;而这个 M 模块,又引用了另外一个 SoapDataModule,这里我叫它 B 模块。

在这种情况下,把 A 模块放到第一,设计期从 ClientDataSet 的 Provider Name 下拉看到的,依然是 B 模块里面的 DataSetProvider。

大概原因就是虽然 A 模块顺序上排前面,但因为它引用了 M,而 M 又引用了 B,导致运行的时候,其实是 B 模块排前面。

我有这样的引用关系,是因为 A 模块里面用到的一个功能,刚好 B 模块里面实现了。为了代码重用,就这样引用了。

解决办法及注意事项

解决办法,就是在 M 模块里面实现一些各个 TSoapDataModule 都需要的函数或者方法。这个 M 模块是个普通的 DataModule 而不是一个 SoapDataModule。

这样就避免了多个 SoapDataModule 之间的互相引用,使得无法控制在设计期,客户端工程里面的 ClientDataSet 无法进行设计期的操作的问题。比如设计期添加固定字段。

注意事项

那个 M 模块,使用的是一个 TDataModule,在一个 TSoapDataModule 里面调用它的时候,因为 TSoapDataModule 是被 WebService 的 HTTP 线程调用的,可能多个客户同时访问,就有多个 TSoapDataModule,为了防止多个 TSoapDataModule 实例在多线程的情况下,同时去调用一个 M 模块的实例,这里需要每次调用都单独创建一个 M 模块的实例,调用完就释放掉。

效率问题

 如果每次调用 M 模块都要创建一个实例,调用完就释放,则创建、释放一个模块,会消耗 CPU 资源,让程序执行需要更多的时间。如果访问量很大,则需要考虑执行效率。解决办法是给 M 模块做一个对象缓冲池,需要时从缓冲池里面取一个已经创建好的对象实例来用,用完也不要释放,而是把它放回缓冲池。如此则解决了每次调用都要创建和释放带来的 CPU 消耗。

结论

1. 做一个独立模式(Stand alone)的 WebService 服务器端,如果涉及到的数据库的表太多,设计期拖放到 SoapDataModule 里面的,每个表对应的数据库控件和对应的 DataSetProvider 就会太多,可能的代码,比如检查登录权限然后决定某个表能给用户访问的代码,也会太多。为了方便管理,我们可以在服务器端,创建多个不同的 SoapDataModule 来做到模块化的目的。

2. 多个 SoapDataModule 不要互相引用,间接的也不要做。否则会让 ClientDataSet 在设计期无法看到已经运行的服务器端程序里面的正确的 SoapDataModule 里面的 DataSetProvider,让设计期的工作不方便做。

3. 服务器端,可以在普通的 DataModule 里面放数据库控件,用来实现一些数据库操作的功能,然后给 SoapDataModule 去使用。使用时注意动态创建实例。单一实例的话,程序也能运行,但并发访问多了,可能会出问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值