陳學(xué)明
摘要:Spring作為企業(yè)級應(yīng)用開發(fā)框架,配置煩瑣;Spring Boot簡化了Spring的配置,實現(xiàn)了開箱即用。Ext JS是一站式前端開發(fā)框架,可以搭配Spring Boot買現(xiàn)前后端分離的Java Web應(yīng)用框架。該文基于Spring Boot和Ext JS,提出以實體類為驅(qū)動的前后端協(xié)同開發(fā)和準(zhǔn)前后端分離的通用平臺,在基本規(guī)格確認的基礎(chǔ)上獨立開發(fā),使用單個和數(shù)個JSP頁面實現(xiàn)SPA(單頁面應(yīng)用程序)的開發(fā)方式,通過JSP的Session管理用戶認證信息。該平臺在統(tǒng)一規(guī)格的基礎(chǔ)上,實現(xiàn)開發(fā)分離,提高開發(fā)和測試效率;合并部署,簡化部署過程和部署架構(gòu),適用于中小型及快速開發(fā)的企業(yè)級應(yīng)用。
關(guān)鍵詞:Spring Boot;Ext JS;MVC;MVVM;準(zhǔn)前后端分離;類驅(qū)動;約定優(yōu)于配置
中圖分類號:TP311 文獻標(biāo)識碼:A
文章編號:1009-3044(2019)35-0063-04
1 背景
IoC與AOP是Spring框架最重要的兩個編程思想,基于Spring框架開發(fā)Web應(yīng)用,需要整合MVC框架(比如SpringMVC、Structs2等)、數(shù)據(jù)持久化框架(比如Hibemate、MyBatis等)以及JSP模板引擎等。雖然兼容性是Spring框架的優(yōu)點,但不同的框架搭配對應(yīng)的配置不盡相同,這些配置煩瑣卻又樣板化。對于大多數(shù)企業(yè)級應(yīng)用而言,個性化配置基本沒有要求。提供一種默認的框架組合,在不配置或少量配置的狀況下使用框架開發(fā),就可以省去項目搭建的工作,Spring Boot即在此背景下產(chǎn)生的。
Spring Boot使用默認或簡化配置實現(xiàn)了框架的開箱即用,而且其內(nèi)置了Web服務(wù)器,保持了Web應(yīng)用程序與一般應(yīng)用相同的開發(fā)方式。在應(yīng)用前端展現(xiàn)上,基于Spring Boot框架的Web應(yīng)用,既可以使用后端模板引擎開發(fā)前端頁面,比如Free-Marker或Thymeleaf;也可以作為后端服務(wù)框架搭配前端Web框架進行開發(fā)。
在Spring Boot以及與前端框架結(jié)合的研究上,劉玉號、李沛在基于Spring Boot的后臺服務(wù)器開發(fā)中使用Spring Boot代替SSH或SSM,提出了脫離復(fù)雜的環(huán)境配置,快速搭建Spring應(yīng)用程序Ⅲ;張峰總結(jié)了Spring Boot在應(yīng)用系統(tǒng)開發(fā)的架構(gòu)設(shè)計、開發(fā)、測試、部署和監(jiān)控上帶來了變更和便捷嘲;張雷,王悅對Spring Boot作為MVC的微服務(wù)架構(gòu)進行了研究[3];楊妍探討了Spring Boot與Vue結(jié)合的系統(tǒng)管理模塊開發(fā)[4];莫秋晶,黃志遠等基于Spring Boot設(shè)計和實現(xiàn)了Spring+Vue以及Vue+Elemen-tUI的前后端分離的框架[5];周玉,聞金華,徐建良則研究了ExtJS框架MVC模式的面向?qū)ο蟮膹?fù)用技術(shù)[6]。
基于Spring Boot和JSP或模板引擎的Web開發(fā),無法發(fā)揮前端的優(yōu)勢,前后端代碼混雜,維護性差;開發(fā)人員兼顧前后,無法發(fā)揮專業(yè)化優(yōu)勢,效率不高;完全的前后端分離開發(fā),除了物理架構(gòu)和部署工作量稍大之外,主要是需要單獨處理用戶認證及Session問題。大部分企業(yè)級應(yīng)用的特點是對前端UI和交互的要求較高,需要美觀的頁面樣式的流暢的動態(tài)引導(dǎo),但用戶數(shù)量有限,并發(fā)訪問量不高,對分布式也沒有要求。實現(xiàn)系統(tǒng)豐富、動態(tài)UI同時,簡化系統(tǒng)架構(gòu)和提高開發(fā)效率是本文研究的方向。本文提出了基于Spring Boot+Ext JS的準(zhǔn)前后端分離的通用框架,從規(guī)格出發(fā),以模型類為驅(qū)動,分離前后端開發(fā)、合并部署,實現(xiàn)系統(tǒng)功能性能的同時、簡化開發(fā)的復(fù)雜度和提升開發(fā)效率。
2 Spring Boot與Ext JS介紹
Spring Boot不是全新框架,其是Spring、Spring MVC以及Hibernate等一系列框架的默認配置。中小型的企業(yè)級應(yīng)用系統(tǒng),配置Spring和Spring MVC的配置文件顯得煩瑣,耗費時間且無必要性,基于Spring Boot可以實現(xiàn)零配置。Ext JS包含豐富的前端組件,支持基于MVC和MVVM的開發(fā)模式,是一站式Web框架。
2.1Spring Boot
Spring Boot首版于2014年發(fā)布,本文基于Spring 2.1.9版本。Spring Boot遵循約定優(yōu)于配置,自動檢測JDBC、Hiber-nate、JPA等框架并自動配置,可以開發(fā)桌面應(yīng)用,也可以開發(fā)Web應(yīng)用,因為其內(nèi)置Web服務(wù)器,默認端口8080,基于IDE開發(fā)可像開發(fā)桌面應(yīng)用一樣的開發(fā)Web應(yīng)用,不需要部署到服務(wù)器。
通過Spring Initializr,可以很容易初始化Spring Boot項目,在使用Maven管理項目的狀況下,不需要在pom.xml配置依賴的版本,因為項目默認繼承自spring-boot-starter-parent父項目,該父項目中實現(xiàn)了默認的配置且自動管理依賴的版本?;赟pring Boot的Web應(yīng)用至少需要導(dǎo)入以下依賴項:
1)spring-boot-starter Spring Boot核心啟動器。包括配置、日志等。
2)spring-boot-starter-web:自動引入Web模塊。
基于Spring Boot的應(yīng)用中,@SpringBootApplication是項目的核心注解,其是@Configuration、@EnableAutoConfiguration、@ComponentScan的組合注解。默認配置可以通過application。propenies或application.yml文件進行配置修改。前后端分離架構(gòu)下,控制器使用@RestController注解,返回JSON格式數(shù)據(jù);使用@Service注解服務(wù)類;使用@PersistenceContext注解實體管理器進行數(shù)據(jù)庫持久化操作。
2.2Ext JS
Ext JS提供輸入框、工具欄、下拉單輸入框、表單、表格、樹、圖表等前端組件,支持經(jīng)典(Classic)和現(xiàn)代(Modern)兩種樣式。Classic是傳統(tǒng)樣式,適用在桌面端;Modem是新一代的樣式,考慮了移動端的顯示。開發(fā)上,Ext JS基于面向?qū)ο蟮睦砟?,支持前端類的層級結(jié)構(gòu),通過繼承擴展前端類,類定義格式如下:
Ext.define('全路徑類名',{
extend:'父全路徑類型',
其他配置
})
在Ext JS框架下,可以像創(chuàng)建Java對象一樣創(chuàng)建組件對象。對象創(chuàng)建的語法如下:
Ext。create('類名',{配置項});
早期Ext JS的開發(fā)通過導(dǎo)入。js的文件到JSP或html進行開發(fā),Sencha CMD工具之后,就可以以一個前端應(yīng)用為單位進行開發(fā)了。創(chuàng)建前端應(yīng)用之后,通過配置方式進行視圖組件注冊和組裝,數(shù)據(jù)綁定上,可以選擇MVC和MVVM方式。前端的MVC模式,Model模型類似于后端的實體類,用于定義數(shù)據(jù)的屬性。View是視圖顯示Controller使用Ajax方式調(diào)用后端服務(wù)或是前端的動態(tài)效果。VM是ViewModel,直接綁定數(shù)據(jù)和視圖。
類似Spring Boot,Sencha CMD同樣內(nèi)置服務(wù)器,默認端口是1841,運行sencha app watch既可以在瀏覽器中查看開發(fā)的實時效果,避免瀏覽器緩存的問題且在Chrome等瀏覽器可以進行源調(diào)試。正式環(huán)境部署使用CMD對源碼編譯、壓縮,使用index。html或index。jsp作為你模板,壓縮后JS源碼在一份文件,前端需要的文件數(shù)量和大小都減少了,加快了網(wǎng)絡(luò)傳輸和頁面響應(yīng)的速度。
3 平臺整體設(shè)計
數(shù)據(jù)對象及關(guān)系管理是企業(yè)應(yīng)用系統(tǒng)管理的核心,圍繞此衍生文檔、權(quán)限等其他功能模塊。平臺采用準(zhǔn)前后端分離方式,即:開發(fā)階段,前后端分離開發(fā);集成測試與部署階段,前端編譯產(chǎn)生JSP文件,通過JSP Session管理用戶登錄和認證信息。
3.1平臺功能模塊與設(shè)計
企業(yè)應(yīng)用系統(tǒng)管理企業(yè)運營中的數(shù)據(jù),按照面向?qū)ο蟮木幊趟枷?,這些數(shù)據(jù)可以歸類為不同的對象類型,對這些對象類型的數(shù)據(jù)進行對象信息、狀態(tài)信息以及關(guān)聯(lián)的管理。以辦公自動化系統(tǒng)為例,有請假單、加班單、資源申請單等;以制造企業(yè)的PLM系統(tǒng)為例,有零件、部件、產(chǎn)品等;以ERP為例,有銷售單、入庫單、出庫單、薪資單等。不同對象之間除了其本身的管理之外,還存在與其他對象的關(guān)聯(lián),比如在PLM系統(tǒng)中,各種零件組裝成部件,最后組裝成產(chǎn)品,零部件關(guān)系構(gòu)成物料清單(BOM)。除數(shù)據(jù)本身及關(guān)聯(lián)的管理外,一個完備的框架還包括權(quán)限、日志等管理。該平臺的基礎(chǔ)功能模塊包括:
1)業(yè)務(wù)對象管理:使用數(shù)據(jù)庫表和字段存儲業(yè)務(wù)對象的屬性和內(nèi)容。
2)對象關(guān)系管理:主要包括關(guān)聯(lián)關(guān)系和組合關(guān)系,通過屬性或是關(guān)聯(lián)表實現(xiàn)。
3)文檔管理:文檔包括文件,除文件本身之外,還包括該文件的描述,比如上傳時間、上傳人、更新時間以及版本信息等。
4)權(quán)限管理:包括認證和授權(quán),認證是對當(dāng)前用戶身份有效性的確認,授權(quán)則是對數(shù)據(jù)或動作操作權(quán)限的控制。常用的認證包括:用戶名/密碼,LDAP認證和SSO自動登錄等,授權(quán)則可以分為多個層級實現(xiàn)。
3.2平臺架構(gòu)設(shè)計
平臺基于Spring Boot后端框架、使用Ext JS作為前端框架,采用SPA(single page application,單頁面應(yīng)用程序)的方式。生產(chǎn)環(huán)境中,前后端集成于index.jsp頁面,使用JSP的Session對象管理用戶登錄信息。平臺整體框架如圖1所示。
后端遵循MVC的設(shè)計典范,對外提供RESTful的服務(wù)接口,響應(yīng)JSON格式數(shù)據(jù)。前端利用Ext JS規(guī)范的MVC+MVVM的開發(fā)方式,調(diào)用后端服務(wù)呈現(xiàn)頁面和交互。前后端按照功能模塊拆分目錄,各功能模塊內(nèi)部再按照類的MVC規(guī)劃源碼文件。
3.2.1后端設(shè)計
后端以業(yè)務(wù)實體類型為驅(qū)動進行設(shè)計,源碼對應(yīng)模型層Model、視圖層View和控制層Controlller,各層保持命名的相關(guān)性,以實體類Demo為例,定義的源碼類如表1所示。
使用JPA的EntityManager操作數(shù)據(jù),省去DAO層,在控制器中,ModeIAndView類型返回僅用在主頁登錄或少量特殊需要頁面跳轉(zhuǎn)場景,控制器類基本使用@RestController注解返回JSON格式數(shù)據(jù)。默認對實體類型提供增、刪、該、查的服務(wù)(其中查包括根據(jù)主鍵查詢單個或根據(jù)條件查詢列表),單個實體類默認包括五個服務(wù)。服務(wù)地址遵循RESTful風(fēng)格,結(jié)合不同的HTTP請求方法,以實體類名全小寫后面加s,以Demo類為例,對應(yīng)服務(wù)地址及HTTP請求方法如表2所示。
3.2.2前端設(shè)計
前端同樣以實體類為驅(qū)動,結(jié)合MVC和MVVM架構(gòu)。前端模型類的屬性盡量保持與后端實體類一致,可以適量增減。定義實例類似:
Ext.define('Splm.model.demo.Demo',{
extend:'Ext.data.Model',
fields:[
'obid','name','descrip'
]});
視圖是前端框架中最重要的部分,從Ext JS框架繼承前端組件類,單個實體類對應(yīng)的基本視圖包括:查詢視圖、編輯視圖、查看視圖。
1)查詢視圖:布局分為兩部分,上半部分是過濾條件篩選,下半部分是查詢的結(jié)果列表。
2)編輯視圖:通用于創(chuàng)建和更新,對基本信息欄位進行編輯。布局上輸入框可以一列,也可以多列,還可以是根據(jù)瀏覽器窗口大小自動變化的響應(yīng)式布局。在更新視圖中,使用ViewModel綁定視圖和數(shù)據(jù)。
3)查看視圖,以多標(biāo)簽頁方式顯示,分為基本信息、關(guān)聯(lián)信息、其他信息(比如更新日志等),使用ViewModel綁定基本信息和部分關(guān)聯(lián)信息。
View Model用于自動綁定數(shù)據(jù)和視圖,可以單向或雙向的自動綁定,綁定效果數(shù)據(jù)發(fā)生變化自動顯示在頁面中對應(yīng)的組件或頁面組件輸入值變化自動更新到數(shù)據(jù)。本平臺將ViewModel使用在基本信息的綁定,適用在更新頁面和對象查看頁面。除此的其他非數(shù)據(jù)綁定的場景,通過在控制器中使用Ajax調(diào)用服務(wù),獲取返回后實現(xiàn),比如創(chuàng)建、刪除等功能。
前端類的命名與源碼文件命名保持統(tǒng)一,同樣相關(guān)于實體類的命名,以Demo為例,類命名對應(yīng)DemoQuery、DemoEdit和DemoInfo。
3.2.3前后端數(shù)據(jù)格式與整合
JSP頁面部署在Servlet容器中,根據(jù)客戶端請求,動態(tài)生成HTML等響應(yīng)返回。JSP內(nèi)置了REQUEST、SESSION等九種內(nèi)置對象,瀏覽器端訪問JSP頁面時,會創(chuàng)建SESSION對象,并使用唯一ID保存在Servlet容器中,這個Session的ID會響應(yīng)到瀏覽器端并且記錄在名字是JSESSIONID的Cookie中。瀏覽器在下次訪問該站點服務(wù)時會將JSESSIONID附加上,在后端從Re-quest對象中獲取Session對象。如果Session對象超時,會被清空。但HTML頁面并不具備Session對象,在完全的前后端分離框架中,就需要借助Token實現(xiàn)登錄身份認證,或者持久化Ses-sion信息到文件或是數(shù)據(jù)庫,或者使用JWT讓前端處理驗證。但不管哪種,都要額外處理。完全的前后端獨立框架可以實現(xiàn)分布式架構(gòu),但一般的企業(yè)級應(yīng)用對分布式架構(gòu)和橫向擴展基本沒要求,導(dǎo)入獨立用戶驗證處理會使開發(fā)和架構(gòu)變復(fù)雜。該平臺保留JSP的Session對象,使用Ext JS的CMD編譯產(chǎn)生in-dex。jsp,實現(xiàn)兩者的融合,在每個控制器觸發(fā)的服務(wù)方法上從Session獲取是否存在登錄用戶信息,驗證錯誤則返回對應(yīng)的JSON數(shù)據(jù)交由前端處理。
3.3平臺復(fù)用設(shè)計
前后端都可以通過父類繼承提取共用功能,后端結(jié)合Spring AOP,降低耦和性、增加平臺的動態(tài)擴展性,進一步提高復(fù)用性。
3.3.1后端復(fù)用設(shè)計
模型類和服務(wù)類抽象共用屬性和共用方法的父類。業(yè)務(wù)實體類具備主鍵、創(chuàng)建人、創(chuàng)建時間、更新人、更新時間等基本屬性,考慮顯示的通用性定義一個displayName的動態(tài)屬性,該屬性值由該類型的其他屬性組合而來。公用基本屬性具體如表3所示。
遵循屬性共用原則,模型類結(jié)合屬性及功能所屬,從頂層開始包括:Root(平臺實體類根類)、BusItem(業(yè)務(wù)類型的父類)和DataItem(文檔類型的父類)。
3.3.2前端復(fù)用設(shè)計
前端模型、視圖和控制層都可以定義父類。前端模型父類包含后端基本屬性,考慮查詢頁面、編輯頁面和查看頁面的基本布局的相似性,在父類上設(shè)計基本的頁面布局和設(shè)置,類名設(shè)計為:ItemEdit、ItemInfo、ItemQuery。定義BaseController及其子類ItemController的控制器,BaseController定義基本的方法,比如異常處理、獲取服務(wù)連接,通用Ajax服務(wù)呼叫。ItemCon-troller中定義查詢和創(chuàng)建等功能。而對于Info頁面,因為各實體類的功能不同,不定義父類。
3.3.3AOP設(shè)計
系統(tǒng)屬性值的設(shè)置、日志、權(quán)限驗證等功能通過SpringAOP框架動態(tài)增加。使用@Aspect定義切面類,在切面類中使用@Pointcut和@Around等注解定義切點和增強。
4 框架實現(xiàn)與整合部署
使用Maven管理項目,前后端作為項目模塊構(gòu)建父子項目,基于Eclipse等IDE開發(fā)。開發(fā)階段完全前后端分離,集成測試和部署則合并前后端。
4.1平臺功能模塊與設(shè)計
后端項目不繼承spring-boot-starter-parent,需要配置spring-boot-dependencies的依賴管理。父項目創(chuàng)建一個簡單項目,打包的類型選擇pom。在此項目下建立前后端的模塊。以項目名是crab為例,其包含crab_front和crab_back兩個模塊。
4.2前后端分離開發(fā)與數(shù)據(jù)交互
后端以模型類為驅(qū)動,提供標(biāo)準(zhǔn)RESTful開發(fā),對服務(wù)層和控制層接口的測試使用Spring及MVC測試框架,前端開發(fā)可以在瀏覽器端執(zhí)行或是通過PostMan等工具進行驗證。前端與后端開發(fā)同步進行,不需要依賴后端服務(wù),定義交互格式文件,該文件既可以作為前后交互的規(guī)范,也可以直接用來作為前端的開發(fā)臨時接口服務(wù)。以JSON文件作為數(shù)據(jù)文件格式,提供單個對象和對象類表的數(shù)據(jù)文件,以Demo類為例,查詢和顯示的JSON的文件分別是DemoInfo.json和DemoList.json,內(nèi)容格式如下:
{
"obid":"97d66b3e-338d-40c5-908c-fe33ea0db143",
"sysCreatedDate":"2019/08/18",
"displayName":"Demo 1"
}
{
"total":8,
"datas":[
{
"obid":"97d66b3e-338d-40c5-908c-fe33ea0db143",
"sysCreatedDate":"2019/08/18",
"displayName":"Demo 1"
}
}