陳學明



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