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

下載本文檔

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

文檔簡介

1、第四篇中間件服務(wù)端高級編程QuickBurro 中間件從入門到精通本篇資料首先介紹 QuickBurro 中間件的各類服務(wù)端插件框架的接口標(biāo)準(zhǔn)、開發(fā)模板、注意事項及編程實例,然后給出了中間件 件所提供的各類 API 函數(shù)的技術(shù)細(xì)節(jié)及其用法示例。服務(wù)程序與重要接口插浙江-樵夫樵夫軟件開發(fā)2017-09-07QuickBurro 從入門到精通 - 中間件服務(wù)端高級編程所有© 樵夫軟件開發(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 中的虛擬動態(tài)頁面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)頁客戶端里調(diào)用 Web 服務(wù)插件示例413.8 、ISAPI 標(biāo)準(zhǔn)的Web 服務(wù)插件48四、移動服務(wù)插件開發(fā)524.1 、Multipart 格式的Web 請求534.2 、移動服務(wù)插件的接口規(guī)范534.3 、移動服務(wù)插件模板文件544.4 、移動服務(wù)插件的客戶端調(diào)用方法59五、Lazarus 服務(wù)插件開發(fā)645.1、Lazarus 服務(wù)插件接口規(guī)范641 / 309QuickBurro 從入門到精通 - 中間件服務(wù)端高級編程所有© 樵夫軟件開發(fā)5.2 、Lazarus 服務(wù)插件模板文件645.3 、TLazRPC 遠過程調(diào)用控件695.4 、

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

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

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

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

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

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

10、話,就不必與這些糾結(jié)在一起的技術(shù)問題打交道直接使用插件框架、編寫一下插件并調(diào)用,就可以了。1.2、服務(wù)端插件的種類上節(jié)這樣的服務(wù)端插件框架在 QuickBurro 中間件主服務(wù)中存在多個實例,即 C/S 三層服務(wù)插件框架、Web 服務(wù)插件框架、WebSocket 服務(wù)插件框架、移動開發(fā)服務(wù)插件框架等,它們的實現(xiàn)原理都一樣,只是在接口規(guī)范上存在一些很小的差異。然后,與這些插件框架實例相對應(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è)置來確保安全性;支持駐留/非駐留運行方式;支持同步/異步方式調(diào)用。除了被客戶端調(diào)用之外,這類插件還支持以計劃任務(wù)、觸發(fā)消息等方式進行觸發(fā)執(zhí)行。2)、Web 服務(wù)插件這是一類通過 HTTP/HTTPS 協(xié)議調(diào)用的服務(wù)端插件。這類插件也可為駐留內(nèi)存以應(yīng)對高強度頻繁調(diào)用的需求,但不時也能直接調(diào)用(但不駐留內(nèi)存);另外,對它們的調(diào)用通過自動的“虛擬動態(tài)頁面”URL 的形式進行;調(diào)用時參數(shù)交換通過 Web 表單、Json、Xml 等方式

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

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

14、l 服務(wù)插件另外,QuickBurro 中間件中又以“移動服務(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ù)格式進行客戶端/中間層交互,所傳輸?shù)男畔⒖偸切枰D(zhuǎn)換為流式數(shù)據(jù)的形式進行。一般地,以容器類特有的方式組織的數(shù)據(jù)轉(zhuǎn)換為流式數(shù)據(jù)的過程,稱為序列化,反之則叫反序列化(或叫對象化)。在

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

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

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

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

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

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

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

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

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

24、經(jīng)常需要使用:l序列化方法序列化為字符串(不含回車換行制表符) function ToString (): Ansistring ; overload; override; 序列化為字符串(含回車換行制表符)function ToString2 (indentFactor : integer): Ansistring; overload;序列化為字符串(含回車換行制表符,帶縮進)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;序列化到包裹對象的字段function SaveToParcel(aQBParcel: TQBParcel; GoodsName: Ansistring; OutFormat: integer): boolean;l反序列化方法從字符串反序列化為 Json 對象constructor Create (s : Ansistring); overload; 從流數(shù)據(jù)反序列

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

27、IXMLDocument,可以用以下方法進行序列化/反序列化處理: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ù)端高級編程所有© 樵夫軟件開發(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 對象: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ù)據(jù)容器之間、容器與流對象/內(nèi)存塊/字符串之間的實用轉(zhuǎn)換函數(shù),請各位適當(dāng)熟悉一下,編程時方便:lVclsdkqbcommon.pas 下字符串與流對象之間的轉(zhuǎn)儲procedure Str2Stream(Str: Ansistring; var aStream: TMemoryStream);procedure Stream2Str(aStream: TMemoryStream; var aStr: Ansistring);字符串與文件之間的轉(zhuǎn)儲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);字符串緩沖與包裹對象的轉(zhuǎn)儲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 與流對象之間的轉(zhuǎn)換function VariantToStream (const v: OleVariant; Stream:

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

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

35、set: TDataset): OleVariant;8 / 309QuickBurro 從入門到精通 - 中間件服務(wù)端高級編程所有© 樵夫軟件開發(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ù)集與流對象之間的轉(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ù)集與其他對象之間的轉(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ù)集與流對象間的轉(zhuǎn)換function ads2LazStream(ads: TAdoDataset; aStream: TMemoryStream): boolean; function LazStream2ads(aStream: TMemoryStream; ads: TAdoDataset): boolean;ADO 數(shù)據(jù)集與文件之間的轉(zhuǎn)儲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ù)插件類別的不同,會在不同的外部條件下被調(diào)用9 / 309QuickBurro 從入門到精通 - 中間件服務(wù)端高級編程所有© 樵夫軟件開發(fā)執(zhí)行,通常表現(xiàn)為以下幾種情況:1)、被客戶端調(diào)用時當(dāng) VCLSDK 下的TDllPlugin 控件、TQBHttps 控件、以及“QuickBurro Extended”組

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

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

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

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

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

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

49、 API 函數(shù)庫單元(新版,推薦使用)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ù)庫單元支付寶支付接口 API 函數(shù)庫單元語音接口 API 函數(shù)庫單元FireDAC 數(shù)據(jù)庫引擎 API 函數(shù)庫單元Lazarus 服務(wù)插件接口

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

51、需求,QuickBurro 中間件系統(tǒng)中實現(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ù)棧”在這里是指一種用于 刪除失效了的數(shù)據(jù)等等,是 QuickBurro的公用數(shù)據(jù)區(qū),可以向其中“寄存”數(shù)據(jù)、檢索數(shù)據(jù)、從中為了實現(xiàn)服務(wù)端程序的各個部分(特別是插件之間)進行數(shù)據(jù)共享交換的一種數(shù)據(jù)結(jié)構(gòu)及技術(shù)。對于數(shù)據(jù)棧的使用,我們專門在服務(wù) API 函數(shù)庫單元 qbserviceapi.pas 中封裝了一個 TAP

52、IDataShare接口類,供應(yīng)用程序員在編寫服務(wù)端插件時調(diào)用數(shù)據(jù)棧請參考本資料的“8.8、數(shù)據(jù)共享交換接口 API”一節(jié)。的 API 函數(shù)。關(guān)于此接口類的詳細(xì)功能和用法,1.10、插件的安全性服務(wù)端插件編寫完成、并將.dll 部署到服務(wù)端之后,有多種方法可以這些插件的安全性:安全性驗證通過的調(diào)用、安全性驗證失敗的調(diào)用。1)、插件對于 C/S 三層服務(wù)插件,可以在插件時指定其,然后在對它的 RPC 調(diào)用時,就需要指定此調(diào)用插件。中間件在收到 RPC 調(diào)用請求時,會檢查的正確性,如發(fā)現(xiàn)不對,就會拒絕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ù)端高級編程所有© 樵夫軟件開發(fā)3)、應(yīng)用業(yè)務(wù)權(quán)限驗證可以將應(yīng)用程序相關(guān)的安全驗證信息包含在調(diào)用參數(shù)里傳到插件,插件在處理業(yè)務(wù)邏輯時先判定安全驗證信息是否,是,繼續(xù)處理,否則拒絕繼續(xù)執(zhí)行。二、C/S 三層服務(wù)插件開發(fā)2.1、C/S 三層服務(wù)插件的接口規(guī)范這是一類 QuickBurro 中間件中最早實現(xiàn)的服務(wù)端插件類別,功能強大、細(xì)節(jié)完善、使用廣泛,主要為VCL 三層架構(gòu)應(yīng)用開發(fā)提供公用功能服務(wù)和應(yīng)用相關(guān)的業(yè)務(wù)邏輯處理服務(wù),其接

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

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

溫馨提示

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

最新文檔

評論

0/150

提交評論