魏 穎
(天津大學(xué)管理與經(jīng)濟(jì)學(xué)部,天津 300072)
近些年,Web技術(shù)快速發(fā)展,B/S模式已經(jīng)成了當(dāng)今系統(tǒng)的主流模式。與此同時(shí),越來越多的優(yōu)秀軟件開發(fā)人員參與到J2EE[1-2]開源框架的開發(fā)中,打造出了一批易用且完善的Web框架,如Spring、MyBatis、Hibernate等,大大降低了Web系統(tǒng)的開發(fā)門檻。為了提升系統(tǒng)的開發(fā)效率、降低系統(tǒng)的維護(hù)成本,大多數(shù)Web系統(tǒng)都采用MVC分層模式進(jìn)行開發(fā)。MVC模式是一種“分治”的思想[3],將數(shù)據(jù)的訪問、邏輯處理和數(shù)據(jù)的展現(xiàn)分開,使每一層次都專注于自己的業(yè)務(wù)處理。后臺(tái)管理系統(tǒng)提供的功能大部分是針對(duì)數(shù)據(jù)庫的CRUD(增、刪、改、查)操作,其邏輯簡單,流程相對(duì)固定。但是在實(shí)際的開發(fā)中,程序員往往要花費(fèi)大量的時(shí)間去重復(fù)編寫各層次的代碼,包括后臺(tái)程序代碼和前臺(tái)頁面展示代碼,不但增加了程序員工作量,而且還影響了軟件的開發(fā)進(jìn)度。因此,自動(dòng)化代碼生成一直以來都是軟件工程師追求的目標(biāo)。本文針對(duì)后臺(tái)管理系統(tǒng)的特性,利用Freemarker模板技術(shù),設(shè)計(jì)了一個(gè)可自動(dòng)生成基于MVC模式的J2EE后臺(tái)管理系統(tǒng)的代碼生成器,用于后臺(tái)程序代碼和前臺(tái)頁面的自動(dòng)生成。
本代碼生成器根據(jù)用戶的配置,針對(duì)數(shù)據(jù)庫單表或聯(lián)表生成從前臺(tái)頁面到后臺(tái)處理的CRUD代碼。軟件開發(fā)人員可以在自動(dòng)生成系統(tǒng)的基礎(chǔ)上,進(jìn)行二次開發(fā),打造符合需求的后臺(tái)管理系統(tǒng)。
現(xiàn)有的代碼生成工具主要服務(wù)于生成數(shù)據(jù)庫操作代碼和業(yè)務(wù)代碼,沒有提供對(duì)前臺(tái)頁面的代碼生成接口,并且代碼模板都預(yù)置在系統(tǒng)中,用戶無法改變代碼結(jié)構(gòu)和風(fēng)格,靈活性比較差。相比于業(yè)界已有的代碼生成器,本代碼生成器的優(yōu)點(diǎn)如下:
(1)用戶可自定義代碼生成任務(wù)。
為了滿足不同用戶的需要,本代碼生成器提供3種代碼生成任務(wù),分別是生成整套系統(tǒng)、生成基本架構(gòu)和生成數(shù)據(jù)庫操作代碼。用戶可以結(jié)合自身需要在命令批處理文件中自行定義代碼生成任務(wù)。
(2)用戶可自行開發(fā)代碼模板。
Freemarker是一個(gè)使用純Java編寫的開源模板引擎[4],能夠基于模板生成各類文件,具有語法簡單明了、結(jié)構(gòu)清晰和解析效率高等特點(diǎn),目前廣泛應(yīng)用在Web界面、Email模板和其他模板定義方面。由于Freemarker的易上手特性,用戶在遵循自定義模板規(guī)則的基礎(chǔ)上,可以很輕松地設(shè)計(jì)和開發(fā)自己的代碼模板,然后在業(yè)務(wù)模型文件中指定代碼模板路徑,就可生成符合自身需求的代碼。
(3)可以自動(dòng)生成前臺(tái)頁面。
jQuery[5-6]是一款優(yōu)秀的 JS框架,由于其簡單明了的語法、良好的瀏覽器兼容性和強(qiáng)大的功能,已經(jīng)廣泛應(yīng)用于Web系統(tǒng)的開發(fā)。Bootstrap是由著名社交網(wǎng)站Facebook提供的一款開源CSS框架,能讓設(shè)計(jì)人員很快地構(gòu)建自己的系統(tǒng)前臺(tái),并且對(duì)PC端和移動(dòng)端都提供良好的兼容性。本代碼生成器以jQuery和Bootstrap作為前臺(tái)框架,提供針對(duì)數(shù)據(jù)庫的增刪改查操作的界面生成功能。
(4)生成的系統(tǒng)默認(rèn)提供角色權(quán)限配置功能。
由于提供角色權(quán)限配置功能基本上是后臺(tái)管理系統(tǒng)的通用需求,所以本代碼生成器生成的后臺(tái)管理系統(tǒng)默認(rèn)提供此功能。新版的Spring Security 3框架具有完善的安全體系[7-8],在用戶認(rèn)證和用戶授權(quán)方面都提供了很好的支持。本系統(tǒng)提供的角色權(quán)限配置是在Spring Security的基礎(chǔ)上,進(jìn)行二次開發(fā),使用戶可以根據(jù)自身的需要靈活地對(duì)權(quán)限進(jìn)行配置。
本代碼生成器生成的后臺(tái)系統(tǒng)采用Maven作為項(xiàng)目管理工具,以J2EE為系統(tǒng)架構(gòu),前端引用jQuery和Bootstrap框架。
Maven是Apache提供的一款基于項(xiàng)目對(duì)象模型(Project Object Model,POM)的開源項(xiàng)目管理工具,是Ant的進(jìn)化,為項(xiàng)目提供包管理、編譯和發(fā)布等一系列功能。它包含了一個(gè)項(xiàng)目對(duì)象模型、一組標(biāo)準(zhǔn)集合、一個(gè)項(xiàng)目生命周期(Project Lifecycle)、一個(gè)依賴管理系統(tǒng)(Dependency Management System)和用來運(yùn)行定義在生命周期階段(Phase)中插件(Plugin)目標(biāo)(Goal)的邏輯。當(dāng)使用Maven時(shí),可以用一個(gè)明確定義的項(xiàng)目對(duì)象模型來描述項(xiàng)目,然后Maven可以應(yīng)用橫切的邏輯,這些邏輯來自一組共享的(或者自定義的)插件[9]。Maven可以讓開發(fā)人員快速地構(gòu)建一個(gè)項(xiàng)目,有效地解決包管理和項(xiàng)目發(fā)布問題,并且可以與持續(xù)集成進(jìn)行無縫對(duì)接。對(duì)于大型的系統(tǒng),采用Maven作為項(xiàng)目管理工具,可以有效地進(jìn)行分工協(xié)作。
本代碼生成器遵循MVC模式,選擇Spring Web、Spring和MyBatis作為J2EE框架。其中,Spring Web負(fù)責(zé)前端數(shù)據(jù)的展示和處理,Spring負(fù)責(zé)整個(gè)項(xiàng)目的統(tǒng)籌和管理,MyBatis作為持久層框架,負(fù)責(zé)處理數(shù)據(jù)庫的CRUD操作。各框架各司其職,這種分層的體系結(jié)構(gòu)一方面能夠很好地解決各模塊的耦合性問題,使代碼結(jié)構(gòu)更加明了,有利于項(xiàng)目的維護(hù);另一方面為代碼生成器的設(shè)計(jì)提供了便利性,只需根據(jù)每層的特點(diǎn)編寫對(duì)應(yīng)的模板文件,大大提高了編碼效率,降低了用戶自定義模板的難度。項(xiàng)目各層交互如圖1所示。
圖1 J2EE體系結(jié)構(gòu)圖
(1)PO和VO對(duì)象。
一張數(shù)據(jù)庫表對(duì)應(yīng)一個(gè)PO對(duì)象,PO對(duì)象是簡單的Java對(duì)象,沒有任何的業(yè)務(wù)邏輯處理,只有與數(shù)據(jù)表字段對(duì)應(yīng)的屬性和Setter/Getter方法。PO對(duì)象的主要用途是接收和封裝單張數(shù)據(jù)表CRUD的結(jié)果數(shù)據(jù),在業(yè)務(wù)邏輯處理層和數(shù)據(jù)持久層進(jìn)行傳遞。VO對(duì)象的作用主要是接收和封裝前端數(shù)據(jù)展示層的數(shù)據(jù),通過前端數(shù)據(jù)處理層傳遞給業(yè)務(wù)邏輯層,業(yè)務(wù)邏輯層負(fù)責(zé)VO和PO的轉(zhuǎn)換。PO和VO的主要區(qū)別在于PO服務(wù)于數(shù)據(jù)庫,而VO服務(wù)于前端數(shù)據(jù)展示。
(2)展示層。
在本系統(tǒng)中,由Spring Web框架負(fù)責(zé)展現(xiàn)層。前端數(shù)據(jù)展示由JSP、jQuery和Bootstrap協(xié)同配合完成,通過Get或Post請(qǐng)求,經(jīng)過Spring Web Servlet容器處理,定位到對(duì)應(yīng)的數(shù)據(jù)處理即Controller方法。與此同時(shí),請(qǐng)求參數(shù)被封裝到指定的VO對(duì)象中,傳遞給Controller方法。經(jīng)過Controller方法的處理,再傳遞給邏輯處理層,邏輯處理層處理之后將結(jié)果返回給 Controller,Controller通過 Spring Web Servlet再將數(shù)據(jù)返回前臺(tái),通過Spring Web標(biāo)簽將數(shù)據(jù)顯示在頁面上。
(3)邏輯處理層。
顧名思義,邏輯處理層主要負(fù)責(zé)業(yè)務(wù)邏輯的處理,是整個(gè)系統(tǒng)的核心和精髓,但具體的業(yè)務(wù)會(huì)增加邏輯處理代碼的耦合度,不利于系統(tǒng)的擴(kuò)展和維護(hù)。為了解決此問題,本系統(tǒng)通過Spring容器管理邏輯處理和數(shù)據(jù)持久層,為各層組件的靈活配置提供便利性。
(4)數(shù)據(jù)持久層。
數(shù)據(jù)持久層主要負(fù)責(zé)關(guān)系數(shù)據(jù)表與Java對(duì)象(即PO和VO對(duì)象)的映射,本系統(tǒng)使用MyBatis作為持久層框架,相比Hibernate或 OJB等全自動(dòng)式ORM框架,MyBatis可以自行定義、優(yōu)化SQL語句,因此被稱為半自動(dòng)式ORM框架[10-11]。MyBatis由Mapper和SQL Map兩大組件組成,其中Mapper負(fù)責(zé)定義數(shù)據(jù)口操作接口,SQL Map負(fù)責(zé)SQL語句的組裝。為了減少程序員的工作量,提高代碼編寫效率和正確性,MyBatis官方網(wǎng)站提供了一款代碼生成器iBator,可生成針對(duì)數(shù)據(jù)庫單表進(jìn)行增刪改查操作的Mapper、SQL Map和PO對(duì)象。本代碼生成器也會(huì)調(diào)用iBator生成單表的增刪改查的持久層代碼。
代碼生成器的原理:按照規(guī)則定義輸入文件,解析輸入文件得到符合要求的輸入數(shù)據(jù)模型,將輸入數(shù)據(jù)模型按照特定的規(guī)則轉(zhuǎn)為輸出文件。本代碼生成器利用Freemarker模板技術(shù)實(shí)現(xiàn)輸入和輸出的轉(zhuǎn)換。使用模板的目的是將不變的代碼處理邏輯和可變的數(shù)據(jù)分離開來,這樣生成器的專注點(diǎn)就在于解析出可變的數(shù)據(jù)。由于Freemarker是一款基于Java語言的模板引擎,因此可以利用模板標(biāo)簽引用到Java對(duì)象中的各種屬性,將可變的數(shù)據(jù)和不變的代碼處理邏輯合為一體,組裝出系統(tǒng)所需要的各種組件。通過利用模板技術(shù),不僅可以減少代碼編寫工作量,提高生成程序的準(zhǔn)確性,還可以使代碼生成器滿足用戶自定義代碼邏輯的需求,用戶只需定義自己的程序模板,就可以生成出符合自身需求的業(yè)務(wù)組件。
如圖2所示,本代碼生成器可以分為3大塊內(nèi)容,業(yè)務(wù)描述文件、代碼生成引擎和模板文件。代碼生成引擎就像一個(gè)工廠,將業(yè)務(wù)描述文件和模板文件進(jìn)行組裝,最后產(chǎn)出后臺(tái)管理系統(tǒng)。代碼生成器的基本流程是:軟件開發(fā)人員首先分析自身的需求,在業(yè)務(wù)描述文件里定義數(shù)據(jù)規(guī)則和組件規(guī)則,如需要用到的數(shù)據(jù)表信息、數(shù)據(jù)表之間的關(guān)聯(lián)和對(duì)應(yīng)關(guān)系信息、每個(gè)字段對(duì)應(yīng)的前臺(tái)組件信息等;然后通過代碼生成器中的數(shù)據(jù)解析引擎解析業(yè)務(wù)描述JSON文件,將解析得到的數(shù)據(jù)和模板文件結(jié)合,生成后臺(tái)管理系統(tǒng)。
具體來說,本代碼生成器一共包括3種類型的代碼生成器:DAO代碼生成器,負(fù)責(zé)數(shù)據(jù)持久層的代碼生成;Controller代碼生成器,負(fù)責(zé)生成除頁面以外的所有代碼;CRUD代碼生成器,在調(diào)用以上兩種代碼生成器的基礎(chǔ)上,繼續(xù)生成增刪改查頁面、項(xiàng)目的目錄結(jié)構(gòu)和配置文件。
圖2 代碼生成器流程圖
3.2.1 業(yè)務(wù)描述文件定義
業(yè)務(wù)描述文件負(fù)責(zé)描述整個(gè)后臺(tái)管理系統(tǒng)的業(yè)務(wù)邏輯,具體包括項(xiàng)目配置信息、數(shù)據(jù)庫連接信息、數(shù)據(jù)表信息和頁面UI信息4方面的配置。本系統(tǒng)采用JSON作為業(yè)務(wù)文件的定義形式。隨著Web2.0技術(shù)的不斷發(fā)展,Ajax技術(shù)大放異彩,JSON作為在異步傳輸中被廣泛采用的數(shù)據(jù)交換語言,已經(jīng)擁有了很成熟的發(fā)展體系。JSON和XML同為數(shù)據(jù)傳輸語言,具有很好的擴(kuò)展性,都能滿足自定義數(shù)據(jù)格式的需求,但是相比XML,JSON編碼容易,解析成本低[6],所以本系統(tǒng)采用JSON描述業(yè)務(wù)邏輯。下面是業(yè)務(wù)描述文件數(shù)據(jù)表信息部分,其中tables中封裝的是數(shù)據(jù)表信息,fields中封裝的是數(shù)據(jù)列信息,component中封裝的是某個(gè)字段對(duì)應(yīng)的前端組件信息。
圖3 業(yè)務(wù)數(shù)據(jù)類圖
3.2.2 業(yè)務(wù)文件解析
業(yè)務(wù)文件解析器負(fù)責(zé)將業(yè)務(wù)描述JSON字符轉(zhuǎn)化為代碼生成器可識(shí)別的Java對(duì)象,為代碼生成提供數(shù)據(jù)源。本文的解析器是在開源組織Apache提供的JSON解析工具Jackson的基礎(chǔ)上進(jìn)一步加工和封裝所形成的,具體的處理過程為:首先對(duì)業(yè)務(wù)描述文件進(jìn)行檢查,例如,JSON字符是結(jié)構(gòu)定義是否有誤,業(yè)務(wù)描述是否符合規(guī)則等,如不符合預(yù)期,則拋出異常信息;其次將業(yè)務(wù)數(shù)據(jù)解析轉(zhuǎn)化為Java對(duì)象并加載到內(nèi)存中,供代碼生成器訪問。本系統(tǒng)所使用的業(yè)務(wù)對(duì)象類如圖3所示,具體包括項(xiàng)目基本信息、數(shù)據(jù)庫基礎(chǔ)信息和數(shù)據(jù)表信息,其中數(shù)據(jù)表信息又由數(shù)據(jù)列信息和前端組件信息兩部分組成。通過這樣的對(duì)象結(jié)構(gòu)設(shè)計(jì)和組合,就可以將業(yè)務(wù)描述信息全部加到Java對(duì)象中,為代碼生成器提供結(jié)構(gòu)化的數(shù)據(jù)源。
3.2.3 代碼模板定義
本代碼生成器基于模板技術(shù),在模板中定義程序原型,再由代碼生成器和模板引擎共同合成最終的程序文件。本文將以Service層代碼模板為例,闡述本系統(tǒng)使用的模板文件的結(jié)構(gòu)和原理。Service層主要負(fù)責(zé)數(shù)據(jù)庫的CRUD的邏輯操作,圖4是Service層插入數(shù)據(jù)到數(shù)據(jù)庫的模板片段。
圖4 Service層插入數(shù)據(jù)到數(shù)據(jù)庫的模板片段
從圖4中可以看到,整個(gè)代碼分為兩部分,其中${}中的代碼為動(dòng)態(tài)代碼,其他為靜態(tài)代碼。對(duì)于靜態(tài)代碼,代碼解析器不會(huì)做任何的解析直接輸出到對(duì)應(yīng)的程序文件中,對(duì)于動(dòng)態(tài)代碼,代碼解析器會(huì)從業(yè)務(wù)對(duì)象中取出對(duì)應(yīng)的數(shù)據(jù),輸出給Freemarker模板引擎,然后由模板引擎進(jìn)行動(dòng)態(tài)替換,合成最終的程序文件。
表1 模板說明表
本后臺(tái)系統(tǒng)采用的是J2EE體系結(jié)構(gòu),與J2EE體系相對(duì)應(yīng),本文提供了每一層的代碼模板,具體如表1所示,其中表現(xiàn)層除了 Controller模板外,在Component文件夾中定義了前端頁面所使用的組件模板,在uiTemplate目錄下定義了前端展示的增刪改查頁面。
圖5 代碼生成器類圖
3.2.4 代碼生成引擎
本代碼生成器是以command.bat文件為入口,通過命令行方式驅(qū)動(dòng)代碼生成器的運(yùn)行,如圖5所示,其中commandLine負(fù)責(zé)命令的接收,在命令行中以參數(shù)的形式指定生成器類型和業(yè)務(wù)文件??蛇x的生成器包括 generateDAO、generateController、generateCRUD三種類型,其中g(shù)enerateDAO負(fù)責(zé)生成數(shù)據(jù)持久層代碼,generateController在generateDAO的基礎(chǔ)上生成邏輯層和控制層的后端代碼,generateCRUD在generateController的基礎(chǔ)上繼續(xù)生成前臺(tái)頁面。代碼生成過程如圖5所示:首先commandLine調(diào)用JSONParser進(jìn)行業(yè)務(wù)文件解析,將解析結(jié)果以對(duì)象的形式保存下來,然后commandLine利用 Java的反射機(jī)制[13-14],調(diào)用DefaultGenerator中對(duì)應(yīng)的生成器方法并將業(yè)務(wù)參數(shù)傳遞過去,進(jìn)行代碼生成。
眾所周知,中小軟件外包公司承接的項(xiàng)目中Web后臺(tái)系統(tǒng)占有較大的比例,很適合利用本文設(shè)計(jì)的代碼生成器進(jìn)行項(xiàng)目開發(fā)。經(jīng)過努力和推廣,本代碼生成器已經(jīng)在某軟件外包公司中得到應(yīng)用。根據(jù)使用之后的反饋結(jié)果,使用代碼生成器可以快速構(gòu)建一個(gè)后臺(tái)系統(tǒng)雛形,明顯地縮短了項(xiàng)目的開發(fā)周期,減少了軟件開發(fā)人員的重復(fù)工作。但是與此同時(shí),也暴露出了一些問題,如:業(yè)務(wù)文件語法復(fù)雜;只能生成系統(tǒng)指定J2EE架構(gòu)的 Web項(xiàng)目;只支持 Oracle和 My SQL兩種類型的數(shù)據(jù)庫等。針對(duì)實(shí)際使用中的問題,在后續(xù)的開發(fā)中,將對(duì)代碼生成器進(jìn)行逐步的完善,達(dá)到最終支持完全可視化配置和驅(qū)動(dòng)的目標(biāo)。
[1]曹鳴鵬,趙偉,許林英.J2EE技術(shù)及其實(shí)現(xiàn)[J].計(jì)算機(jī)應(yīng)用,2001,21(10):20-23.
[2]袁梅冷,黃煙波,黃家林,等.J2EE應(yīng)用模型中MVC軟件體系結(jié)構(gòu)的研究與應(yīng)用[J].計(jì)算機(jī)應(yīng)用研究,2003,20(3):147-149.
[3]陸榮幸,郁洲,阮永良,等.J2EE平臺(tái)上MVC設(shè)計(jì)模式的研究與實(shí)現(xiàn)[J].計(jì)算機(jī)應(yīng)用研究,2003,20(3):144-146.
[4]李剛.Struts 2.1權(quán)威指南[M].北京:電子工業(yè)出版社,2009.
[5]單東林,張曉菲,魏然.鋒利的jQuery[M].北京:人民郵電出版社,2009:35-42.
[6]費(fèi)拉納提.Javascript權(quán)威指南(第5版)[M].李強(qiáng),等譯.北京:機(jī)械工業(yè)出版社,2007:56-67.
[7]丁振凡.基于Spring Security的Web資源訪問控制[J].宜春學(xué)院學(xué)報(bào),2012,34(8):71-74.
[8]焦寧波,常炳國.Spring Security構(gòu)建靈活的企業(yè)級(jí)安全應(yīng)用[J].計(jì)算機(jī)光盤軟件與應(yīng)用,2011(1):7-8.
[9]百度百科.Maven[EB/OL].http://baike.baidu.com/view/336103.htm,2013-07-23.
[10]李澎林,朱國清,吳斌.基于iBatis SQL Map的數(shù)據(jù)持久層實(shí)現(xiàn)應(yīng)用研究[J].浙江工業(yè)大學(xué)學(xué)報(bào),2008,36(1):72-76.
[11]劉軍,戴金山.基于Spring MVC與iBatis的輕量級(jí)Web應(yīng)用研究[J].計(jì)算機(jī)應(yīng)用,2006,26(4):840-843.
[12]韓義波,宋莉,宋俊杰.Ajax技術(shù)結(jié)合XML或JSON的使用比較[J].電腦知識(shí)與技術(shù),2009(1):101-103.
[13]王開,譚翼,周蘭江.Java中反射機(jī)制淺析及應(yīng)用[J].電腦知識(shí)與技術(shù),2007(1):255-256.
[14]張航,藍(lán)雯飛.探尋Java反射機(jī)制的奧秘[J].計(jì)算機(jī)光盤軟件與應(yīng)用,2011(9):203.