上一篇文章 從產品展現頁面談談Hybris的特有概念和設計結構 咱們講解了Hybris一些特有的概念以及大致架構,而且介紹了Facade層裏是如何定義DTO(Data Transfer Object)對象。前端
一個還沒有回答的問題: 爲何DTO(在上一篇文章的具體例子裏是Java類ProductData)會由Converter來生成?spring
這篇文章就今後問題開始。數據庫
咱們再次翻出上一篇文章展現過的這張架構圖。設計模式
當咱們打開一個Hybris應用網頁,好比某個Product(產品)的明細頁面時, 背後實際上執行了下列的邏輯:數據結構
Service層從數據庫裏把數據取出,以Model(又稱爲DAO對象)的形式返回給Facade層。架構
Facade層調用Converter, 在Populator的幫助下,基於Model生成了DTO。框架
明細頁面的Controller將其對應的JSP路徑返回給Hybris框架。url
上述步驟完成以後,咱們便可看到數據填充完畢以後的Hybris Product明細頁面。設計
本文將詳細介紹上述步驟(2), 即DTO的生成邏輯。code
當點擊這個名爲DSC-H20 BLUE的產品圖片後,
能夠跳轉到它的明細頁面。
其中DAO的生成,也就是下圖137行代碼裏的變量productModel的生成邏輯,會在下一篇文章即這個系列的第三篇文章詳細闡述。 本文咱們重點介紹DTO(第138行變量productData的生成邏輯)。
如今咱們能夠簡單地把DAO對象,即變量productModel理解成它包含了DSC-H20 BLUE這個產品在數據庫裏存儲的明細。
若是有ABAP開發經驗的朋友,能夠把這個變量包含的內容類比成ABAP裏經過OPEN SQL從透明表裏取出的數據。 這些數據因爲格式緣由還不能直接給上層的UI作展現,而須要通過進一步的加工和處理。這些加工由下文的converter和populator來完成。
以前咱們介紹了DTO(productData)是由第138行的convert方法生成的。這個方法的調用者是getProductConverter方法返回的一個Converter的實例,該實例其實是Spring框架幫咱們注入的一個Bean。對Bean這個概念不熟悉的朋友能夠用關鍵字"Spring Bean"在百度或者Google上搜索。
那麼ProductConverter這個Bean的Spring相關定義在Hybris項目文件夾的什麼地方呢?
前一篇文章從產品展現頁面談談Hybris的特有概念和設計結構介紹過,產品相關的Facade層存在於bin/ext-commerce/commercefacades這個extension。而在其中的resource/commercefacades-spring.xml文件中能夠找到productConverter的定義:
第137行到139行代表實際注入的populators屬性是一個列表(List),這個List裏的每個元素是ProductPopulator。 從List這個數據結構咱們能夠猜測到,Converter主要是經過調用1個或多個Populator來生成DTO對象的。
咱們再來看看Populator這個接口的代碼,它定義了一個名爲**populate(SOURCE,TARGET)**的方法。方法的註釋清楚地說明了Populator是用Source變量的字段值去生成(Populate)Target變量的字段值,以下圖所示。
回到咱們的Product明細頁面的展現例子。在ProductPopulator中:
Source對應Java類ProductModel
Target對應Java類ProductData
可見, Populator通常用於從Service層的DAO對象生成Facade層的DTO對象。
關於Populator的實際例子, 咱們能夠看看ProductUrlPopulator這個類, 它是接口Populator的一個具體實現類, 位於packagede.hybris.platform.commercefacades.product.converters.populator下面。從這個package下面咱們也能發現不少其餘的Populator,這也解釋了本文Converter章節裏介紹的爲何Populator屬性注入的類型須要選擇爲List。
從populate方法中能夠看到:
DTO ProductData裏的code和name屬性的值都是直接取自DAO ProductModel裏對應的同名屬性;
DTO ProductData的url屬性則是第47行的resolve方法根據DAO ProductModel計算出來的。
這個resolve方法的使用,代表了Populator不僅是簡單的把DAO對象的值設置到DTO對象中。在Hybris的標準實現裏諸如Product url屬性這樣須要調用其它Service來處理後而後再展現到前端的例子還有不少。
好比商品的庫存,多貨幣價格等信息, 在數據庫端原本就沒有和產品信息存在同一張表,天然也不能直接從Product的DAO對象中獲取,而是須要在相關的Populator裏調用單獨的物流處理和價格處理的Service來生成。
這裏咱們再回想下Hybris的三層結構圖。
設想下若是沒有Facade層和DTO對象,前端的Controller將不得不調用不少Service,返回不少單獨的Model(如產品,物流和價格信息)給頁面,加劇頁面處理的負擔。而Hybris的Facade層包裝了Service層的複雜邏輯,爲前端提供了簡明統一的DTO對象,大大下降了前端的處理複雜度。這正是面向對象設計模式中的Facade(外觀)模式的體現,所以咱們可以從Hybris的架構圖中發現Facade層的名字。
但願你們經過這篇文章對Hybris Facade層的Converter和Populator能有比較詳細的瞭解。下一篇咱們將繼續介紹Hybris的Service層。
Jerry注:
優秀的產品老是有着類似的設計思路。本文介紹的DAO和DTO, 不只僅出如今Hybris裏,在SAP的不少其餘產品裏也有用到。
在SAP CRM裏,從ABAP數據庫裏取出的數據由於結構差別沒法直接被SAP CRM的BSP UI消費,必需要在圖中的Generic Interaction Layer裏作一個結構和格式的轉換:
下圖是SAP CRM UI上產品長文本字段的一個截圖:
這個長文本字段的值, 從數據庫取出到最後顯示在UI上,也經歷了在Populator(下圖的ABAP類: CL_CRM_PRODIL_LONGTEXT)裏從DAO到DTO的轉換。
至此咱們能發現不管是在SAP Hybris仍是SAP CRM裏,這種DAO到DTO的映射都體如今具體的代碼裏。
而在SAP Business by Design, SAP Hybris Cloud for Customer和SAP S/4HANA裏,這種DAO到DTO的映射關係則維護在一些模型裏。這樣, 應用開發人員負責維護映射關係,而框架負責統一處理映射關係。即便未來由於業務變化致使這些映射關係也須要發生變化,此時能夠僅修改維護映射關係的模型,而無需修改任何代碼。
SAP把底層模型層(Model Layer)和上層消費層(Consumption Layer)之間的存儲及解析映射關係模型的這一中間層稱爲SADL(Service Adaptation Definition Layer, L在有的上下文裏也稱爲Language)。維護映射關係的模型則成爲SADL模型。以下圖所示:
在這個系列的下一篇文章裏,Jonathan將介紹Hybris Commerce的持久層設計原理。
要獲取更多Jerry的原創技術文章,請關注公衆號"汪子熙"或者掃描下面二維碼: