Hybris平台Web架構模式演變:前後端分離
深度技術文章,第一時間送達!
「前後端分離」顯然已不是什麼新鮮的話題,表面上看是一場架構模式的變革,但實質上是為了解決以往傳統的服務端MVC設計模式的一些詬病和痛點。前後端分離帶來的全新的前後端協作方式能夠讓專業的人做專業的事,無論前端後端都能更專註在自己擅長的方面。那麼如何基於一個成熟的Hybris平台進行前後端分離?接下來,我們將會逐一剖析這個演變過程。
Hybris平台Web層現狀
眾所周知,Hybris平台是一套成熟的電商解決方案,當然也包括Web層的定製化。由於Hybris平台項目至今已經經歷過許多版本,對電商的核心流程進行了不同程度上的重組與優化。對於Web層,相對於核心流程來說,升級的速度和頻率則顯得稍微緩慢。慢慢的我們會發現,在當前前端技術突飛猛進的發展趨勢下,Hybris平台Web層的技術體系會變的相對陳舊,比如:缺少了動靜分離。因此,在這個技術體系下進行Web層的二次研發,往往還面臨著前後端耦合依賴的局面,導致項目進度緩慢。
Hybris平台Web層架構的不足
Hybris平台Web層基於傳統的服務端MVC(Model-View-Controller)設計模式,傳統的服務端MVC架構在為我們提供優勢的同時也會帶來以下不足:
1. 對於簡單的頁面,嚴格遵循MVC,會增加結構的複雜性,並可能產生過多的更新操作,降低運行效率
2. 視圖與控制器之間過於緊密的連接。視圖沒有控制器的存在,其應用是很有限的,反之亦然,這樣就妨礙了他們的獨立重用。
3.View的渲染通過服務端完成,最終呈現給瀏覽器的是帶有Model的視圖頁面,性能無法得到很好的優化
4. 控制器會變得複雜,很多人會在Controller(Spring),Action(Struts)中寫業務代碼已經變得很常見,所有的操作都在控制器中,導致業務與控制器相耦合
5. 對象間接地通過控制器耦合在一起,一個對象在控制器中查詢獲得,然後複製給另外一個對象,這兩個對象就耦合在一起
6. View通過服務端完成後,視圖頁面包含CSS, JS等資源,這些資源需要重新請求(雖然可能已經進行了緩存)
Hybris平台前後端協作的痛點
由於Hybris平台基於傳統的服務端MVC(Model-View-Controller),在這個模式下,前後端協作模式一般採用以下兩種方式:
1. 前端直接在服務端View中編寫模版,這樣做的問題在於,編寫的過程中強依賴服務端環境。在服務端沒有完成的情況下,前端無法進行完整測試
2. 前端先編寫靜態原型,完成後,後端在View中套用靜態原型。這樣做的問題在於,服務端需要對前端代碼進行瀏覽,以免出錯
這兩種協作方式都存在問題。
在模式一下,前端必須掌握一定的服務端JSP技術,並且還需要對Hybris平台內部View的劃分機制有一定的了解。因此,學習成本是我們第一要面對的問題。此外,視圖的測試依賴服務端環境,導致測試滯後。
在模式二下,首先帶來的是時間、成本的消耗,靜態原型對於用戶來說不是最終的產品,只是開發過程中的一個過渡品。其二,將靜態原型轉換到服務端View的過程中,後端開發人員需要了解前端的設計,比如:如何找到正確的切分點將一個完整的靜態頁面切分成若干小的片斷,並應用於服務端。在比如:如何正確地使用前端的第三方庫?這些問題,不同的前端技術有著不同的做法,因此當後端開發人員在套用靜態原型的過程中,無形當中增加了了解,學習前端技術的成本。其三,在靜態原型沒有完成情況下,如果服務端開發工作已經完畢,那麼前後端集成工作則處於等待狀態,造成集成緩慢。
如何解決這些不足,並消除痛點呢? 這就是我們近期在使用傳統技術經過搭建了幾十個Hybris電商運營網站之後進行的一次大膽的前後端分離的嘗試,取得了很好的效果。下面,將為讀者分享Hybris平台Web架構模式演變及並行化實踐。
Hybris平台Web前後端分離
Web架構
上圖可見,我們將View、Controller從傳統的服務端MVC架構中遷移到客戶端。客戶端負責視圖的渲染,交互的控制。數據的獲取通過Restful API介面使用JSON格式交互。而後端只需要負責業務邏輯,數據的存儲,數據模型的定義,並為前端提供JSON格式的數據。
這樣改變之後,頁面的渲染完全從服務端分離出來,並且渲染之後的後續交互,數據都交由客戶端代碼完成。在這樣的架構模式下,前端代碼倉庫與後端隔離,前端獨立負責靜態資源,View模板的維護和發布。
代碼組織方式
前後端未分離:傳統的服務端MVC架構下,前後端代碼放置在同一個代碼倉庫中,前端開發過程中需要導入整個代碼倉庫,並且很難獨立部署與運行。
前後端分離:前後端代碼庫分離,前端代碼可以進行數據的本地化Mock,因此前端可獨立開發和測試,以及部署。而後端 代碼中除了功能實現外,還有著詳細的測試用例,以保證API的可用性,降低集成風險。
帶來的挑戰
新的Web架構在給前端帶來更多的便利性的同時,也同樣帶來了不小的挑戰。比如,如何繼續遵循Hybris平台後端開發最佳實踐,如何統一進行JSON數據轉換等等一系列的問題,在我們開發過程中一一浮出水面。有些是在做出這種架構選擇時就預見到的,有些是在具體實施中遇到的。
1. 前端技術選型
既然客戶端負責View,我們就需要選擇一種適合的前端框架來滿足要求,從而丟棄傳統的Hybris平台前端框架JQuery. 在進行斟酌後,對於前端技術採用如下:
ECMAScript + React + Node + NPM+ Typescript
其中React最為核心,它不但提供了虛擬DOM機制,並且組件化的開發思想使的頁面結構化合理。前端開發可以完全關注到組件的開發中,進行模板的編寫、數據的綁定、事件的處理。開發過程中不會受到後端的影響,順利完成本地化測試。
2. 遵循Hybris平台後端開發最佳實踐
Hybris平台對於每一個頁面請求,都有與之對應的控制器,並且平台的Web層基於Spring MVC框架,利用這些特點,我們決定將每一個OOTB 控制器包裝成為一個完成數據交互的Endpoint,從而為前端提供Rest風格的API介面。與此同時,在Hybris平台內部,仍然採用DTO(Data Transfer Object )作為API服務層與Fa?ade層之間的數據傳輸對象,平台內部的數據轉換過程不需要發生任何改變,仍然採用Converter/ Populator機制。
3. JSON數據轉換
正如上文提及,每一個頁面請求,都有與之對應的控制器。比如:購物車頁面對應CartPageController,產品分類頁面對應CategoryPageController,當瀏覽器根據不同的頁面完成PageLoad後,將會觸發控制器中默認的Get方法中,通過該方法為視圖提供所需要的數據。由於在Rest API層面上,我們仍然採用DTO作為數據載體,可見,在這些默認的Rest Get方法中,將會侵入一些代碼片斷用來完成DTO到JSON的轉換。顯而易見,如果在每一個默認的Rest Get方法中都加入轉換代碼不是一個很好的處理方式,會造成代碼的過渡重複,產生壞味道。那麼,我們如何從原始的代碼中將數據轉換的過程分離出來呢?我們採用了BeforeViewHandler攔截器。
優點:
攔截器可以自動攔截到需要進行數據轉換的Rest Get 請求
數據轉換代碼與控制器解偶,通過攔截器完成
易於配置管理
4. 組件中的JSON處理
對於可以重複使用的頁面片斷,Hybris平台採用組件的方式進行處理。比如:Global Header, Global Footer. 在前後端分離的架構下,客戶端同樣負責View的渲染,那麼Hybris 的組件又該如何為前端提供所需要的數據呢?Hybris允許為組件配置對應的控制器,當一個請求導向至組件時,對應的控制器將會自動觸發。但是由於Hybris對於組件控制器的管理與常規有所不同,在受置於其的約束下,我們無法使用BeforeViewHandler攔截器來處理,因此,採用JSON-taglib為前端View提供JSON數據則成為一種可選方案。
提供安全機制
前後端分離的Web架構中,如何解決交互過程中產生的安全性風險是需要考慮的另一個問題。
1. 基於Hybris平台自身的特性,通過Spring Form 提交的表單,自身已經加入CSRF Token 校驗機制。那麼如何在HTML Form提交的過程中避免CSRF攻擊呢?
解決方式:
利用Hybris OOTB 服務生成CSRF Token, 並將 Token返回前端
在每一次提交過程中,Token會作為數據的一部分提交給後端
利用Hybris OOTB CSRF校驗機制進行Token的驗證
2. 敏感數據的加密處理
在數據傳輸的過程中,我們需要對敏感數據進行必要的加密處理,避免明文數據的傳輸,減少非正常請求的攻擊。
解決方式:
Hybris通過RSA生成公鑰,私鑰(公鑰/私鑰是基於1024+ Base64S 加密),並將公鑰返回前端
前端使用公鑰以及RSA client lib進行加密,並把加密後的數據傳遞給Hybris。此時在網路傳輸過程中,使用的是加密後的數據
Hybris 使用私鑰進行解密後,再使用必要的敏感數據
3. Restful API的安全機制
對於Restful API的調用,採用授權認證的安全機制來約束匿名與非匿名請求。比如,對於下訂單流程中所暴露的API,必須是登錄成功後的用戶才能訪問,限制匿名用戶請求。
解決方式:
採用註解方式,顯示地聲明一個Rest API為Require Hard LogIn
性能考慮
在前後端分離的架構模式下,前端有且僅有靜態內容。View視圖的渲染脫離服務端,不需要任何服務端技術進行動態化組裝,因此對於前端資源可以考慮CDN加速,緩存機制,從而提高性能。
由於前端內容是完全的靜態內容,在初次獲取以後的大部分時間內,瀏覽器使用的就是本地緩存,也就是說,伺服器的壓力主要來自於承載數據的Restful API調用。因此,合理的對象創建,以及業務邏輯的優化能夠幫助我們減少性能的開銷。比如:
1. 減少DTO對象的創建
對於一個頁面所需要的數據,盡量一次性提供完畢,減少DTO的多次創建,使DTO到JSON的轉換隻發生一次,從而減少數據轉換帶來的性能開銷
2. 攔截器最小化配置
對於BeforeViewHandler,刪除不需要監聽的請求,從而減少BeforeViewHandler內部流程,提高代碼性能
最後,對於電商網站來說,圖片資源的管理與使用同樣是性能的一個考核指標。在這裡,我們對於圖片資源的規劃採用的方式是:將圖片實體獨立出Hybris 電商文件系統。即Hybris電商文件系統不存儲任何圖片實體,通過OOTB Media對象保存產品或者內容與圖片的映射關係。真正的圖片實體則被保存在其他第三方系統,例如:Scene7,Amazon S3。由於Hybris 只保存映射關係,簡單來說就是資源的URL,並通過Restful API將URL返回給前端。那麼當請求訪問一個具體的圖片時,前端可採用懶載入的機制,根據需要才將圖片URL賦予SRC屬性,從而提高前端性能,減輕服務端負擔,提高頁面的載入速度。此外,緩存的合理使用同樣也是提高性能的一種手段。
前後端調用流程
如上圖所示(Promotion detail為例),一套完整的渲染流程包含以上步驟,其中不乏一些技巧,比如:前端如何利用Hybris Page Type屬性來完成JS/CSS文件的查找,從而避免不相關JS/CSS文件的載入。關鍵偽代碼參考如下:
利用Hybris OOTB Page type屬性動態載入對應JS/CSS文件
統一的export function處理JSON數據以及Mock數據的切換,其他組件只需import即可
BeforeViewHandler攔截器定義與配置
JSON數據轉換
結束語
前後端分離的Web架構使得前後端職責更加明確。清晰的分工,可以讓開發並行,減少相互依賴,提高開發效率。View的渲染來自於客戶端,性能上得到進一步的提升。部署相對獨立,很好地應對了複雜多變的前端需求。同時,前後端分離後,應用代碼不再是前後端耦合,只有在運行期才會有調用依賴關係,易於管理與維護。最後,基於Hybris平台的前後端分離的Web架構模式同樣易於向SPA Web應用轉型,帶來更快,更好的用戶體驗。
作者:楊智,現就職於奧博傑天技術有限公司,擔任多個電子商務項目的解決方案架構師。曾擔任未來國際軟體股份有限公司多個項目的技術負責人,負責政府網站以及政務平台設計,研發。參與國家林業局多個系統集成項目。 關注電子商務應用,微服務架構以及DevOps。
※2017年資料庫技術盤點
※三種常見的API設計錯誤及解決方案
TAG:CSDN技術頭條 |