姜林美, 李國剛, 杜勇前
(華僑大學 計算機科學與技術學院, 福建 廈門 361021)
?
結合AOP思想和依賴注入技術的輕量級MVC框架
姜林美, 李國剛, 杜勇前
(華僑大學 計算機科學與技術學院, 福建 廈門 361021)
摘要:為了解決目前Java主流模型-視圖-控制器(MVC)框架日益龐大,從而導致性能低下的問題,提出了一個輕量級的MVC框架.該框架利用面向方面編程(AOP)技術實現(xiàn)了橫向業(yè)務的剝離,采用控制反轉設計模式實現(xiàn)了模塊間的最低耦合,并通過Java反射技術實現(xiàn)了數據庫記錄與Java對象的自動轉換.實驗結果表明:該框架以僅僅70 KB左右的JAR包實現(xiàn)了比其龐大數百倍的類似框架的主要功能,同時支持網絡應用和移動應用的開發(fā),具有更高的執(zhí)行效率.
關鍵詞:Java反射; 依賴注入; 控制反轉; 模型-視圖-控制器框架; 面向方面編程; 移動應用開發(fā)
在面向對象設計領域,框架是由一組相互協(xié)作的可重用設計的類構成,對這些類進行特化(specialized),即可創(chuàng)建不同的客戶應用程序[1].目前,框架設計已成為加速信息系統(tǒng)開發(fā)和軟件重用的一項關鍵技術[2],盡可能地降低模塊之間的耦合性.模型-視圖-控制器(model view controller,MVC)框架的核心是能夠實現(xiàn)三層甚至多層的松散耦合[3].面向方面編程(aspect oriented programming,AOP)的核心思想是對軟件系統(tǒng)中各個互相獨立的橫切關系(如日志記錄、權限檢查、緩存和持久化等)加以模塊化,使之可以有效地集中被管理,而不會讓其分散到程序代碼的各個地方[4].AOP把一個系統(tǒng)看作一批關注點,強調調用者與被調用者之間的解耦,并能夠自動將橫切關注點織入到面向對象的軟件系統(tǒng)中[5],將業(yè)務關注點和橫切關注點分離[6-7].依賴注入是Martin Fowler對IoC(inversion of control)模式的一種擴展解釋,即高層不應依賴于底層,兩者都應依賴于抽象;抽象不應依賴于細節(jié),細節(jié)應依賴于抽象[8].在Java中,依賴注入一般通過反射機制來實現(xiàn).Java反射機制允許在運行時加載、探知和使用編譯期完全不知道的類[9].目前,SSH(struts2 spring hibernate)框架在Java Web輕量級應用開發(fā)領域得到了廣泛的應用.SSH是由Struts2,Spring和Hibernate三個獨立組件組合而成,它們各有自己的不同的版本,這些版本相互組合存在兼容性問題和執(zhí)行效率低下的問題.另外,Hibernate因采用對象關系映射(ORM)技術導致效率比精心編寫的JDBC(java data base connectivity)差[10].最后,SSH的各個組件的尺寸越來越大,所帶來的問題是應用系統(tǒng)的可維護性差,運行效率的降低.為此,本文提出應用AOP和Java依賴注入技術的思想的輕量級MVC框架.
1框架的設計
文中提出的框架運行于Web容器之上,其總體結構如圖1所示.
圖1 框架結構Fig.1 Structure of the framework
派遣過濾器是框架與Web容器交互的界面.派遣過濾器實現(xiàn)了javax.servlet.Filter接口.Filter接口的配置管理器由派遣過濾器創(chuàng)建并調用,負責讀取并解析系統(tǒng)配置文件.frame.xml.init()方法中,通過配置管理器讀取框架的配置文件frame.xml,并進行解析.Filter接口的doFilter()方法中,利用Action調度器對Web容器發(fā)來的HttpServletRequest請求進行處理,并將處理結果通過HttpServletResponse反饋給Web容器.
配置管理器由派遣過濾器創(chuàng)建并調用,它負責讀取并解析系統(tǒng)配置文件frame.xml.根據配置文件中的配置項生成各類映射表,包括Action映射表、攔截器映射表、終結器映射表、DAO(data access object)映射表、結果視圖映射表和常量映射表.前4種映射表是Action調度器進行依賴注入的依據.另外,配置管理器還通過反射機制創(chuàng)建數據庫連接池.該連接池在DAO對象調用數據庫操作工具包進行數據庫訪問時被自動引用,并在派遣過濾器銷毀時自動銷毀.
當客戶端的HTTP請求經Web服務器送達Web容器后,Web容器生成相應HttpServletRequest請求,派遣過濾器則會在其doFilter() 方法中截獲該請求,并通過Action調度器對該請求進行處理,并反饋處理結果.因此,Action調度器是整個框架的核心.
1.3.1依賴注入依賴注入是Action調度器對一次HttpServletRequest請求所做的第一個操作,需要調用反射工具包中的反射處理函數配合完成.首先,Action調度器會根據請求的URL(universal resource locator)信息,在配置管理器的Action映射表中查找相應的Action類名.如果找到,則通過依賴注入創(chuàng)建相應的Action實例;否則,立即終止請求,并輸出錯誤提示.Action實例成功創(chuàng)建之后,調度器繼續(xù)在配置管理器的映射表中查找與該Action相關的攔截器和終結器,查找成功,即通過依賴注入創(chuàng)建相應的實例.此外,調度器還將在配置管理器的DAO映射表中查找與該Action相關聯(lián)的DAO,如果查找成功,則創(chuàng)建DAO實例,并將創(chuàng)建的DAO實例注入該Action對象.最后,調度器通過Java反射功能檢查該Action中的成員變量中是否有表單類型的對象,如果有,則創(chuàng)建表單實例,并為表單對象的各成員變量注入值.所注入的值來自HttpServletRequest中與成員變量同名的請求參數,表單類型指的是直接或間接從Form類繼承的類.
1.3.2攔截器調度器在完成依賴注入之后,在配置文件中,以攔截器配置的先后順序依次調用攔截器對象的intercept()方法,該方法以接收請求相應的Action對象作為其參數.在攔截器中可以對請求做任何橫切事務處理,并根據橫切處理結果決定是否要繼續(xù)執(zhí)行Action對象中的目標方法.
1.3.3ActionAction是框架提供給上層應用的主要接口,應用程序應當是在Action中或Action的交互類中實現(xiàn)業(yè)務處理的核心代碼.
如節(jié)1.3.1所述,Action中若有DAO類型的成員變量,并在frame.xml中進行了相應的配置,該成員變量的值會在依賴注入階段進行注入.另外,Action中表單類型的成員變量的值也會在依賴注入階段進行注入.因此,在Action中可以直接使用DAO進行數據庫訪問,也可以通過表單類型的成員變量直接獲得客戶端提交的數據.
在Action中,可通過“表單-POJO(plain ordinary java objects)轉換器”將表單對象轉換成POJO對象.轉換的原則是同名成員變量做類型轉換后,進行相應的賦值,轉換后的POJO對象即可供業(yè)務處理使用.此后,若業(yè)務處理過程需要進行數據庫操作,可使用DAO對象來完成.在DAO中只需編寫SQL語句,然后調用數據庫操作工具包中的相應方法執(zhí)行該SQL語句,即可完成任何數據庫操作.若執(zhí)行的是有結果集(Resultset)的SQL語句,所取得所有記錄行(結果集中的)會通過“記錄行-POJO轉換器”轉換成POJO對象,然后整個結果集中的數據將被封裝成一個List列表(POJO數據集)返回.
1.3.4結果視圖結果視圖對應MVC框架的視圖部分,在Action中對業(yè)務邏輯進行處理之后,可根據處理結果選擇在frame.xml中配置好的屬于Action的任一結果視圖.框架支持的結果類型包括FORWARD,REDIRECT,REDIRECT_TOP,CHAIN,PLAINTEXT,JSON和XML.前3種類型一般用于JSP頁面,其中,F(xiàn)ORWARD類型用于直接在服務端轉發(fā)請求的JSP頁面;RIDRECT類型則用于重新轉發(fā)到一個新的URL頁面;REDIRECT_TOP和RIDRECT一樣,但在原始頁面由多個frame(指html的〈frame〉或〈iframe〉)構成時,會在頂層顯示轉發(fā)后的結果頁面.CHAIN類型用于直接調用另一個Action作后續(xù)處理的頁面;使用PLAINTEXT類型會向客戶端傳送普通文本;使用JSON類型則會將Action中的處理結果格式化成JSON字符串,再傳送給客戶端.最后,XML類型意味著向客戶端傳送XML文檔.
1.3.5終結器Action調度器處理的最后一步,在配置文件中,對終結器配置的先后順序依次調用終結器對象的intercept()方法,該方法同樣以接收請求相應的Action對象作為其參數,可對請求做任何橫切事務處理.
2框架的實現(xiàn)
框架源碼實現(xiàn)時含4個包,分別是工具包util、數據庫包db、核心包core和活動包action.整個框架最終被打包成xxdw-platform.jar提供給上層應用程序來使用,框架的源碼組織結構,如圖2所示.
圖2 源碼組織結構Fig.2 Organization of the source codes
工具包util提供整個框架的一些工具類,工具類只有一些靜態(tài)的方法,以便通過類名直接調用.其中:ReflectUtil類是實現(xiàn)依賴注入的基礎,同時也為Form2PojoUtil類進行表單-POJO的轉換,以及為Record2PojoUtil進行記錄行-POJO的轉換提供支持.ReflectUtil的核心操作是依賴注入和數據類型的轉換.
ViewUtil定義了和視圖操作相關的一些方法,如取上下文路徑、視圖重定向等.CommonUtil則定義了其他一些常用的公共方法,如設置調試模式、獲取遠端IP地址、特殊字符轉義處理等.
數據庫包db中的類均與數據庫處理相關.其中:ConnectionPoolFactory是用于創(chuàng)建連接池的工廠類;ConnectionPool是數據庫連接池.配置管理器在讀入并解析frame.xml時,實例化連接池工廠,并創(chuàng)建連接池;Dao是一個抽象類,應用程序應當繼承該類以實現(xiàn)自身的各種數據庫訪問操作;DbUtil類提供一系列靜態(tài)方法以執(zhí)行任何SQL查詢操作,使用Record2PojoUtil工具可將數據庫記錄轉換成Java對象.
核心包core實現(xiàn)整個框架的“控制”(即MVC中的Controller)部分,其中:FrameFilter是派遣過濾器,它被配置到Web容器的web.xml文件中,以截獲客戶端的ServletRequest請求;ConfigureManager即配置管理器,管理frame.xml中的各配置項;ActionItem,ResultItem和DaoItem分別用于其中的Action配置項、結果視圖配置項和Dao配置項;ActionDispatcher對應框架中的Action調度器,對整個HttpServletRequest的請求處理過程進行調度處理.
活動包action中實現(xiàn)了一些應用程序所必須繼承的基礎類或應當實現(xiàn)的接口,應用程序主要通過這些類使用框架的各項功能.其中:Action類是業(yè)務活動基類,所有繼承該類的類應當在frame.xml中進行配置,并會在框架的依賴注入階段被實例化;Form是所有表單類應繼承的基類,用于接收客戶端提交的數據,表單類也會在依賴注入階段被實例化,并被注入數據;Interceptor和Finalizer分別為攔截器和終結器接口;Pojo類則是應用程序中的簡單對象類.
3實驗結果與分析
為驗證所提出的輕量級MVC框架的性能,建立了兩個Web項目,分別采用struts 2框架和所提出的輕量級MVC框架對客戶端的請求進行處理.客戶端通過多線程來模擬并發(fā)連接,每個線程可連續(xù)向服務端發(fā)起多個請求.線程數稱為并發(fā)數;每個線程連續(xù)發(fā)起的請求數稱為每并發(fā)請求數,簡稱請求數.因此,總請求數=并發(fā)數×請求數,客戶端向服務端提交請求的核心代碼如下所示.
∥建立一個Socket
Socket socket=new Socket(InetAddress.getByName(“l(fā)ocalhost”),8080);
∥提交的數據
String para=“username=alice&password=568998”;
StringBuffer command=new StringBuffer()
.append(“POST” +path+ “HTTP/1.1 ” )
.append(“Accept:*/* ”)
.append(“Content-Type: application/x-www-form-urlencoded ”)
.append(“HOST:localhost:8080 ”)
.append(“Connection:Close ”)
.append(“Content-Length: ”+para.length() + “ ”)
.append(“ ”+para);
∥發(fā)送命令
BufferedWriter writer=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
writer.write(command.toString());
writer.flush();
∥接收返回的結果
BufferedReader reader=new BufferedReader(new InputStreamReader(socket.getInputStream()));
while (reader.readLine() != null);
兩個Web項目所構建的服務端接收相同的請求數據(即username=alice&password=123456)并對其進行讀取,然后向客戶端返回相同的jsp響應頁面.
實驗一的客戶端和服務器采用同一臺主機,該主機的配置如下:CPU為Pentium (R) Dual Core CPU E5200@2.5 GHz,內存3.0 G,操作系統(tǒng)為Windows 7,32位旗艦版 Service Pack 1,Web服務器為Apache Tomcat 6.0.26.
實驗二的服務端同實驗一,客戶端則為一臺安卓華為C8813手機.華為C8813的主要參數:操作系統(tǒng)為Android OS 4.1,CPU為高通驍龍Snapdragon MSM8625Q雙核1.2 GHz,內存512 M.
兩個實驗各自的總請求數均為2 500(基本接近Tomcat 6所能接受的并發(fā)連接數的上限),各自測試3種具有代表性的情形:并發(fā)數為1,每并發(fā)連接數為2 500;并發(fā)數為50,每并發(fā)連接數也為50;并發(fā)數為2 500,每并發(fā)連接數為1.第1,3種情形屬于極端情況,中間一種情形代表了普通情況.3種情況下,采用struts 2的服務端和采用文中MVC框架的服務端的平均耗時(每種情形均進行1 000次測試),如表1所示.表1中:T為并發(fā)數;R為請求數.由表1可知:采用輕量級MVC框架的服務端所用時間遠低于采用struts 2的服務端所用時間.
表1 處理2 500個連接的耗時
為更清晰地觀察兩個框架的性能區(qū)別,根據表1計算出的兩個框架每秒所能處理的請求數,如表2所示.由表2可知:在客戶端為PC機的情況下,相比于struts 2,采用文中輕量級MVC框架可提升處理請求的能力平均達57.11%;在客戶端為手機的情況下,受限于移動終端的并行處理能力,相比于struts 2,采用文中輕量級MVC框架可提升處理請求的能力小一些,但平均仍達16.64%.
每秒所能處理的連接數對比,如圖3所示.圖3中:橫軸標識中的T表示并發(fā)數;R表示每并發(fā)請求數.由圖3可以直觀地看出:文中輕量級MVC框架的性能優(yōu)越性.
(a) PC客戶端 (b) Android客戶端圖3 每秒所能處理的連接數對比Fig.3 Connection processing performance comparison
從實驗結果可以看出:兩個框架在并發(fā)數和每并發(fā)請求數均衡的普通情況下的處理能力均優(yōu)于各自的極端情況,但是在任何情形下,文中所述框架在性能上均優(yōu)于struts框架.
表2 每秒處理的請求數和性能比較
4結束語
鑒于AOP程序設計和MVC框架在Web應用程序開發(fā)中日益廣泛的應用,而現(xiàn)存的采用Java平臺的MVC框架(如SSH)日益龐大繁雜,提出了一個精簡的輕量級的結合AOP和依賴注入的MVC框架.該框架的成品jar包庫僅有72.1 KB,遠小于SSH和Spring MVC等框架的jar包庫.實驗數據說明:該框架相比于struts 2具有更好的運行性能.另外,該框架已在多個Web和移動應用項目中得到應用.實踐結果證明:該框架能極大地提升應用開發(fā)的效率.最后,增加Web服務支持可以更大地提高框架的通用性,這也是進一步的研究方向.
參考文獻:
[1]LI Fangxing,BROADWATER R P.Software framework concepts for power distribution system analysis[J].IEEE Transactions on Power Systems,2004,19(2):948-956.
[2]CHEN Liyan,GAO Qing.Research on framework developing technology based on MVC[J].Advances in Information Sciences and Service Sciences,2011,3(3):25-31.
[3]張忻.基于MVC模式的Struts框架在物流管理信息系統(tǒng)中的應用[D].成都:西南交通大學,2005:7-8.
[4]徐倩穎,楊宗源.面向方面編程的一種新型設計模式[J].華東師范大學學報(自然科學版),2008,2008(1):68-74.
[5]史玉珍,李波.一種面向方面的UML建模方法研究[J].計算機測量與控制,2009,17(12):2497-2499.
[6]陳月娟,李慧,劉光遠,等.基于AOP的信息管理系統(tǒng)的研究與實現(xiàn)[J].計算機應用與軟件,2010,27(2):130-132,140.
[7]卞世暉,李龍澍,陳圣兵,等.基于AOP理念的Struts 2攔截器的研究與應用[J].電子設計工程,2010,18(1):8-9.
[8]ROBERT C M.敏捷軟件開發(fā):原則、 模式與實踐[M].北京:清華大學出版社,2003:116-118.
[9]費廷偉,劉淑芬,屈志勇,等.Java反射驅動的規(guī)則引擎技術研究[J].計算機應用,2010,30(5):1324-1326,1330.
[10]柏銀.基于Struts+Spring+Hibernate多架構的性能分析系統(tǒng)[D].成都:四川大學,2006:26-30.
(責任編輯: 陳志賢英文審校: 吳逢鐵)
A Light-Weight MVC Framework Combining
AOP and Dependency Injection
JIANG Linmei, LI Guogang, DU Yongqian
(College of Computer Science and Technology, Huaqiao University, Xiamen 361021, China)
Abstract:To solve the problem of low performance caused by gradually increased size of the most popular Java MVC(Model-View-Control) frameworks, a novel light-weight MVC framework is presented. In the proposed framework, AOP(Aspect Oriented Programming) technology is used to deal with the cross-cutting business logic, and Inversion-of-Control pattern is adopted to achieve the lowest coupling among modules. Meanwhile, Java reflection technology is used to transfer a database record to a Java object automatically. The experimental results show that although the JAR package of the proposed framework takes only around 70 KB, it not only realizes all the primary functions of the similar frameworks whose size are hundreds of times more massive, but also supports the development of both web application and mobile application with higher execution efficiency.
Keywords:Java reflection; dependency injection; inversion of control; model view controller; aspect oriented programming; mobile application development
基金項目:福建省廈門市重大科技計劃項目(3502Z20131019)
通信作者:姜林美(1976-),男,講師,博士研究生,主要從事網絡安全與網絡應用軟件的研究.E-mail:clough@hqu.edu.cn.
收稿日期:2014-07-30
中圖分類號:TP 393.01
文獻標志碼:A
doi:10.11830/ISSN.1000-5013.2016.01.0092
文章編號:1000-5013(2016)01-0092-06