第4篇quick中間件服務(wù)端高級(jí)編程_第1頁(yè)
第4篇quick中間件服務(wù)端高級(jí)編程_第2頁(yè)
第4篇quick中間件服務(wù)端高級(jí)編程_第3頁(yè)
第4篇quick中間件服務(wù)端高級(jí)編程_第4頁(yè)
第4篇quick中間件服務(wù)端高級(jí)編程_第5頁(yè)
已閱讀5頁(yè),還剩305頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、第四篇中間件服務(wù)端高級(jí)編程QuickBurro 中間件從入門到精通本篇資料首先介紹 QuickBurro 中間件的各類服務(wù)端插件框架的接口標(biāo)準(zhǔn)、開發(fā)模板、注意事項(xiàng)及編程實(shí)例,然后給出了中間件 件所提供的各類 API 函數(shù)的技術(shù)細(xì)節(jié)及其用法示例。服務(wù)程序與重要接口插浙江-樵夫樵夫軟件開發(fā)2017-09-07QuickBurro 從入門到精通 - 中間件服務(wù)端高級(jí)編程所有© 樵夫軟件開發(fā)目錄一、服務(wù)端插件框架原理31.1 、插件框架的由來31.2 、服務(wù)端插件的種類41.3 、數(shù)據(jù)容器類與序列化轉(zhuǎn)換51.4 、插件調(diào)用的激發(fā)條件91.5 、插件的線程模式101.6 、插件的駐留內(nèi)存形式1

2、11.7 、插件延遲卸載處理111.8 、插件編程中的 API 函數(shù)111.9 、插件間共享數(shù)據(jù)的方法121.10 、插件的安全性12二、C/S 三層服務(wù)插件開發(fā)132.1 、C/S 三層服務(wù)插件的接口規(guī)范132.2 、C/S 三層服務(wù)插件模板文件132.3、C/S 三層服務(wù)插件的.202.4、在客戶端程序里調(diào)用插件功能21三、Web 服務(wù)插件開發(fā)233.1 、QuickBurro 中的虛擬動(dòng)態(tài)頁(yè)面233.2 、Web 服務(wù)插件的接口規(guī)范243.3 、Web 服務(wù)插件模板文件263.4 、Web 服務(wù)插件的部署方法323.5 、傳統(tǒng) Web 表單形式調(diào)用插件示例333.6 、AJAX 形式調(diào)用

3、Web 服務(wù)插件示例373.7 、在非網(wǎng)頁(yè)客戶端里調(diào)用 Web 服務(wù)插件示例413.8 、ISAPI 標(biāo)準(zhǔn)的Web 服務(wù)插件48四、移動(dòng)服務(wù)插件開發(fā)524.1 、Multipart 格式的Web 請(qǐng)求534.2 、移動(dòng)服務(wù)插件的接口規(guī)范534.3 、移動(dòng)服務(wù)插件模板文件544.4 、移動(dòng)服務(wù)插件的客戶端調(diào)用方法59五、Lazarus 服務(wù)插件開發(fā)645.1、Lazarus 服務(wù)插件接口規(guī)范641 / 309QuickBurro 從入門到精通 - 中間件服務(wù)端高級(jí)編程所有© 樵夫軟件開發(fā)5.2 、Lazarus 服務(wù)插件模板文件645.3 、TLazRPC 遠(yuǎn)過程調(diào)用控件695.4 、

4、Lazrus 服務(wù)插件及調(diào)用示例70六、WebSocket 服務(wù)插件開發(fā)736.1 、QuickBurro 的 WebSocket 服務(wù)746.2 、在 WebSocket 連接上實(shí)現(xiàn)的遠(yuǎn)過程調(diào)用836.3 、WebSocket 服務(wù)插件的接口規(guī)范836.4 、WebSocket 服務(wù)插件模板文件836.5 、WebSocket 插件調(diào)用示例86七、計(jì)劃任務(wù)插件開發(fā)897.1 、可執(zhí)行文件形式的計(jì)劃任務(wù)模塊897.2 、DLL 形式的計(jì)劃任務(wù)插件937.3 、駐留式計(jì)劃任務(wù)示例95八、服務(wù)端 API 函數(shù)詳解1008.1、ADO 數(shù)據(jù)庫(kù)連接池接口 API1028.2、ADO 數(shù)據(jù)庫(kù)重要功能接口

5、 API1118.3 、UniDAC 數(shù)據(jù)庫(kù)連接池接口 API1208.4 、FireDAC 數(shù)據(jù)庫(kù)連接池接口 API1298.5 、中間件對(duì)象管理接口 API1378.6 、消息傳輸功能接口 API1518.7 、Web 會(huì)話管理接口 API1708.8 、WebSocket 會(huì)話管理接口API1968.9 、數(shù)據(jù)共享交換接口 API2218.10 、通用對(duì)象池管理接口 API2358.11、HTTPS接口 API2448.12、雜項(xiàng)功能接口 API2518.13、第平臺(tái)接口API274九、后記3082 / 309QuickBurro 從入門到精通 - 中間件服務(wù)端高級(jí)編程所有©

6、樵夫軟件開發(fā)QuickBurro 中間件服務(wù)端高級(jí)編程一、服務(wù)端插件框架原理1.1、插件框架的由來從新版資料第一篇中的第 5 章“三層架構(gòu)模塊化技術(shù)”我們可以看出,將中間件分為“ 主程序、業(yè)務(wù)邏輯部件集合、 工具”三大部分是QuickBurro 中間件系統(tǒng)所推崇的模塊化實(shí)現(xiàn)方案,它將帶來中間層軟件規(guī)模的可控化、服務(wù)的可配置能力、模塊的可復(fù)用性、維護(hù)的方便性等好處,對(duì)降低開發(fā)與運(yùn)維成本、降低項(xiàng)目開發(fā)風(fēng)險(xiǎn)、提高軟件質(zhì)量等方面也有很明顯的促進(jìn)作用。而“服務(wù)端插件框架”技術(shù),是上述分模塊方案的實(shí)現(xiàn)方法。具體來說,就是將中間層軟件主程序設(shè)計(jì)為一種可輕松和拔除模塊的容器程序,而將業(yè)務(wù)處理部分設(shè)計(jì)成一系列的

7、可到主程序及從主程序拔除的模塊程序,形象地說,類似于帶了無數(shù)擴(kuò)展槽的電子設(shè)備,可以將遵循擴(kuò)展槽接口標(biāo)準(zhǔn)的電子線路板主設(shè)備以進(jìn)行功能增強(qiáng)、而將電子線路板從主設(shè)備插槽里拔掉來實(shí)現(xiàn)功能的卸除。對(duì)于 QuickBurro中間件,在基于Windows 系統(tǒng)的環(huán)境下,中間件主程序是一個(gè)標(biāo)準(zhǔn)Windows 服務(wù)程序(.exe),而業(yè)務(wù)處理模塊則是一系列的動(dòng)態(tài)庫(kù)(.dll),而所謂的“/拔除”動(dòng)作,可以使用臺(tái)管理工具等實(shí)現(xiàn)。由中間件服務(wù)程序的技術(shù)實(shí)現(xiàn)角度來看,服務(wù)端插件框架既要滿足輕松/拔除的需要,更要滿足“為客戶端提供良好的并發(fā)服務(wù)”這一總?cè)蝿?wù)的需要,所以,插件框架必須與網(wǎng)絡(luò)通信、并發(fā)任務(wù)處理等部分有很好的

8、協(xié)作,框架運(yùn)行流程上遵循中間件工作主流程的。經(jīng)過我們大量的研究與實(shí)踐, QuickBurro中間件最終采用了下圖所示這樣的技術(shù)實(shí)現(xiàn)方案,按下圖嘗試走一遍功能調(diào)用交互過程,就可以理解此插件框架的工作原理。3 / 309QuickBurro 從入門到精通 - 中間件服務(wù)端高級(jí)編程所有© 樵夫軟件開發(fā)(1) 、客戶端程序通過 TCP 或 HTTP/HTTPS 通信向中間件發(fā)起功能服務(wù)請(qǐng)求(2) 、服務(wù)端通信程序接收到來自客戶端的請(qǐng)求后,將任務(wù)壓入隊(duì)列,然后再分配工作線程來處理任務(wù)(3) 、工作線程從任務(wù)隊(duì)列彈出請(qǐng)求任務(wù),根據(jù)調(diào)用對(duì)象標(biāo)識(shí)找到服務(wù)端插件,加載、傳入?yún)?shù)、執(zhí)行(4) 、服務(wù)端插

9、件根據(jù)傳入的參數(shù)及預(yù)先編制的程序來處理業(yè)務(wù)邏輯(5) 、業(yè)務(wù)邏輯處理完成后,插件將結(jié)果返回給工作線程,工作線程再將處理結(jié)果壓入應(yīng)答任務(wù)隊(duì)列(6) 、中間件調(diào)度程序再分配應(yīng)答反饋工作線程,然后此工作線程再?gòu)膽?yīng)答任務(wù)隊(duì)列中取出應(yīng)答數(shù)據(jù)(7)、應(yīng)答反饋工作線程通過 TCP 或 HTTP/HTTPS 通信向調(diào)用發(fā)起的客戶端應(yīng)答數(shù)據(jù)顯然,服務(wù)端插件框架的實(shí)現(xiàn)過程,是與中間件的網(wǎng)絡(luò)通信、任務(wù)調(diào)度、線程池、任務(wù)隊(duì)列等算法或數(shù)據(jù)結(jié)構(gòu)緊密相關(guān)的,對(duì)外提供一種簡(jiǎn)潔的插拔式接口,而內(nèi)部實(shí)現(xiàn)則相對(duì)復(fù)雜、較難實(shí)現(xiàn)的。當(dāng)然,假如您理解了服務(wù)端插件框架的原理,而直接使用QuickBurro 中間件、不是寫底層去實(shí)現(xiàn)這一切的

10、話,就不必與這些糾結(jié)在一起的技術(shù)問題打交道直接使用插件框架、編寫一下插件并調(diào)用,就可以了。1.2、服務(wù)端插件的種類上節(jié)這樣的服務(wù)端插件框架在 QuickBurro 中間件主服務(wù)中存在多個(gè)實(shí)例,即 C/S 三層服務(wù)插件框架、Web 服務(wù)插件框架、WebSocket 服務(wù)插件框架、移動(dòng)開發(fā)服務(wù)插件框架等,它們的實(shí)現(xiàn)原理都一樣,只是在接口規(guī)范上存在一些很小的差異。然后,與這些插件框架實(shí)例相對(duì)應(yīng),服務(wù)端插件也就分為如下幾類:1)、C/S 三層架構(gòu)服務(wù)插件這是一類服務(wù)于 C/S 三層客戶端的服務(wù)端插件,是QuickBurro 中間件最早支持的一類插件。這類插件通過中間件的TCP 任務(wù)端口接收調(diào)用任務(wù)后再

11、被調(diào)用執(zhí)行;并且,它們需要到中間件上才能被客戶端調(diào)用;這類插件通過傳遞TQBParcel 形式的參數(shù)包和出口參數(shù)包的形式來交換數(shù)據(jù);支持單線程/多線程兩種線程模式;可以設(shè)置來確保安全性;支持駐留/非駐留運(yùn)行方式;支持同步/異步方式調(diào)用。除了被客戶端調(diào)用之外,這類插件還支持以計(jì)劃任務(wù)、觸發(fā)消息等方式進(jìn)行觸發(fā)執(zhí)行。2)、Web 服務(wù)插件這是一類通過 HTTP/HTTPS 協(xié)議調(diào)用的服務(wù)端插件。這類插件也可為駐留內(nèi)存以應(yīng)對(duì)高強(qiáng)度頻繁調(diào)用的需求,但不時(shí)也能直接調(diào)用(但不駐留內(nèi)存);另外,對(duì)它們的調(diào)用通過自動(dòng)的“虛擬動(dòng)態(tài)頁(yè)面”URL 的形式進(jìn)行;調(diào)用時(shí)參數(shù)交換通過 Web 表單、Json、Xml 等方式

12、進(jìn)行;這類插件全部為多線程方式調(diào)用,支持同步/異步調(diào)用。3)、WebSocket 服務(wù)插件這是一類專門為WebSocket 長(zhǎng)連接提供的服務(wù)端插件,客戶端也通過自動(dòng)的“虛擬動(dòng)態(tài)頁(yè)面”URL來作為標(biāo)識(shí)進(jìn)行調(diào)用。這類插件像 Web 插件一樣,可為駐留內(nèi)存以應(yīng)對(duì)高強(qiáng)度頻繁調(diào)用的需求,但不時(shí)也能直接調(diào)用(但不駐留內(nèi)存);調(diào)用時(shí)參數(shù)交換一般通過 Json、Xml 等方式進(jìn)行。這類插件全部為多線程方式調(diào)用,當(dāng)然也支持同步/異步調(diào)用。4)、移動(dòng)服務(wù)插件對(duì)于 Delphi 多設(shè)備應(yīng)用程序開發(fā)的支持(即 FireMonkey 架構(gòu)下的應(yīng)用開發(fā)支持)而專門實(shí)現(xiàn)的一類服務(wù)端插件是一種特殊的 Web 服務(wù)插件,即通信

13、協(xié)議上采用 HTTP/HTTPS,但交換信息的封裝上采用萬能容器類 TMBParcel,即,TMBParcel 的傳入數(shù)據(jù)包轉(zhuǎn)換為Multipart 格式的Web 表單后經(jīng)由 HTTP/HTTPS 通信來實(shí)現(xiàn)任務(wù)的提交,而結(jié)果則通過輸出參數(shù)包對(duì)象封裝,然后轉(zhuǎn)換為二進(jìn)制流,返回給多設(shè)備應(yīng)用程序客戶端。由于其數(shù)據(jù)交互的二進(jìn)制數(shù)據(jù)形式,故在基于 HTTP 協(xié)議進(jìn)行通信時(shí),安全性比一般基于 Json/Xml 數(shù)據(jù)的方式要好。這類插件也全部為多線程方式調(diào)用、也可為駐留內(nèi)存或不。4 / 309QuickBurro 從入門到精通 - 中間件服務(wù)端高級(jí)編程所有© 樵夫軟件開發(fā)5)、FreePasca

14、l 服務(wù)插件另外,QuickBurro 中間件中又以“移動(dòng)服務(wù)插件”類似的方式提供 FreePascal 服務(wù)插件,專門為 Free Pascal客戶端(比如 Lazarus 編寫的客戶端)提供各種通用/的業(yè)務(wù)邏輯處理服務(wù),它們同樣通信協(xié)議上采用HTTP/HTTPS,但交換信息的封裝上采用萬能容器類 TLazParcel。這類插件全部為多線程方式調(diào)用、也可為駐留內(nèi)存或不。1.3、數(shù)據(jù)容器類與序列化轉(zhuǎn)換無論以怎么樣的數(shù)據(jù)格式進(jìn)行客戶端/中間層交互,所傳輸?shù)男畔⒖偸切枰D(zhuǎn)換為流式數(shù)據(jù)的形式進(jìn)行。一般地,以容器類特有的方式組織的數(shù)據(jù)轉(zhuǎn)換為流式數(shù)據(jù)的過程,稱為序列化,反之則叫反序列化(或叫對(duì)象化)。在

15、客戶端調(diào)用服務(wù)端插件、或插件編寫的過程中,經(jīng)常會(huì)碰到各種序列化/反序列化的場(chǎng)景,故這是比較重要的編程技巧,建議大家掌握。1)、萬能容器類的序列化/反序列化lTQBParcel 對(duì)象序列化方法序列化到流對(duì)象function SaveToStream(var aStream: TMemoryStream): boolean;序列化到文件function SaveToFile(FileName: String): boolean;序列化到字符串緩沖function SaveToString(var aStr: Ansistring): boolean;帶前導(dǎo)長(zhǎng)度的序列化到字符串緩沖function

16、SaveToStringWithLength(var aStr: Ansistring): boolean;加密序列化到流對(duì)象function EncryptToStream(var aStream: TMemoryStream): boolean;Zip 壓縮序列化到流對(duì)象function ZipToStream(var aStream: TMemoryStream): boolean;Zip 壓縮序列化到文件function ZipToFile(FileName: string): boolean;LZO 壓縮序列化到流對(duì)象function LzoToStream(var aStream:

17、 TMemoryStream): boolean;LZO 壓縮序列化到文件function LzoToFile(FileName: string): boolean;LZO 壓縮序列化到字符串緩沖function LzoToString(var Str: ansistring): boolean;lTQBParcel 對(duì)象反序列化方法從流對(duì)象反序列化function LoadFromStream(aStream: TMemoryStream): boolean;從文件反序列化function LoadFromFile(FileName: String): boolean;從字符串緩沖反序列化f

18、unction LoadFromString(aStr: Ansistring): boolean;從全局內(nèi)存區(qū)反序列化5 / 309QuickBurro 從入門到精通 - 中間件服務(wù)端高級(jí)編程所有© 樵夫軟件開發(fā)function LoadFromMemory(MemPtr: Pointer): boolean;從全局內(nèi)存塊反序列化function LoadFromGlobalMem(MemPtr: integer): boolean;從流對(duì)象并反序列化function DecryptFromStream(aStream: TMemoryStream): boolean;從流對(duì)象 Z

19、IP 解壓并反序列化function UnzipFromStream(aStream: TMemoryStream): boolean;從文件 ZIP 解壓并反序列化function UnzipFromFile(FileName: string): boolean;從流對(duì)象 LZO 解壓并反序列化function UnlzoFromStream(aStream: TMemoryStream): boolean;從字符串緩沖 LZO 解壓并反序列化function UnlzoFromString(Str: ansistring): boolean;從文件 LZO 解壓并反序列化function

20、UnlzoFromFile(FileName: string): boolean;與TQBParcel 對(duì)象類似,多設(shè)備應(yīng)用開發(fā)中使用的TMBParcel 對(duì)象和Lazarus 應(yīng)用開發(fā)中使用的TLazParcel對(duì)象,其序列化/反序列化的處理也類似,各有一系列方法,用法很簡(jiǎn)單,不再贅述。2)、數(shù)據(jù)集的序列化/反序列化lTClientDataset 的數(shù)據(jù)集序列化方法數(shù)據(jù)集序列化到流對(duì)象procedure SaveToStream(Stream: TStream; Format: TDataPacketFormat = dfBinary);數(shù)據(jù)集序列化到文件procedure SaveToFi

21、le(const FileName: string = '' Format: TDataPacketFormat = dfBinary);lTClientDataset 的數(shù)據(jù)集序反序列化方法從流對(duì)象反序列化數(shù)據(jù)集procedure LoadFromStream(Stream: TStream);從文件反序列化數(shù)據(jù)集procedure LoadFromFile(const FileName: string = '');lTMBTable/TQBMemTable 的數(shù)據(jù)集序列化方法數(shù)據(jù)集序列化到流對(duì)象function SaveToStream(aStream: T

22、MemoryStream): boolean;數(shù)據(jù)集序列化到文件function SaveToFile(aFileName: string): boolean;lTMBTable/TQBMemTable 的數(shù)據(jù)集序反序列化方法從流對(duì)象反序列化數(shù)據(jù)集function LoadFromStream(aStream: TMemoryStream): boolean;從文件反序列化數(shù)據(jù)集function LoadFromFile(aFileName: string): boolean;6 / 309QuickBurro 從入門到精通 - 中間件服務(wù)端高級(jí)編程所有© 樵夫軟件開發(fā)在遠(yuǎn)過程調(diào)用期

23、間及服務(wù)端插件與客戶端調(diào)用方交互期間,當(dāng)需要進(jìn)行數(shù)據(jù)集形式的時(shí),這些數(shù)據(jù)集與流對(duì)象之間的轉(zhuǎn)換很常見。其他內(nèi)存表對(duì)象如 FDMemTable 之類,其序列化/反序列化處理大同小異,另外,也可以先與TClientDataset 進(jìn)行轉(zhuǎn)換,再由TClientDataset 作流化處理。3)、Json 對(duì)象的序列化/反序列化QuickBurro 中 Json 對(duì)象TQBJson/TMBJson/TLazJson 進(jìn)行序列化/反序列化處理過程,就是將 Json 對(duì)象轉(zhuǎn)換為字符串/流對(duì)象/文件,或者反向由字符串/流/文件生成 Json 對(duì)象。這種轉(zhuǎn)換處理方法在進(jìn)行 JsonRPC 調(diào)用時(shí)的服務(wù)端插件編程時(shí)

24、經(jīng)常需要使用:l序列化方法序列化為字符串(不含回車換行制表符) function ToString (): Ansistring ; overload; override; 序列化為字符串(含回車換行制表符)function ToString2 (indentFactor : integer): Ansistring; overload;序列化為字符串(含回車換行制表符,帶縮進(jìn))function ToString3 (indentFactor, indent : integer): Ansistring; overload;序列化為流數(shù)據(jù)function SaveToStream(aStrea

25、m: TStream; OutFormat: integer): boolean;序列化到文件function SaveToFile(aFilename: string; OutFormat: integer): boolean;序列化到包裹對(duì)象的字段function SaveToParcel(aQBParcel: TQBParcel; GoodsName: Ansistring; OutFormat: integer): boolean;l反序列化方法從字符串反序列化為 Json 對(duì)象constructor Create (s : Ansistring); overload; 從流數(shù)據(jù)反序列

26、化為 Json 對(duì)象constructor Create (aStream: TStream; Bytes: integer); overLoad;從文件反序列化為 Json 對(duì)象constructor Create (aFilename: string; FailIfNoFile: boolean); overload;從包裹對(duì)象字段數(shù)據(jù)反序列化為Json 對(duì)象constructor create (aQBParcel: TQBParcel; GoodsName: Ansistring); overload;4)、XML 數(shù)據(jù)的序列化/反序列化Delphi 中處理 XML 數(shù)據(jù)的常用對(duì)象是

27、IXMLDocument,可以用以下方法進(jìn)行序列化/反序列化處理:l 序列化方法序列化為流數(shù)據(jù)procedure SaveToStream(const Stream: TStream);序列化到文件procedure SaveToFile(const AFileName: DOMString);序列化為字符串procedure SaveToXML(var XML: DOMString); overload; procedure SaveToXML(var XML: WideString); overload; procedure SaveToXML(var XML: UTF8String);

28、overload;7 / 309QuickBurro 從入門到精通 - 中間件服務(wù)端高級(jí)編程所有© 樵夫軟件開發(fā)l 反序列化方法從流數(shù)據(jù)反序列化procedure LoadFromStream(const Stream: TStream; EncodingType: TXMLEncodingType = xetUnknown);從文件反序列化procedure LoadFromFile(const AFileName: DOMString);從字符串反序列化procedure LoadFromXML(const XML: AnsiString); overload; procedur

29、e LoadFromXML(const XML: DOMString); overload;XmlDOC.pas 單元中的反序列化函數(shù),由文件、字符串等創(chuàng)建IXMLDocument 對(duì)象:function LoadXMLDocument(const FileName: DOMString): IXMLDocument; function LoadXMLData(const XMLData: DOMString): IXMLDocument; overload; function LoadXMLData(const XMLData: AnsiString): IXMLDocument; over

30、load;5)、常用的轉(zhuǎn)換函數(shù)在中間件的VCLSDK、FMXSDK 下,還存在若干實(shí)用函數(shù)庫(kù)單元,其中包含有各種數(shù)據(jù)容器之間、容器與流對(duì)象/內(nèi)存塊/字符串之間的實(shí)用轉(zhuǎn)換函數(shù),請(qǐng)各位適當(dāng)熟悉一下,編程時(shí)方便:lVclsdkqbcommon.pas 下字符串與流對(duì)象之間的轉(zhuǎn)儲(chǔ)procedure Str2Stream(Str: Ansistring; var aStream: TMemoryStream);procedure Stream2Str(aStream: TMemoryStream; var aStr: Ansistring);字符串與文件之間的轉(zhuǎn)儲(chǔ)function Str2File(St

31、r: Ansistring; aFileName: string): boolean; function File2Str(aFileName: string; var Str: Ansistring): boolean; 字符串緩沖與 Cds 數(shù)據(jù)集的轉(zhuǎn)換procedure Str2Cds(Str: Ansistring; var aCds: TClientDataset);procedure Cds2Str(aCds: TClientDataset; Fmt: TDataPacketFormat; var aStr: Ansistring);字符串緩沖與包裹對(duì)象的轉(zhuǎn)儲(chǔ)procedure S

32、tr2Parcel(Str: Ansistring; var aParcel: TQBParcel); procedure Parcel2Str(aParcel: TQBParcel; var aStr: Ansistring);Recordset 中的 Blob 字段轉(zhuǎn)存到流function blob2stream(Rs: _RecordSet; FieldName: string; aStream: TMemoryStream): boolean;Variant 與流對(duì)象之間的轉(zhuǎn)換function VariantToStream (const v: OleVariant; Stream:

33、TMemoryStream): boolean; function StreamToVariant(Stream: TMemoryStream; var v: OleVariant): boolean;RecordSet 對(duì)象與流對(duì)象之間的轉(zhuǎn)換function RecordsetToStream(const Recordset: _Recordset; var Stream: TMemoryStream; var error: string): boolean; function StreamToRecordset(Stream: TMemoryStream; var RecordSet: _

34、Recordset): boolean;TParam 對(duì)象與包裹對(duì)象的轉(zhuǎn)換function ParamToParcel(AParam:TParam; AParcel: TQBParcel; ParamDir: Byte):Boolean; function ParamFromParcel(AParam:TParam; AParcel: TQBParcel):Boolean;數(shù)據(jù)集對(duì)象之間的轉(zhuǎn)換function CreateAdoDatasetAs(const SourceDS: TADODataset): TAdoDataset; function DatasetToCdsData(aData

35、set: TDataset): OleVariant;8 / 309QuickBurro 從入門到精通 - 中間件服務(wù)端高級(jí)編程所有© 樵夫軟件開發(fā)function GetCdsFromAdo(aAdoDataset: TAdoDataset; aCds: TClientDataset): boolean;ADO 數(shù)據(jù)集轉(zhuǎn)內(nèi)存表function Adods2Tab(aAdoDataset: TAdoDataset; aTab: TMBTable2): boolean;lVclsdkLazPluginApi.pas 下TQBMemDataset 數(shù)據(jù)集與 TClientDataset

36、數(shù)據(jù)集間的轉(zhuǎn)換function Mds2Cds(aMds: TQBMemDataset; aCds: TClientDataset): boolean; function Cds2Mds(aCds: TClientDataset; aMds: TQBMemDataset): boolean;TQBMemDataset 數(shù)據(jù)集與 ADO 數(shù)據(jù)集之間的轉(zhuǎn)換function Adods2Mds(aAdoDataset: TAdoDataset; aMds: TQBMemDataset; var Error: string): boolean; function Mds2Adods(Mds: TQBM

37、emDataset; AdoDataset: TAdoDataset): boolean;TQBMemDataset 數(shù)據(jù)集與 Json 之間的轉(zhuǎn)換function MDS2Json(Mds: TQBMemDataset; aJson: TQBJson): boolean; function Json2MDS(aJson: TQBJson; Mds: TQBMemDataset): boolean;TQBMemDataset 數(shù)據(jù)集與流對(duì)象之間的轉(zhuǎn)換function MDS2Stream(Mds: TQBMemDataset; aStream: TMemoryStream): boolean;

38、 function Stream2MDS(aStream: TMemoryStream; Mds: TQBMemDataset): boolean;ADO 數(shù)據(jù)集與 Json 之間的轉(zhuǎn)換function Adods2Json(aAdoDataset: TAdoDataset; aJson: TQBJson): boolean;function Adods2Stream(aAdoDataset: TAdoDataset; aStream: TMemoryStream): boolean;TClientDataset 數(shù)據(jù)集與其他對(duì)象之間的轉(zhuǎn)換function Cds2Json(Cds: TCli

39、entDataset; aJson: TQBJson): boolean;function Cds2Stream(Cds: TClientDataset; aStream: TMemoryStream): boolean; function Tab2Cds(aTab: TQBMemTable; aCds: TClientDataset): boolean; function Cds2Tab(aCds: TClientDataset; aTab: TQBMemTable): boolean;ADO 數(shù)據(jù)集與 TQBMemTable 之間的轉(zhuǎn)換function Adods2Tab(aAdoData

40、set: TAdoDataset; aTab: TQBMemTable): boolean; function Tab2Adods(aTab: TQBMemTable; AdoDataset: TAdoDataset): boolean;TQBMemTable 與 Json 之間的轉(zhuǎn)換function Tab2Json(aTab: TQBMemTable; aJson: TQBJson): boolean; function Json2Tab(aJson: TQBJson; aTab: TQBMemTable): boolean;TQBMemDataset 與 TQBMemTable 之間的轉(zhuǎn)

41、換function Mds2Tab(aMds: TQBMemDataset; aTab: TQBMemTable): boolean;lVclsdk adods2json.pas 下ADO 數(shù)據(jù)集與流對(duì)象間的轉(zhuǎn)換function ads2LazStream(ads: TAdoDataset; aStream: TMemoryStream): boolean; function LazStream2ads(aStream: TMemoryStream; ads: TAdoDataset): boolean;ADO 數(shù)據(jù)集與文件之間的轉(zhuǎn)儲(chǔ)function ads2LazFile(ads: TAdo

42、Dataset; aFileName: string): boolean; function LazFile2ads(aFileName: string; ads: TAdoDataset): boolean;1.4、插件調(diào)用的激發(fā)條件服務(wù)端插件在創(chuàng)建并部署到中間件服務(wù)端之后,根據(jù)插件類別的不同,會(huì)在不同的外部條件下被調(diào)用9 / 309QuickBurro 從入門到精通 - 中間件服務(wù)端高級(jí)編程所有© 樵夫軟件開發(fā)執(zhí)行,通常表現(xiàn)為以下幾種情況:1)、被客戶端調(diào)用時(shí)當(dāng) VCLSDK 下的TDllPlugin 控件、TQBHttps 控件、以及“QuickBurro Extended”組

43、件面板下基于服務(wù)端插件封裝的擴(kuò)展控件調(diào)用了服務(wù)端插件模塊中的方法時(shí),服務(wù)端插件會(huì)被中間件的工作線程加載內(nèi)存、調(diào)用執(zhí)行指定的方法。2)、被模塊觸發(fā)器觸發(fā)調(diào)用模塊觸發(fā)器之后,當(dāng)指定的觸發(fā)消息被中間件接收到后,就會(huì)分配一個(gè)工作線程加載觸發(fā)器時(shí)指定的插件,并調(diào)用其導(dǎo)出函數(shù)。3)、計(jì)劃任務(wù)條件滿足時(shí)調(diào)用當(dāng)中間件啟動(dòng)服務(wù)時(shí),為“啟動(dòng)服務(wù)時(shí)調(diào)用”的計(jì)劃任務(wù)會(huì)被自動(dòng)調(diào)用;當(dāng)中間件即將停止服務(wù)之間,為“停止服務(wù)時(shí)調(diào)用”的計(jì)劃任務(wù)會(huì)被自動(dòng)調(diào)用;而為周期執(zhí)行、某時(shí)間點(diǎn)執(zhí)行等的計(jì)劃任務(wù)插件,則會(huì)在時(shí)間點(diǎn)上被中間件工作線程調(diào)起并執(zhí)行其導(dǎo)出函數(shù)。4)、被周邊插件調(diào)用服務(wù)端插件可以主動(dòng)調(diào)用其他周邊插件的功能,以實(shí)現(xiàn)功能復(fù)用

44、。1.5、插件的線程模式插件有多線程和單線程兩種調(diào)用模式。C/S 三層服務(wù)插件在其他類型的插件,全部以多線程模式進(jìn)行調(diào)用。插件時(shí),可以指定這種線程模式。對(duì)于插件功能的調(diào)用都是由中間件服務(wù)所分配的工作線程進(jìn)行的,所謂多線程模式,就是指同一時(shí)刻可能存在多個(gè)工作線程對(duì)同一插件進(jìn)行功能調(diào)用,而單線程模式,系統(tǒng)確保同一時(shí)刻只能存在一個(gè)調(diào)用它的工作線程,不存在并發(fā)調(diào)用的情景;對(duì)于多線程模式的插件,編寫時(shí)務(wù)必注意臨界、全局變量等的防處理,可以不用全局變量的,盡量不要用,而單線程插件,則可以不用擔(dān)心并發(fā)導(dǎo)致出錯(cuò)問題;總體效率而言,多線程模式明顯要高于單線程模式;對(duì)于一些特殊的需要排隊(duì)執(zhí)行的功能,多線程不合適,

45、務(wù)必使用單線程模式實(shí)現(xiàn),比如業(yè)務(wù)掛號(hào)之類。除了在 C/S 三層服務(wù)插件時(shí)指定線程模式外,對(duì)于駐留內(nèi)存的插件,應(yīng)用程序員也可以通過定義全局臨界區(qū)變量來自行處理線程模式,比如,預(yù)加載的Web 插件(駐留內(nèi)存),一般外部來看是多線程執(zhí)行,10 / 309QuickBurro 從入門到精通 - 中間件服務(wù)端高級(jí)編程所有© 樵夫軟件開發(fā)但您可以在內(nèi)部定義臨界區(qū),調(diào)用時(shí)通過臨界區(qū)來確保某些方法的串行執(zhí)行,起到單線程模式的效果。EnterCriticalSection(Cs); LeaveCriticalSection(Cs);1.6、插件的駐留內(nèi)存形式有兩種功能需求要求插件一直駐留在內(nèi)存中,而不

46、要從內(nèi)存卸載:一是運(yùn)行過程需要保存中間狀態(tài); 二是插件被調(diào)用的頻率非常高、需要減少調(diào)進(jìn)調(diào)出的次數(shù)。當(dāng)插件隨中間件服務(wù)啟動(dòng)而被一直駐留內(nèi)存后,就可以通過定義使用全局變量的形式來保存功能執(zhí)行的中間態(tài),插件也被經(jīng)常地調(diào)進(jìn)調(diào)出內(nèi)存而影響運(yùn)行效率;而對(duì)于非駐留形式的插件,一般是被調(diào)用時(shí)才被調(diào)入內(nèi)存運(yùn)行,功能調(diào)用完成后,又會(huì)從內(nèi)存中卸載。駐留內(nèi)存的插件占用內(nèi)存,而非駐留內(nèi)存的插件只在被調(diào)用時(shí)占用內(nèi)存??梢栽赒uickBurro 中間件的服務(wù)管理器的“插件”頁(yè)面插件,指定“加載模式”為常駐內(nèi)存或即時(shí)加載;對(duì)于 Web 服務(wù)插件,為“預(yù)加載”形式的插件就是指定為駐留內(nèi)存,不則指不駐留內(nèi)存。1.7、插件延遲卸載

47、處理對(duì)于即時(shí)加載的插件,由于可能會(huì)導(dǎo)致頻繁的調(diào)進(jìn)調(diào)出而影響運(yùn)行效率、降低系統(tǒng)穩(wěn)定性,因此,我們?cè)趯?shí)現(xiàn)插件框架時(shí)實(shí)現(xiàn)了一種有效的技術(shù)措施來減少調(diào)進(jìn)調(diào)出的次數(shù),那就是所謂“插件延遲卸載”技術(shù),即在插件需要從內(nèi)存卸載時(shí)加入一定的延時(shí),如在延時(shí)時(shí)段內(nèi)有新的調(diào)用請(qǐng)求,則不用再?gòu)耐獠考虞d而直接調(diào)用、而卸載延遲在新的調(diào)用結(jié)束后重新開始,如在延時(shí)時(shí)段內(nèi)不再有新的調(diào)用請(qǐng)求,則此插件才正式從內(nèi)存中作卸載處理。采用“插件延遲卸載”技術(shù)之后,對(duì)于頻繁調(diào)用但又未設(shè)置為駐留內(nèi)存的插件(有時(shí)管理員或應(yīng)用程序員也無法有些插件的調(diào)用頻度,而未將它們?cè)O(shè)置為駐留內(nèi)存),可以顯著減少調(diào)進(jìn)調(diào)出內(nèi)存的次數(shù),有效提高運(yùn)行速度及穩(wěn)定性;當(dāng)然

48、,此技術(shù)使用之后,插件的動(dòng)態(tài)更新可能會(huì)因插件還未卸載而出現(xiàn)失敗,需要延時(shí)重試才能,對(duì)此,應(yīng)用程序員或管理員應(yīng)有思想準(zhǔn)備。1.8、插件編程中的 API 函數(shù)QuickBurro 的服務(wù)及公共服務(wù)插件除了為客戶端提供相對(duì)通用的各種中間層功能服務(wù)之外,還以回調(diào)函數(shù)的形式向周邊其他服務(wù)端插件提供API 服務(wù),這些API 函數(shù)庫(kù)定義在VCLSDK 目錄下的如下這些單元中,編寫服務(wù)端插件時(shí),直接 Uses 它們,就可以使用其中的 API 函數(shù):11 / 309QuickBurro 從入門到精通 - 中間件服務(wù)端高級(jí)編程所有© 樵夫軟件開發(fā)服務(wù)程序 API 函數(shù)庫(kù)單元(老版本,將逐步廢棄)服務(wù)程序

49、 API 函數(shù)庫(kù)單元(新版,推薦使用)NodeServiceAPI.pasQBServiceAPI.pas AlidayuAPI.pas AlipayAPI.pas BaiduTTSAPI.pas FiredacEngineAPI.pas LazPluginApi.pas MBPluginApi.pas UnidacEngineAPI.pas WeixinApi.pas WeixinEntApi.pas WxPayApi.pas阿里大于接口 API 函數(shù)庫(kù)單元支付寶支付接口 API 函數(shù)庫(kù)單元語音接口 API 函數(shù)庫(kù)單元FireDAC 數(shù)據(jù)庫(kù)引擎 API 函數(shù)庫(kù)單元Lazarus 服務(wù)插件接口

50、輔助函數(shù)單元移動(dòng)服務(wù)插件接口輔助函數(shù)單元UniDAC 數(shù)據(jù)庫(kù)引擎 API 函數(shù)庫(kù)單元訂閱號(hào)/服務(wù)號(hào)接口 API 函數(shù)庫(kù)單元企業(yè)號(hào)接口 API 函數(shù)庫(kù)單元支付接口 API 函數(shù)庫(kù)單元對(duì)以上這些API 庫(kù)函數(shù)單元中的 API 函數(shù)的功能、用法,將在本資料的最后一章中進(jìn)行詳細(xì)介紹,本節(jié)只做概括性的梳理,目的是概況全篇,以便更好地深入各章節(jié)。1.9、插件間共享數(shù)據(jù)的方法插件模塊除了需要和宿主服務(wù)程序及客戶端應(yīng)用程序之間交換數(shù)據(jù)、與底層的數(shù)據(jù)庫(kù)及操作系統(tǒng)間交換信息外,有時(shí)還需要進(jìn)行不同插件之間的信息共享交換、插件的不同調(diào)用時(shí)期間的信息共享交換等,比如,插件需要向數(shù)據(jù)處理插件傳遞所到的數(shù)據(jù),等等。出于這種

51、需求,QuickBurro 中間件系統(tǒng)中實(shí)現(xiàn)了一種稱之為“數(shù)據(jù)?!钡募夹g(shù),以“驛站”(公用數(shù)據(jù)區(qū))的形式向“各位旅客”(插件)提供數(shù)據(jù)寄存、刪除等功能。數(shù)據(jù)棧分為公用數(shù)據(jù)棧和私有數(shù)據(jù)棧兩類,“私有數(shù)據(jù)?!笔菤w屬于某插件的局部的數(shù)據(jù)區(qū),一般只由本插件在不同的調(diào)用時(shí)段進(jìn)行讀寫;而“公用數(shù)據(jù)?!痹谶@里是指一種用于 刪除失效了的數(shù)據(jù)等等,是 QuickBurro的公用數(shù)據(jù)區(qū),可以向其中“寄存”數(shù)據(jù)、檢索數(shù)據(jù)、從中為了實(shí)現(xiàn)服務(wù)端程序的各個(gè)部分(特別是插件之間)進(jìn)行數(shù)據(jù)共享交換的一種數(shù)據(jù)結(jié)構(gòu)及技術(shù)。對(duì)于數(shù)據(jù)棧的使用,我們專門在服務(wù) API 函數(shù)庫(kù)單元 qbserviceapi.pas 中封裝了一個(gè) TAP

52、IDataShare接口類,供應(yīng)用程序員在編寫服務(wù)端插件時(shí)調(diào)用數(shù)據(jù)棧請(qǐng)參考本資料的“8.8、數(shù)據(jù)共享交換接口 API”一節(jié)。的 API 函數(shù)。關(guān)于此接口類的詳細(xì)功能和用法,1.10、插件的安全性服務(wù)端插件編寫完成、并將.dll 部署到服務(wù)端之后,有多種方法可以這些插件的安全性:安全性驗(yàn)證通過的調(diào)用、安全性驗(yàn)證失敗的調(diào)用。1)、插件對(duì)于 C/S 三層服務(wù)插件,可以在插件時(shí)指定其,然后在對(duì)它的 RPC 調(diào)用時(shí),就需要指定此調(diào)用插件。中間件在收到 RPC 調(diào)用請(qǐng)求時(shí),會(huì)檢查的正確性,如發(fā)現(xiàn)不對(duì),就會(huì)拒絕2)、特殊的調(diào)用參數(shù)插件可以要求調(diào)用方傳入特殊的標(biāo)記才認(rèn)為是合法的調(diào)用,這也是一種很常見的確保調(diào)用

53、安全的措施,插件導(dǎo)出函數(shù)處檢查傳入的參數(shù)包里若不包含調(diào)用標(biāo)記,則拒絕繼續(xù)執(zhí)行,直接返回執(zhí)行失敗。12 / 309QuickBurro 從入門到精通 - 中間件服務(wù)端高級(jí)編程所有© 樵夫軟件開發(fā)3)、應(yīng)用業(yè)務(wù)權(quán)限驗(yàn)證可以將應(yīng)用程序相關(guān)的安全驗(yàn)證信息包含在調(diào)用參數(shù)里傳到插件,插件在處理業(yè)務(wù)邏輯時(shí)先判定安全驗(yàn)證信息是否,是,繼續(xù)處理,否則拒絕繼續(xù)執(zhí)行。二、C/S 三層服務(wù)插件開發(fā)2.1、C/S 三層服務(wù)插件的接口規(guī)范這是一類 QuickBurro 中間件中最早實(shí)現(xiàn)的服務(wù)端插件類別,功能強(qiáng)大、細(xì)節(jié)完善、使用廣泛,主要為VCL 三層架構(gòu)應(yīng)用開發(fā)提供公用功能服務(wù)和應(yīng)用相關(guān)的業(yè)務(wù)邏輯處理服務(wù),其接

54、口規(guī)范如下:模塊類別:標(biāo)準(zhǔn) Windows 動(dòng)態(tài)庫(kù)(.DLL)開發(fā)工具:Delphi 6 起到最新版 Delphi,都支持插件用途:VCL 三層架構(gòu)客戶端程序功能服務(wù)、服務(wù)端計(jì)劃任務(wù)、或消息觸發(fā)服務(wù)命名規(guī)則:普通文件名,建議文件名長(zhǎng)度<64 字符,全路徑長(zhǎng)度<=96 字符內(nèi)存管理:FastMM4(插件工程 Uses 的第一個(gè)單元線程模式:多線程及單線程均支持,取決于插件的駐留模式:即時(shí)加載不駐留、駐留內(nèi)存、用戶程序Fastmm4) 方式駐留三種方式任選安全:驗(yàn)證及插件內(nèi)調(diào)用標(biāo)志驗(yàn)證等方式:需要接口標(biāo)準(zhǔn):Stdcall(參數(shù)從右至左入棧,Pascal 標(biāo)準(zhǔn)) 調(diào)用方式:同步調(diào)用、異步

55、調(diào)用都支持調(diào)用標(biāo)識(shí):插件時(shí)指定的插件標(biāo)識(shí)代碼導(dǎo)出函數(shù):RemoteProcess(主函數(shù))、ApiInitialize(初始化)、ApiUninitialize(善后) 部署方式:靜態(tài)部署+運(yùn)行時(shí)動(dòng)態(tài)部署,支持熱插拔調(diào)用方法:TDllPlugin 控件的 BinaryRPC 方法及 AsyncRPC 方法、模塊觸發(fā)器調(diào)用、計(jì)劃任務(wù)調(diào)用以及動(dòng)態(tài)調(diào)用DLL 方式接口參數(shù):TQBParcel 容器對(duì)象之一傳入?yún)?shù)、另一 TQBParcel 容器對(duì)象傳出參數(shù),參數(shù)個(gè)數(shù)不固定,應(yīng)用程序員自行約定API 函數(shù):可調(diào)用 VCLSDK 下提供的全部 API 函數(shù)庫(kù)單元延遲卸載:非駐留模式自動(dòng)支持延遲卸載共享數(shù)據(jù):私有數(shù)據(jù)棧、公用數(shù)據(jù)棧對(duì)于 C/S 三層服務(wù)插件,中間件服務(wù)程序除了將客戶端調(diào)用提交的參數(shù)通過TQBParcel 對(duì)象傳遞給插件外,還會(huì)將中間件的一些重要系統(tǒng)參數(shù)、API 函數(shù)基地址等信息一并隨參數(shù)包傳遞到插件,插件編程時(shí),除了從參數(shù)包中取普通請(qǐng)求參數(shù)外,還可以取用這些系統(tǒng)信息:API 函數(shù)基地址: 通信密鑰:被調(diào)插件文件名:本節(jié)點(diǎn)代碼:InParcel.PutQBIntegerGoods('Callback_Proc_List',QBInteger(NodeService.ExportAddrList0);InParcel.PutAnsiStringGoods

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論