劉 露
(中國石油化工股份有限公司 湖南岳陽石油分公司, 湖南 岳陽 414000)
隨著信息管理系統(tǒng)的不斷發(fā)展, 各個(gè)企事業(yè)單位都引入了信息管理軟件來管理自己日益增長的各種信息, 但多數(shù)系統(tǒng)在開發(fā)中存在系統(tǒng)結(jié)構(gòu)復(fù)雜、代碼重用率低、網(wǎng)頁設(shè)計(jì)和軟件開發(fā)相互制約導(dǎo)致開發(fā)效率低下等不盡人意的地方. 為此人們在實(shí)際中開發(fā)了MVC與對象——關(guān)系映射(ORM)等很多成功的模式.Struts 是Apache 組織的一個(gè)開放源代碼項(xiàng)目, 它提供了一個(gè)構(gòu)建基于MVC 體系結(jié)構(gòu)的Web 應(yīng)用程序的框架[1]. 但是Struts架構(gòu)只解決了視圖層、業(yè)務(wù)層和控制層的分離, 并沒有對復(fù)雜的持續(xù)層提供靈活的架構(gòu)支持. Hibernate框架是一個(gè)面向Java開發(fā)平臺的對象/關(guān)系數(shù)據(jù)庫的映射工具, 并且是開源的O/R Mapping框架. 它不僅提供了從Java類到數(shù)據(jù)庫表之間的雙向的映射, 也提供了數(shù)據(jù)查詢、數(shù)據(jù)修改和恢復(fù)等機(jī)制,并且還提供了對系統(tǒng)性能優(yōu)化的各種技術(shù). 從而可以大幅度減少開發(fā)時(shí)直接編寫和使用SQL語句和JDBC API處理數(shù)據(jù)訪問的時(shí)間. 因此通過將這兩個(gè)架構(gòu)整合起來,可以得到一個(gè)迅速地開發(fā)靈活、低耦合及易于維護(hù)的信息系統(tǒng)的完整解決方案.
Struts構(gòu)架模式其實(shí)是MVC構(gòu)架模式在J2EE Web組件技術(shù)上的具體應(yīng)用, 在該構(gòu)架模式中, 主要是利用MVC構(gòu)架模式中的模型(M)、視圖(V)、控制器(C)3種不同形式的組件來構(gòu)建具體的Web應(yīng)用系統(tǒng)的[2]. 其中的模型組件(Model)由 JavaBean組件承擔(dān), 并完成業(yè)務(wù)功能和數(shù)據(jù)處理等方面的功能, 而視圖(View)組件由JSP頁面承擔(dān), 并實(shí)現(xiàn)人機(jī)交互的前臺界面, 最后的控制器(Control)組件部分則由J2EE Web組件技術(shù)中的標(biāo)準(zhǔn) Servlet組件承擔(dān), 主要實(shí)現(xiàn)調(diào)度 JSP頁面和 JavaBean組件等方面的功能[3]. 圖 1為Struts構(gòu)架的工作原理圖. 圖中用戶在瀏覽器端的請求頁面中發(fā)出請求, 該請求向應(yīng)用服務(wù)器端的某個(gè)控制器Servlet組件發(fā)出; 該Servlet組件將根據(jù)請求的類型相應(yīng)調(diào)用具體完成業(yè)務(wù)功能的JavaBean組件中的業(yè)務(wù)功能方法, 由該業(yè)務(wù)功能方法實(shí)現(xiàn)最終的業(yè)務(wù)功能操作(如訪問數(shù)據(jù)庫表中的數(shù)據(jù)或者進(jìn)行業(yè)務(wù)功能處理等); 然后業(yè)務(wù)功能組件再將處理后的結(jié)果數(shù)據(jù)返回到該控制器Servlet組件中,控制器Servlet組件將處理后的結(jié)果轉(zhuǎn)發(fā)到顯示結(jié)果的另一個(gè) JSP頁面以實(shí)現(xiàn)結(jié)果的顯示輸出.
圖1 Struts架構(gòu)
在目前的企業(yè)應(yīng)用系統(tǒng)開發(fā)中所使用的數(shù)據(jù)庫系統(tǒng)仍然為關(guān)系型數(shù)據(jù)庫系統(tǒng), 其中存儲的是關(guān)系型的數(shù)據(jù), 并且還能夠保存這些關(guān)系數(shù)據(jù)的靜態(tài)結(jié)構(gòu). 在采用 Java作為信息系統(tǒng)的開發(fā)語言時(shí), 傳統(tǒng) Web應(yīng)用開發(fā)方法是直接用 JDBC與數(shù)據(jù)庫交互. 但是這個(gè)工作量很大, 而且一旦業(yè)務(wù)邏輯稍微有一些變更,就要大量地更改這些JDBC中的SQL語句, 因此不管是開發(fā)還是維護(hù)系統(tǒng)都很不方便. 考慮到Java的面向?qū)ο笮院完P(guān)系型數(shù)據(jù)庫的關(guān)系型結(jié)構(gòu)相差甚遠(yuǎn), 因此很有必要引入一種在對象與關(guān)系型數(shù)據(jù)庫之間的直接映射機(jī)制, 這種映射應(yīng)該是最大量地使用配置文檔, 以便今后業(yè)務(wù)邏輯更改后是盡可能地修改映射文件而不是Java源代碼, 因此出現(xiàn)了O/R映射模式. 有很多開源項(xiàng)目都使用 Java實(shí)現(xiàn)了這個(gè)O/R映射, 而Hibernate是其中最為優(yōu)秀的實(shí)現(xiàn)架構(gòu)之一,Hibernate框架如圖2所示.
圖2 Hibernate架構(gòu)
Hibernate框架是對 JDBC的輕量級的對象封裝, 它是一個(gè)獨(dú)立的對象持久層框架, 不依賴于某種J2EE應(yīng)用服務(wù)器容器的具體實(shí)現(xiàn)和支持. Hibernate框架可以用在JDBC可以使用的任何場合, 因此從某種意義上來說, Hibernate框架不僅能夠取代JDBC, 而且還進(jìn)一步完善和擴(kuò)展了JDBC的功能. 圖3(a)所示流程圖表示在Java應(yīng)用中通過JDBC API來訪問物理數(shù)據(jù)庫系統(tǒng)的過程, 而圖3(b)則表示在Java應(yīng)用中通過Hibernate 框架API來訪問物理數(shù)據(jù)庫系統(tǒng)的流程. 從圖3(b)中明顯可以看出, Hibernate框架是對JDBC的API的對象包裝, 從而能夠使得Java應(yīng)用以面向?qū)ο蟮姆绞絹聿僮骱驮L問數(shù)據(jù)庫系統(tǒng). 從圖3中能夠發(fā)現(xiàn)Hibernate框架是一個(gè)和JDBC密切關(guān)聯(lián)的框架, 因此Hibernate框架的兼容性和JDBC驅(qū)動程序、數(shù)據(jù)庫都有一定的關(guān)系, 但是和使用它的Java程序、J2EE應(yīng)用服務(wù)器沒有任何關(guān)系, 也不存在兼容性問題. 這使開發(fā)人員可以開發(fā)出與物理數(shù)據(jù)庫系統(tǒng)無關(guān)的應(yīng)用系統(tǒng).
圖3 JDBC和Hibernate框架的數(shù)據(jù)訪問技術(shù)的對比
系統(tǒng)從邏輯上可分為4大模塊: 登錄模塊、客戶管理模塊、訂單管理模塊、管理員模塊. 登錄模塊主要是通過輸入正確的操作員名稱、密碼和操作員級別進(jìn)入主窗體, 其基本流程為: 用戶輸入自己的用戶名,密碼及級別, 系統(tǒng)再對其輸入進(jìn)行判斷, 如果全都正確就進(jìn)入系統(tǒng). 在用戶輸入密碼的過程中, 為了安全,在此設(shè)置了只能輸入三次, 這就可以防止它人惡意進(jìn)入系統(tǒng). 同時(shí)根據(jù)用戶所選擇的級別的不同提供相應(yīng)的訪問權(quán)限. 客戶管理模塊完成對新增客戶基本信息(單位名稱、法人代表、法人電話、代理人、代理人聯(lián)系方式等)的輸入和已有客戶信息的修改、查詢, 是系統(tǒng)最基本的功能. 該模塊主要分為客戶增加、客戶修改、客戶查詢?nèi)齻€(gè)子模塊. 訂單管理模塊是整個(gè)管理系統(tǒng)的核心, 該模塊實(shí)現(xiàn)對公司業(yè)務(wù)訂單(如: 小訂單、合同等)的管理, 為各項(xiàng)業(yè)務(wù)建立信息輸入, 修改和查詢. 具體又分為訂單登記、訂單修改、訂單查詢和打印訂單這四個(gè)子模塊. 管理員模塊主要負(fù)責(zé)添加或刪除用戶, 為用戶提供修改密碼操作, 為用戶瀏覽公司詳細(xì)信息提供便利以及管理員根據(jù)公司實(shí)際情況修改公司信息并對論壇進(jìn)行管理等任務(wù).
由于訂單管理系統(tǒng)涉及到大量的數(shù)據(jù)處理與復(fù)雜的業(yè)務(wù)流程, 使用Struts 與Hibernate 框架能很好的節(jié)約開發(fā)時(shí)間和開發(fā)成本[4]. 系統(tǒng)總體上可分為以下5個(gè)層次:
(1)客戶層: 運(yùn)行在用戶機(jī)器的瀏覽器中, 處理與用戶的交互;
(2)Web 層(視圖層): 運(yùn)行在Web容器中, 產(chǎn)生系統(tǒng)的表現(xiàn)邏輯, 處理用戶的請求并作出響應(yīng); 整個(gè)Web 層建立在Struts 框架基礎(chǔ)上, 其中View 由JSP頁面組成; Controller由ActionServlet結(jié)合Strutsconfig.xml和Action組成, 而Model則交由業(yè)務(wù)邏輯層來實(shí)現(xiàn).
(3)業(yè)務(wù)邏輯層: 完成系統(tǒng)所需的業(yè)務(wù), 為Web層提供所需的業(yè)務(wù)方法, JavaBean等Business Objects(BO)構(gòu)成.
(4)數(shù)據(jù)持久層: 由 Hibernate 組成, Hibernate 從數(shù)據(jù)源中獲取數(shù)據(jù), 然后生成持久對象(Persistent Object, PO), 再把PO 傳給業(yè)務(wù)邏輯層.
(5)數(shù)據(jù)源層: 即數(shù)據(jù)庫層, 存放客戶信息系統(tǒng)的數(shù)據(jù).
本系統(tǒng)的表示層是由Struts 實(shí)現(xiàn), 由基于XML 的配置文件Struts-config.xml 將模型、視圖、控制器聯(lián)系起來. 它將從頁面接收到的請求按FormBean的格式將其封裝成一個(gè)Form對象, 根據(jù)業(yè)務(wù)流的邏輯決定交給的合適的方法實(shí)現(xiàn)業(yè)務(wù)流的轉(zhuǎn)向, 處理完的數(shù)據(jù)返回給控制器, 控制器將數(shù)據(jù)封裝成Form對象,根據(jù)業(yè)務(wù)流決定是交給下一個(gè)業(yè)務(wù)邏輯進(jìn)行處理還是返回到頁面. 控制器是按struts-config.xml 文件中的配置來決定業(yè)務(wù)流的轉(zhuǎn)向的, struts-config.xml 的部分代碼如下:
在系統(tǒng)開發(fā)過程中, 使用功能強(qiáng)大、擴(kuò)展性強(qiáng)的Jbuilder2007作為開發(fā)環(huán)境, 在數(shù)據(jù)庫方面選擇了易用性較好的MySQL SERVER5.0, 考慮到系統(tǒng)中各模塊的實(shí)現(xiàn)大同小異, 本文以“管理員模塊”中的“用戶信息維護(hù)”為例說明系統(tǒng)數(shù)據(jù)持久化的實(shí)現(xiàn). 為了簡化說明, 在Customer類中只定義了三個(gè)屬性, 即CustomerId、CustomerName和CustomerAddress, 它的屬性和數(shù)據(jù)庫中CUSTOMER表的字段是一一對應(yīng)的,并且類型一致.
3.4.1 Hibernate配置
Hibernate有兩種配置方式, 分別是使用hibernate.properties文件和hibernate.Cfg.xml文件, 兩種配置是一樣的. 在本系統(tǒng)中, 使用后者對Hibernate進(jìn)行配置. 在配置文件中, 可以配置數(shù)據(jù)庫的方言、連接驅(qū)動類、用戶名及密碼和URI等. 此外, 使用hibernate.Cfg.xml文件進(jìn)行配置時(shí)還可以指定mapping resource.配置文件hibernate.cfg.xml部分代碼如下所示:
在以上屬性配置文件中, 定義了訪問數(shù)據(jù)庫的URL資源定位地址和數(shù)據(jù)庫名稱, 以及符合SQL規(guī)范的dialect方言, 在mapping映射文件配置部分, 定義了CUSTOMER表對應(yīng)的映射文件Customer. hbm. xml,其他用到的映射資源可以隨著系統(tǒng)開發(fā)進(jìn)行靈活的加載與更新.
3.4.2 映射文件
每個(gè)持久化類都要有與之對應(yīng)的映射文件, 映射文件名為“類名.hbm.xml”. 這個(gè)映射文件定義O/R映射的規(guī)則. 例如持久化類Customer具有屬性ID和name, 其對應(yīng)的映射文件Customer.hbm.xml包含了對象/關(guān)系映射所需的元數(shù)據(jù). 元數(shù)據(jù)中包含了持久化類的聲明, 以及類中各個(gè)屬性到數(shù)據(jù)庫表各個(gè)字段的映射關(guān)系. 映射文件Customer. hbm. Xml主要代碼如下所示:
Hibernate通過這個(gè)XML文件來指定持久化類和關(guān)系數(shù)據(jù)表的映射. 其中主鍵用
3.4.3 定義持久化類
持久化類是指其實(shí)例需要被Hibernate持久化到數(shù)據(jù)庫中的類. 持久對象是一個(gè)普通的JavaBean, 包含一些屬性, 以及與之對應(yīng)的get和set方法, 每個(gè)持久化類對應(yīng)于數(shù)據(jù)庫中的一張表. 定單管理模塊中的持久化類Customer, 其屬性是通過映射文檔映射到數(shù)據(jù)庫中的CUSTOMER表. 這樣對外隱藏了內(nèi)部實(shí)現(xiàn)的細(xì)節(jié), 規(guī)范了事務(wù)處理部分中每個(gè)屬性所對應(yīng)的數(shù)據(jù)庫字段的數(shù)據(jù)操作. 為簡化開發(fā)本文采用結(jié)合hbm2java工具和build.xml文件自動生成Customer.java文件, 其生成的部分代碼如下:
3.4.4 實(shí)現(xiàn)持久化操作
Hibernate為Java 程序員提供了面向?qū)ο蟮腁PI和接口來操縱數(shù)據(jù)庫, 從而避免了在業(yè)務(wù)邏輯中嵌入大量的JDBC訪問和事物控制代碼. SessionFactory接口對應(yīng)我們的數(shù)據(jù)庫存儲源, 程序從此接口中得到Session接口實(shí)例. Session接口是應(yīng)用中進(jìn)行持久化時(shí)經(jīng)常使用的接口, 它提供了所有的持久化相關(guān)操作,同時(shí)我們可以通過Session接口獲得Tranaction接口來實(shí)現(xiàn)數(shù)據(jù)庫事務(wù)的控制. Hibernate還提供了我們其它一些實(shí)用接口和類, 如Query接口等. 首先, 映射文件要將持久化類映射到相應(yīng)的數(shù)據(jù)庫表, 這里需要用Configuration類配置, 并建立起映射關(guān)系, 然后在這個(gè)配置基礎(chǔ)上建立一個(gè)會話工廠SessionFactory.
Configuration cfg=new Configuration().configure();
SessionFactory sf=cfg.buildSessionFactory();
創(chuàng)建會話工廠后, 就可以從中獲取會話Session. 每次Session操作, 代表應(yīng)用程序和持久層之間的一次對話, 也就是一次數(shù)據(jù)處理. 獲取Session后, 可以對對象進(jìn)行保存、查詢、刪除和修改等操作. 使用Hibernate提供的面向?qū)ο蟮牟樵冋Z言HQL(Hibernate Query Language), 使得對對象的操作變得十分簡單:
以查詢條件為客戶姓名和地址, 采用HQL檢索方式為例說明查詢方法, 其相應(yīng)的代碼如下:
Struts減弱了業(yè)務(wù)邏輯接口和數(shù)據(jù)接口之間的耦合, 而Hibernate框架提供了數(shù)據(jù)持久層的支持, 可以使開發(fā)人員專心地實(shí)現(xiàn)業(yè)務(wù)邏輯而不用分心于繁瑣的數(shù)據(jù)庫方面的邏輯, 減小出錯的機(jī)會. 本文通過將Struts和Hibernate這兩個(gè)框架的結(jié)合, 充分發(fā)揮了兩者的優(yōu)點(diǎn), 有效地縮短了系統(tǒng)開發(fā)周期, 使得項(xiàng)目開發(fā)簡潔、結(jié)構(gòu)清晰, 并且通過實(shí)例說明了利用Hibernate實(shí)現(xiàn)數(shù)據(jù)持久化的可行性.
[1]孫衛(wèi)琴. 精通STRUTS:基于MVC的JavaWeb設(shè)計(jì)與開發(fā)[M]. 北京: 電子工業(yè)出版社, 2004
[2]宋秀琴, 侯殿昆, 方中純. 基于Struts 和Hibernate 的Web 應(yīng)用的構(gòu)建[J]. 微計(jì)算機(jī)信息, 2005,11-3: 125~127
[3]葉宇楓, 胡貞華. 基于J2EE架構(gòu)的辦公自動化系統(tǒng)的設(shè)計(jì)研究[J]. 計(jì)算機(jī)科學(xué). 2006, 33(8): 287~289
[4]李偉鐮, 盧建朱.基于Struts和Hibernate的電子申購系統(tǒng) [J]. 計(jì)算機(jī)工程, 2005, 31(19): 290~222