摘 要:電站實時信息的綜合瀏覽對調(diào)整電能的生產(chǎn)具有重要作用。本系統(tǒng)采用Java的RMI分布式對象及數(shù)據(jù)庫連接池技術(shù)來實現(xiàn)廠內(nèi)信息的綜合瀏覽。Java RMI應(yīng)用是CORBA技術(shù)的純Java應(yīng)用之一,整個系統(tǒng)基于B/S結(jié)構(gòu),客戶端WEB瀏覽器中的Applet向RMI服務(wù)器發(fā)出數(shù)據(jù)請求,RMI服務(wù)器通過數(shù)據(jù)庫連接池訪問數(shù)據(jù)庫,然后將結(jié)果回應(yīng)給客戶端,客戶端由Applet進行顯示。整個系統(tǒng)是分布式的,各部分耦合性小,服務(wù)器和客戶端開發(fā)和擴充可以相對獨立進行。實踐證明,該系統(tǒng)運行十分穩(wěn)定和可靠。
關(guān)鍵詞:Java;RMI;數(shù)據(jù)庫連接池
引 言
隨著信息技術(shù)的發(fā)展,火電站信息系統(tǒng)的實時性與綜合性都有進一步的提高。為了能夠隨時隨地瀏覽廠內(nèi)信息,就需要一套獨立的系統(tǒng),它從廠內(nèi)監(jiān)控信息系統(tǒng)(SIS)及管理信息系統(tǒng)(MIS)的數(shù)據(jù)庫中通過數(shù)據(jù)庫連接池獲得所需數(shù)據(jù),并進行處理后顯示。由于它獨立于廠內(nèi)系統(tǒng)以外,并且通過互聯(lián)網(wǎng)向外發(fā)布,因此,可以不受廠內(nèi)條件的限制,方便地進行本地或遠程網(wǎng)上瀏覽。
1 系統(tǒng)設(shè)計思想
該系統(tǒng)采用Java語言開發(fā)。Java語言的安全性、穩(wěn)定性及豐富方便的網(wǎng)絡(luò)功能,使其可與網(wǎng)絡(luò)緊密無縫結(jié)合,更重要的是Java語言的二進制字節(jié)代碼運行于(JVM)Java虛擬機上,而不是直接運行于本地操作平臺上,故其與操作平臺無關(guān),這使Java語言開發(fā)的系統(tǒng)具有良好的跨平臺的可移植性、分布性和擴展性。這樣,無論是在unix,linux操作系統(tǒng),還是在windows NT,win2K,windows9x操作系統(tǒng)下運行,其字節(jié)代碼都不需要重新編譯.隨著很多大型系統(tǒng)都升級到unix操作平臺上,采用Java的優(yōu)勢很快就可體現(xiàn)出來??蛻舳瞬捎脼g覽器訪問的方式,Java客戶端的Applet小應(yīng)用程序可以直接內(nèi)嵌于Web瀏覽器中,用戶不需安裝專門客戶端軟件。所有的生產(chǎn)管理信息統(tǒng)一通過Web服務(wù)器向外發(fā)布,用戶只需通過權(quán)限認證即可通過瀏覽器IE或Netscape進行瀏覽。
系統(tǒng)在結(jié)構(gòu)上采用Java語言的RMI分布式對象技術(shù).Java RMI(Remote method Invoke)采用遠程方法調(diào)用以獲得遠程數(shù)據(jù)。由于所有的數(shù)據(jù)庫訪問及復(fù)雜算法均在Java RMI服務(wù)器上進行,客戶端只需進行顯示,這就減輕了客戶機的工作壓力,從而實現(xiàn)了“瘦客戶”連接.而且因使用分布式對象,降低了系統(tǒng)的復(fù)雜性,使整個系統(tǒng)模塊分明,更易維護,這對系統(tǒng)的擴充升級極為有利。若增加功能,只需修改或添加遠程對象即可,而不會影響客戶端。
系統(tǒng)客戶端采用Java的Applet。Applet可以內(nèi)嵌在網(wǎng)頁中,而不用專門開發(fā)客戶端軟件。采用Applet的雙緩存技術(shù)可以使畫面動態(tài)刷新,無閃爍,圖形界面的形式和內(nèi)容可以進行復(fù)雜的組態(tài)配置。界面友好,柔性強。
整個系統(tǒng)采用B/S的3層模式,并運用分布對象技術(shù)進行設(shè)計,其層次結(jié)構(gòu)如圖1所示。
客戶端訪問Web服務(wù)器時,Web服務(wù)器將訪問轉(zhuǎn)交給信息綜合瀏覽系統(tǒng)的RMI服務(wù)器,RMI服務(wù)器采用數(shù)據(jù)庫連接池通過jdbc-odbc橋從SIS與MIS系統(tǒng)數(shù)據(jù)庫服務(wù)器中取出客戶端所要顯示的原始數(shù)據(jù),經(jīng)過Java RMI服務(wù)器進行統(tǒng)計、計算,以獲得需要顯示的數(shù)據(jù),通過遠程方法的返回值,返回客戶端瀏覽中的Java Applet中,再由Applet進行畫面顯示點的定位及顯示。
2 RMI遠程方法調(diào)用
2.1 RMI分布式對象原理
RMI(Remote method Invoke)分布式對象技術(shù)是指對位于遠程機器上的對象方法進行調(diào)用,而不必將這些對象移回調(diào)用方法所在的客戶機上。它是CORBA技術(shù)的一種純Java應(yīng)用。當客戶機代碼想對遠程對象調(diào)用遠程方法時,它就像調(diào)用了普通的Java方法。該方法被封裝在一個稱為存根(stub)的代理對象(surrogate object)中.存根位于客戶機上。存根首先取得遠程方法中使用的參數(shù),并將其打包為字節(jié)塊,每個參數(shù)的打包使用了獨立于設(shè)備的編碼機制,接著使用對象序列化機制來實現(xiàn)參數(shù)序列化,并向服務(wù)器發(fā)送該信息。在服務(wù)端,有骨架(skeleton)對象,它將收到的信息反序列化,以獲得客戶機傳來的參數(shù),并將該參數(shù)傳遞給執(zhí)行遠程方法的實際對象,以調(diào)用期望的方法。然后,骨架對象將返回值序列化后發(fā)送給客戶機的存根對象,存根在反序列化從服務(wù)器上返回的值,就得到了遠程方法調(diào)用的返回值[1]。見圖2?! ?/p>
該過程很復(fù)雜,但它是完全自動進行的。對上層程序來說,它是透明的,就像調(diào)用本地方法一樣。上層應(yīng)用程序完全感受不到服務(wù)對象是在遠程機上。這也是RMI通訊比Socket通訊方便的地方。Socket通訊客戶機與服務(wù)器傳遞的只是字節(jié)流,其每部分字節(jié)流所代表的含義必須通過雙方自定義的協(xié)議才能互相知道。發(fā)送方與接收方都必須經(jīng)過接受時解碼與發(fā)送時編碼的過程,這對發(fā)送方與接受方來說都不透明,它們都必須自己維護該過程.此外,不透明的另一不足之處是Socket的客戶端與服務(wù)器端都必須維護連接狀態(tài),任何異常與超時,網(wǎng)絡(luò)都必須自己給出異常處理代碼,而在RMI通訊中,上述一切都由RMI協(xié)議維護,用戶不必操心,只需直接調(diào)用所需方法即可。
遠程對象中有遠程方法,即可被客戶端直接調(diào)用方法,也可以有本地方法。本地方法不能被客戶端遠程直接調(diào)用,但它可以被遠程方法調(diào)用,即客戶端可通過遠程方法調(diào)用遠程對象中的本地方法。
客戶程序需要對服務(wù)器對象進行控制處理,但實際上卻沒有該對象的拷貝,對象本身位于遠程服務(wù)器上,客戶只需要知道能對該對象執(zhí)行哪些操作,其能力可用接口函數(shù)表示.將服務(wù)器中能執(zhí)行的操作放入一個接口中,然后,由客戶與服務(wù)器共享該接口即可。這樣,客戶機就可以知道服務(wù)器中有哪些遠程方法可以調(diào)用[2]。
遠程對象的返回值既可以是數(shù)值也可以是對象,當返回值為對象時,若該對象為遠程對象,則返回值為該遠程對象的存根引用,源對象內(nèi)存空間在遠處機上;若返回值為非遠程對象,則返回為該對象的拷貝??蛻魴C及遠程機上各有一份與該種類型內(nèi)容相同的對象。
2.2 功能實現(xiàn)
RMI功能實現(xiàn)過程主要有以下幾個步驟。
1 建立DBServerInterface接口 該接口擴展自遠程類(Remote)接口,并聲明GetResult()為遠程方法.該方法拋出遠程異常(RemoteException).因為遠程方法實現(xiàn)于遠程服務(wù)器上,在與客戶端通訊時有很多網(wǎng)絡(luò)異常需要處理,例如網(wǎng)絡(luò)忙、連接超時等,客戶代碼必須知道這些情況[3,4].該接口只聲明(GetResult()方法,而并沒有實現(xiàn)該方法。
2 遠程服務(wù)器類DBServer 它擴展自接口DBServerInterface,并重載接口中的遠程方法GetR-esult().該服務(wù)器類共有一個遠程方法GetResult()、兩個本地方法QueryDB()和HandleData().出于安全性及降低復(fù)雜性考慮,客戶機無需連接數(shù)據(jù)庫,也無需獲得數(shù)據(jù)庫訪問權(quán)限.因此,采用遠程對象的本地方法QueryDB()負責(zé)訪問SqlServer數(shù)據(jù)庫,執(zhí)行數(shù)據(jù)庫操作,獲得顯示的原始數(shù)據(jù).該方法由遠程方法調(diào)用.本地方法Handle Data()負責(zé)對數(shù)據(jù)庫訪問的數(shù)據(jù)進行計算及將其統(tǒng)計后轉(zhuǎn)換成終要顯示的數(shù)據(jù),而遠程方法GetResult()則負責(zé)將以上兩個本地方法獲得的結(jié)果返回給客戶端。
3 創(chuàng)建DBServerInterface的骨架和存根 骨架和存根是服務(wù)器級的客戶級的類,它們都由RMI機使用,以獲得序列化參數(shù)和序列化結(jié)果.使用Java的rmic工具產(chǎn)生存根類DBServerInterfaceStub.class與骨架類DBServerInterface_Skel.class.它們負責(zé)客戶機與服務(wù)器之間的通訊。
4 使用引導(dǎo)程序(bootstrap registry service)登記遠程服務(wù)對象 其目的是使客戶機可以檢索到這些對象的存根并使用它們的服務(wù).將遠程服務(wù)器對象的引用傳給引導(dǎo)登記服務(wù),并給該對象指定一個名字,就登記了該遠程服務(wù)器對象。
5 啟動服務(wù)程序 客戶端程序在獲得遠程對象的存根后即可直接調(diào)用服務(wù)器程序上的遠程方法。
6 客戶端Applet 其在獲得遠程方法返回顯示數(shù)據(jù)后,進行點的定位與顯示。
2.3 運行過程
1 啟動服務(wù)器程序,服務(wù)器登記服務(wù)對象。DBServer dbserver=newDBServer();
Naming.bind(“DBServer”,dbserver);
2 客戶機訪問wed Server上的HTML頁面,該頁面中內(nèi)嵌Java Applet程序.這樣,Applet二進制字節(jié)代碼就被下載到客戶機上,由Web瀏覽器內(nèi)嵌的Java虛擬機(JVM)運行,在Applet程序的初始化代碼中,通過URL格式指定服務(wù)器名和對象名,獲得對象的存根。
DBServerInterface db=(DBServerInterface);
Naming.lookup(“RMI://www.server.com/
DBServer”);
………………………………
Vector vtDBResult=db.GetResult(szCondition);
接著,客戶端執(zhí)行db.GetResult()遠程方法.參數(shù)szCondition為查詢條件.該方法在服務(wù)器上運行,它首先調(diào)用服務(wù)器的本地方法QueryDB()訪問數(shù)據(jù)庫,取得顯示所需的原始數(shù)據(jù).然后,調(diào)用另一個本地方法HandleData()來處理原始數(shù)據(jù),將結(jié)果寫入Vector對象中,并將其作為返回值.該返回值通過GetResult()的返回值由RMI機制返回到客戶端。由于該返回值為Vector對象,不是遠程對象,因此,返回的不是它的存根,而是拷貝.以上過程盡管復(fù)雜,但在客戶端卻完全感受不到這一切,好像GetResult方法就在本地客戶機上一樣。,客戶端程序?qū)⒔Y(jié)果在客戶機上以適當?shù)姆绞斤@示出來。
3 數(shù)據(jù)庫連接池技術(shù)
在數(shù)據(jù)庫訪問中,若使用一個數(shù)據(jù)庫連接,則不能滿足多個客戶同時訪問的要求;而使用多個數(shù)據(jù)庫連接時,由于每個客戶機都產(chǎn)生一個數(shù)據(jù)庫連接,訪問結(jié)束后,又要將數(shù)據(jù)庫連接關(guān)閉。這樣頻繁連接然后斷開數(shù)據(jù)庫,會給數(shù)據(jù)庫服務(wù)器帶來沉重的負擔,使其性能下降,數(shù)據(jù)庫響應(yīng)速度變慢.這對于電站這種實時性要求很強的數(shù)據(jù)庫系統(tǒng)是極其不利的。鑒于以上分析,可考慮同時打開一定數(shù)目的數(shù)據(jù)庫連接,并一直保持打開狀態(tài)直到系統(tǒng)關(guān)閉.這樣,使用時可獲得一個連接句柄,使用結(jié)束就釋放該連接句柄,從而避免數(shù)據(jù)庫的頻繁打開、關(guān)閉,并可以保證多個客戶的并發(fā)連接請求.本系統(tǒng)的數(shù)據(jù)庫連接采用的就是這種數(shù)據(jù)庫連接池技術(shù)。其具體實現(xiàn)過程如下:
首先,在系統(tǒng)初始化時,打開n個數(shù)據(jù)庫連接(Connection),將這些連接的引用句柄放入一個隊列中,該隊列稱為連接池,并將這些連接的狀態(tài)全置為“閑”(free)。
其次,當系統(tǒng)中DBServer中的本地方法QueryDB()作為一個客戶訪問數(shù)據(jù)庫時,連接池就會檢查連接標志位,看是否有連接空閑.若有連接空閑,將該連接的引用句柄傳給客戶程序使用,并將其狀態(tài)位置為“忙”(busy);若沒有連接空閑,則新打開一個數(shù)據(jù)庫連接,將其引用句柄加入連接池,傳給客戶端使用,并將其標志位置為“忙”(busy)。此時,連接池的大小變?yōu)閚+1,直到連接池的連接上限為止.若某個客戶端使用完數(shù)據(jù)庫連接,并不需要將數(shù)據(jù)庫關(guān)閉,此時,只需將其引用句柄放回連接池,并將其標志位設(shè)為“閑”(free)即可。
,當系統(tǒng)退出時,遍歷連接池中連接,將其中標志位為“閑”(free)的連接全部關(guān)閉.若池中還有標志位為“忙”的連接,則延遲300ms后再將其關(guān)閉,以確保該次數(shù)據(jù)庫操作的完成。
使用數(shù)據(jù)庫連接池,限度地利用了已打開的數(shù)據(jù)庫連接,從而使數(shù)據(jù)庫系統(tǒng)性能顯著增強。
4 結(jié)束語
上述方案所設(shè)計的綜合查詢系統(tǒng)已在實際工程中獲得應(yīng)用.運行表明,該系統(tǒng)穩(wěn)定可靠,已完全達到各項要求。該系統(tǒng)在開發(fā)過程中遇到了一些問題,取得了一些經(jīng)驗。系統(tǒng)開發(fā)初期,由于沒有采用數(shù)據(jù)庫連接池,結(jié)果在多個用戶同時瀏覽系統(tǒng)時,系統(tǒng)的響應(yīng)極慢。針對上述問題,采用了數(shù)據(jù)庫連接池技術(shù),使問題得到圓滿解決。
本系統(tǒng)采用Java RMI的B/S3層結(jié)構(gòu),具有以下明顯的特點:
1 若采用兩層結(jié)構(gòu),使用Java Applet直接訪問數(shù)據(jù)庫,由于Java Applet的安全特性,Applet小應(yīng)用程序只能訪問源主機上的資源,即Applet所存在的那臺服務(wù)器上的資源,這勢必要將數(shù)據(jù)庫服務(wù)器也移植到Web服務(wù)器上,就會對數(shù)據(jù)庫服務(wù)器的性能及安全性造成極大隱患。同時,在客戶機上既要訪問數(shù)據(jù)庫又要處理數(shù)據(jù),勢必對客戶端的性能提出更高要求,這就需要配置性能較高的客戶機,從而造成資源的不合理配置。
2 若采用Java Socket鏈接槽連接,則傳送的全是字節(jié)流,因此,必須考慮適當?shù)臄?shù)據(jù)編碼方法和傳送的適當協(xié)議,客戶與服務(wù)器端都要進行相應(yīng)的編碼與解碼。Java RMI將網(wǎng)絡(luò)通訊細節(jié)封裝起來,對上層應(yīng)用程序是透明的,并擅長傳輸任何類型的對象,而不必局限于生硬的數(shù)據(jù)結(jié)構(gòu)。這樣,使系統(tǒng)更加模塊化,擴充和維護變得十分容易。
該系統(tǒng)所采用的Java RMI應(yīng)用是CORBA技術(shù)一種純Java應(yīng)用,屬于分布式對象技術(shù)的應(yīng)用之一,具有極強的分布性與可擴展性。如系統(tǒng)需要增加功能,只需擴充遠程接口的功能或增加遠程對象即可,對客戶端與服務(wù)器端的升級改造也可分別進行。但該系統(tǒng)也有一些局限性,就是它在進行擴充時不支持其他語言的遠程對象,而只支持Java語言開發(fā)的對象。
參考文獻:
[1] CornellG,Horstmann CS編著.Java核心[M].楊秀軍,丁興農(nóng),何 粼等譯.北京:科學(xué)出版社,1997。
?。?] Bruce E.Java編程思想[M].京京工作室譯.北京:機械出版社,1999。
?。?] Elliatle RH.Java揭密[M].陳遺風(fēng)譯.廣東:世界圖書出版社,1998。
?。?] Patrick C,Rosanna L.Java類庫手冊[M].玄偉劍,龔志波,陳永智等譯.北京:北京大學(xué)出版社,1997.
[5] 閃四清.SQLServer系統(tǒng)[M].北京:清華大學(xué)出版社,2000.