張志強, 鄭 濤, 王偉鈞,楊晉浩
(成都大學 信息科學與工程學院,四川 成都 610106)
目前,在證券公司的數(shù)據(jù)交易系統(tǒng)中,其數(shù)據(jù)查詢是系統(tǒng)非常重要的功能之一.同時,由于證券交易系統(tǒng)的數(shù)據(jù)量往往非常龐大,因此,提高查詢效率是數(shù)據(jù)查詢功能模塊設計的關鍵[1].針對不同環(huán)境下的數(shù)據(jù)訪問接口,科研人員進行了相關的研究與設計,并取得了一系列成果[2-8],但針對證券數(shù)據(jù)交易系統(tǒng)的數(shù)據(jù)查詢訪問接口的研究和設計很少.對此,本研究采用分層化策略來設計數(shù)據(jù)訪問接口,在客戶端層與服務器端數(shù)據(jù)層之間設計數(shù)據(jù)訪問接口的中間層實現(xiàn)數(shù)據(jù)查詢流程,通過該數(shù)據(jù)訪問接口的實現(xiàn),使得查詢過程具有分層化查詢、查詢數(shù)據(jù)精簡化獲取等特點,從而提高了數(shù)據(jù)查詢的效率.
本研究數(shù)據(jù)訪問接口的體系架構(gòu)如圖1所示.
圖1數(shù)據(jù)訪問接口的體系架構(gòu)
如圖1所示,本數(shù)據(jù)訪問接口實現(xiàn)了客戶端層和服務器端數(shù)據(jù)層之間的中間層設計.通過該中間層,當客戶端利用瀏覽器請求查詢時,查詢參數(shù)以get請求方式通過瀏覽器地址進行傳遞,數(shù)據(jù)訪問接口接收查詢參數(shù).在數(shù)據(jù)訪問接口中,通過存儲過程調(diào)用接口將查詢參數(shù)傳遞到服務器端數(shù)據(jù)層的存儲過程進行數(shù)據(jù)查詢,查詢結(jié)果返回到存儲過程調(diào)用接口.為了向客戶端瀏覽器返回精簡的查詢數(shù)據(jù)結(jié)果,數(shù)據(jù)訪問接口在接收到查詢結(jié)果數(shù)據(jù)后,需要進行后期處理,其先將查詢結(jié)果數(shù)據(jù)通過對象數(shù)據(jù)封裝模塊封裝到數(shù)據(jù)對象中,然后再通過JSON封裝模塊將數(shù)據(jù)對象以JSON數(shù)據(jù)格式進行封裝并產(chǎn)生JSON字符串,最后將JSON字符串返回到客戶端瀏覽器,從而實現(xiàn)精簡的查詢數(shù)據(jù)結(jié)果.在后期,客戶端瀏覽器接收了JSON數(shù)據(jù)后,進行前端解析,并最終將查詢數(shù)據(jù)在Web端或移動端瀏覽器以設定的樣式進行顯示.這種分層化的設計可以使數(shù)據(jù)查詢壓力分散在不同的地方.
為了實現(xiàn)數(shù)據(jù)訪問接口的通用性參數(shù)控制,本研究將數(shù)據(jù)庫服務器連接和登錄信息參數(shù)存儲在配置參數(shù)文件中.其配置參數(shù)文件的內(nèi)容格式說明如表1所示.同時,多個配置參數(shù)以XML格式存儲在文件中,其存儲結(jié)構(gòu)形式如圖2所示.
表1 配置參數(shù)文件的格式說明
圖2參數(shù)配置文件的存儲形式
在數(shù)據(jù)訪問接口中,首先利用DOM接口進行配置參數(shù)文件的讀取操作,然后根據(jù)讀取的參數(shù)值實現(xiàn)數(shù)據(jù)庫服務器的連接和登錄.由此可見,通過動態(tài)修改配置參數(shù)文件內(nèi)容的方式,可以使得數(shù)據(jù)訪問接口具有動態(tài)設置權(quán)限賬戶連接和登錄數(shù)據(jù)庫服務器的通用能力.此外,對配置參數(shù)文件的內(nèi)容進行修改后,將參數(shù)配置文件的路徑地址作為參數(shù)傳遞到配置參數(shù)讀取程序,從而完成配置參數(shù)的讀取.
通常,在證券數(shù)據(jù)交易系統(tǒng)中,數(shù)據(jù)表的數(shù)據(jù)量非常大,而且查詢數(shù)據(jù)往往來自多個表的關聯(lián),如果在Web服務器中執(zhí)行查詢操作會給Web服務器帶來較大的壓力.為了降低Web服務器的壓力,可將數(shù)據(jù)查詢操作放在數(shù)據(jù)層的數(shù)據(jù)庫服務器中,通過由客戶查詢需求設計的存儲過程來完成數(shù)據(jù)查詢的任務.因此,在數(shù)據(jù)訪問接口的設計中,需要設計存儲過程調(diào)用接口模塊,通過該模塊,根據(jù)客戶的不同查詢需求,調(diào)用相應存儲過程完成查詢?nèi)蝿?在存儲過程調(diào)用接口模塊設計中,首先判斷數(shù)據(jù)庫連接和登錄操作是否完成,如果沒有完成,則完成相應的數(shù)據(jù)庫連接和登錄操作,然后獲取執(zhí)行參數(shù),這里執(zhí)行參數(shù)由3部分構(gòu)成,分別是存儲過程名、存儲過程in參數(shù)列表及存儲過程out參數(shù)個數(shù).由in參數(shù)列表動態(tài)構(gòu)建和設置存儲過程的in參數(shù),由out參數(shù)個數(shù)動態(tài)構(gòu)建和設置存儲過程的out參數(shù)類型,調(diào)用存儲過程,獲取并返回查詢結(jié)果集.其算法設計如下:
GetInfo(storageprogramname,In-pram,Out-pram-length)
參數(shù)說明:
storageprogramname:存儲過程名
In-pram:存儲過程in參數(shù)列表
Out-pram-length:存儲過程out參數(shù)的個數(shù)值
begin
如果沒有完成數(shù)據(jù)庫的連接和登錄操作,則先完成相關操作;
String str=″{call″ + storageprogramname + ″(″;
repeat
str=str + ″?,″;
untile In-pram參數(shù)列表處理完;
repeat
str=str + ″?,″;
until Out-pram-length - 1處理完;
str = str + ″?)}″;
st =conn.prepareCall(str);
repeat
設置st的in參數(shù)值;
until In-pram參數(shù)列表處理完;
repeat
設置st的out參數(shù)值類型;
until Out-pram-length參數(shù)處理完;
結(jié)果集rs執(zhí)行存儲過程storageprogramname;
return結(jié)果集rs;
end
存儲過程返回查詢結(jié)果集后,需要將查詢結(jié)果集的數(shù)據(jù)封裝到數(shù)據(jù)對象中,這樣便于為后期JSON數(shù)據(jù)封裝處理提供數(shù)據(jù)源.在數(shù)據(jù)對象的封裝處理過程中,首先根據(jù)查詢需求,設計出數(shù)據(jù)對象的實體類,然后根據(jù)獲取的查詢結(jié)果集,將其數(shù)據(jù)寫入實體類的對象中.
以客戶信息查詢?yōu)槔?,在客戶信息查詢需求中,客戶信息由客戶基本信息和客戶推薦產(chǎn)品信息構(gòu)成,客戶信息查詢數(shù)據(jù)類的UML設計如圖3所示.
圖3客戶信息查詢數(shù)據(jù)類的UML結(jié)構(gòu)
從圖3可知,客戶查詢數(shù)據(jù)類ClientInfo的對象包含了經(jīng)理數(shù)據(jù)類ManagerInfo的對象(manager)和客戶產(chǎn)品推薦類Recommends的對象(recommends),其中,類ClientInfo與類ManagerInfo之間是1∶1的關聯(lián)關系,類ClientInfo與類Recommends之間是1∶n的關聯(lián)關系.這些類之間的關聯(lián)關系也體現(xiàn)了數(shù)據(jù)庫的多表關聯(lián)查詢的形式.客戶信息查詢的數(shù)據(jù)對象封裝算法設計如下:
getClients (rs1,rs2)
參數(shù)說明:
rs1:客戶基本信息查詢結(jié)果集;
rs2:客戶推薦產(chǎn)品信息查詢結(jié)果集
begin
構(gòu)建ClientInfo類的對象集合clients和Recommends類的對
象集合res;
i←0;
repeat
c←創(chuàng)建ClientInfo對象;
將rs1的第i條數(shù)據(jù)記錄的ClientInfo對象基本分量寫
入c;
m←創(chuàng)建ManagerInfo對象;
將rs1的第i條數(shù)據(jù)記錄的ManagerInfo對象分量寫入m;
c的ManagerInfo對象分量manager←m;
j←0;
清空res;
repeat
r←創(chuàng)建Recommends對象;
將rs2的第j條數(shù)據(jù)記錄的Recommends對象分量
寫入r;
res←r;
j←j + 1;
until rs2結(jié)果集中所有數(shù)據(jù)記錄處理結(jié)束;
c的Recommends對象分量recommends←res;
clients←c;
i←i + 1;
until rs1結(jié)果集中所有數(shù)據(jù)記錄處理結(jié)束;
return clients;
end
在本算法中,rs1和rs2都是通過GetInfo接口獲取的查詢結(jié)果集,最后根據(jù)rs1和rs2的結(jié)果集,將相應數(shù)據(jù)封裝到客戶信息查詢數(shù)據(jù)對象集合clients中.
一般而言,在證券數(shù)據(jù)交易系統(tǒng)的查詢中,為了提高查詢效率,在客戶端瀏覽器進行查詢后,客戶端瀏覽器只需要接收精簡的查詢結(jié)果數(shù)據(jù),而不需要接收臃腫的html數(shù)據(jù)代碼.為了實現(xiàn)這種策略,需要將查詢結(jié)果數(shù)據(jù)封裝為JSON數(shù)據(jù),然后返回給客戶端瀏覽器.由于JSON數(shù)據(jù)格式是一種輕量級的數(shù)據(jù)交換格式,其廣泛應用于網(wǎng)頁數(shù)據(jù)的存儲和交換文本信息,客戶端很容易利用JS解析JSON數(shù)據(jù)并在客戶端瀏覽器按照指定樣式顯示數(shù)據(jù).因此,客戶端瀏覽器接收JSON數(shù)據(jù),有利于后期的解析處理.
在數(shù)據(jù)對象封裝模塊中,客戶查詢數(shù)據(jù)已經(jīng)封裝到數(shù)據(jù)對象中,在JSON數(shù)據(jù)封裝模塊中,根據(jù)數(shù)據(jù)對象,將查詢數(shù)據(jù)以JSON格式進行封裝.盡管專門有封裝JSON數(shù)據(jù)的類庫,但由于查詢結(jié)果數(shù)據(jù)的結(jié)構(gòu)復雜多樣,直接使用類庫產(chǎn)生特殊格式的JSON數(shù)據(jù)會比較困難.因此,本研究設計了特定的JSON數(shù)據(jù)封裝模塊,其以數(shù)據(jù)對象為數(shù)據(jù)源,進行JSON數(shù)據(jù)封裝,并最終形成JSON字符串.JSON數(shù)據(jù)封裝模塊算法設計如下:
ClentsJsonString(list)
參數(shù)說明:
list:客戶信息查詢數(shù)據(jù)對象集合,其為getClients算法的clients
begin
if list集合中數(shù)據(jù)對象個數(shù) = 1 then
將list集合中第1條數(shù)據(jù)記錄的ClientInfo對象基本分
量按照JSON格式構(gòu)建字符串JsonString1;
j←0;
repeat
recommends←獲取list集合中第1個數(shù)據(jù)記錄的第
j個Recommends對象分量;
將recommends按照JSON格式構(gòu)建字符串
JsonString2;
JsonStr集合←JsonString2;j←j + 1;
until list集合中第1條數(shù)據(jù)記錄的Recommends對象分
量處理結(jié)束;
根據(jù)JsonStr集合構(gòu)建嵌套結(jié)構(gòu)的字符串JsonString3;
JsonString←JsonString1 + JsonString3;
else if list集合中數(shù)據(jù)對象個數(shù) > 1 then
i←0;
repeat
clientInfo←獲取list集合中第i條數(shù)據(jù)記錄的
ClientInfo對象基本分量;
將clientInfo按照JSON格式構(gòu)建字符串JsonString1;
j←0;清空JsonStr集合;
repeat
recommends←獲取list集合中第i條數(shù)據(jù)記錄
的第j個Recommends對象分量;
將recommends按照JSON格式構(gòu)建字符串JsonString2;
JsonStr集合←JsonString2;j←j + 1;
until list集合中第i條數(shù)據(jù)記錄的Recommends對
象分量處理結(jié)束;
根據(jù)JsonStr集合構(gòu)建嵌套結(jié)構(gòu)的字符串JsonString3;
JsonString4←JsonString1 + JsonString3;
JsonStr2集合←JsonString4;
i←i + 1;
until list集合的數(shù)據(jù)對象處理結(jié)束;
根據(jù)JsonStr2集合構(gòu)建嵌套結(jié)構(gòu)的字符串JsonString5;
JsonString←JsonString5;
end if
return JsonString;
end
在ClentsJsonString算法中,list為getClients算法處理的數(shù)據(jù)對象集合clients,其由1個或多個數(shù)據(jù)對象構(gòu)成.ClentsJsonString算法根據(jù)數(shù)據(jù)對象集合list利用JSON數(shù)據(jù)格式進行JSON數(shù)據(jù)封裝,在封裝過程中,會根據(jù)數(shù)據(jù)對象之間的關聯(lián),構(gòu)建具有嵌套結(jié)構(gòu)的JSON字符串JsonString.
在證券數(shù)據(jù)交易系統(tǒng)中,客戶通過客戶端瀏覽器以get請求方式調(diào)用數(shù)據(jù)訪問接口進行查詢,數(shù)據(jù)訪問接口首先在瀏覽器的地址信息中獲取查詢的參數(shù),然后將查詢參數(shù)傳遞給存儲過程調(diào)用接口模塊執(zhí)行查詢,接著將查詢結(jié)果集傳遞到數(shù)據(jù)對象封裝模塊進行數(shù)據(jù)對象的封裝處理,接著將封裝后的數(shù)據(jù)對象傳遞到JSON數(shù)據(jù)封裝模塊進行JSON數(shù)據(jù)封裝處理,最后將封裝后的JSON字符串返回到客戶端瀏覽器.在后期,可以由客戶端的JS進行解析操作.由于數(shù)據(jù)訪問接口是通過網(wǎng)絡請求方式調(diào)用,因此采用Servlet方式設計,其部署在Tomcat的Web服務器端.數(shù)據(jù)處理流程如圖4所示.
圖4數(shù)據(jù)訪問接口的數(shù)據(jù)處理流程
在測試中,數(shù)據(jù)訪問接口采用Java編程實現(xiàn),Web服務器采用Tomcat 7.0進行部署,數(shù)據(jù)庫服務器系統(tǒng)采用SQL Server 2008 R2,數(shù)據(jù)庫連接與登錄的參數(shù)配置文件內(nèi)容如圖2所示,其部署在Tomcat服務器中.
接口設計中,首先需要根據(jù)客戶的查詢需求設計不同的多個數(shù)據(jù)訪問接口,本研究以客戶信息查詢需求為例,設計并測試了客戶信息查詢數(shù)據(jù)訪問接口的運行結(jié)果.在數(shù)據(jù)庫服務器系統(tǒng)中部署了相應的數(shù)據(jù)表和存儲過程,其中,ClientInfo表(用戶信息表)如表2所示,ManagerInfo表(客戶經(jīng)理信息表)如表3所示,ClientRecommendation表(客戶推薦產(chǎn)品表)如表4所示,客戶基本信息查詢存儲過程如圖5所示,客戶推薦產(chǎn)品信息查詢存儲過程如圖6所示.
表2 ClientInfo表
表3 ManagerInfo表
表4 ClientRecommendation表
圖5客戶基本信息查詢存儲過程
圖6客戶推薦產(chǎn)品信息查詢存儲過程
客戶端瀏覽器查詢界面如圖7所示,在客戶端瀏覽器的http請求地址中,testServlet為數(shù)據(jù)訪問接口名、Id為查詢參數(shù),其為客戶身份編號(以get請求方式傳遞查詢參數(shù)到testServlet接口),查詢結(jié)果以JSON數(shù)據(jù)格式進行嵌套封裝后返回到客戶端瀏覽器,從圖7可以看出,返回到客戶端瀏覽器的數(shù)據(jù)不再是冗余的html代碼,而是精簡的可解析查詢數(shù)據(jù).
圖7數(shù)據(jù)訪問接口查詢的返回結(jié)果
針對證券數(shù)據(jù)交易系統(tǒng)查詢的特殊性,本研究采用了分層的數(shù)據(jù)訪問接口,通過該接口的實現(xiàn)可以看出,一方面分散了各部分的查詢壓力,另一方面也精簡了查詢結(jié)果的返回值,進而從整體上提高了查詢效率.本研究為證券數(shù)據(jù)交易系統(tǒng)的查詢功能提供了一種可實例化的設計模式.