今天這篇文章來自我的同僚,SAP成都研究院Hybris開發團隊的開發人員Zhang Jonathan(張健)。需要特别介紹的是,張健和成都研究院的其他開發同僚不同,張健畢業于電子科技大學,讀的專業是英語,也就是說Jonathan是文科背景。但是張健畢業後的第一份居然選擇了程式設計工作,而且是在IBM大型機上的程式設計工作。沒錯,就是用下面這個龐然大物寫代碼, 厲害吧!

然後,Jonathan在他大四上學期時,參加了IBM在電子科技大學計算機學院開展的大型機教育訓練,從此開始了他的大型機程式設計之路。用的程式設計語言是COBOL。好古老的程式設計語言啊!
一個英語專業的畢業生從事IBM大型機程式設計工作,這本身就很傳奇了。然而傳奇還沒有結束,2016年底,Jonathan選擇了跨程式設計語言跨行業,從他已經積累了豐富開發經驗的COBOL語言大型機開發領域裡,轉投Java開發。他申請了SAP成都研究院Hybris開發工程師的職位,這之前他隻是業餘自學過Java,有過不到半年的Web項目經驗。
(如果是一般的軟體公司,對于這種profile和崗位需求不太符合的履歷,可能直接就拒掉了。但是在Jonathan應聘之前,SAP成都研究院有過成功的案例。我們之前招過一位同樣是英語專業背景的應聘者。該應聘者畢業後10年期間一直從事英語專業的工作, 隻是業餘時間喜歡寫代碼。他應聘的是SAP Fiori開發工程師。成功通過面試後,他利用在SAP成都研究院工作的18個月時間,成為了一位前端大神。他叫Wu Ji吳脊)
時任SAP成都Hybris開發團隊項目經理的Derry和我一起對Jonathan進行了面試,Derry給Jonathan用優盤拷貝了一份Hybris開發環境,替他申請了一個通路Hybris幫助文檔的賬号,然後布置了三道題目。這三道題目的内容是在這個Hybris開發環境上,給目前版本的Hybris實作一些新的功能。
Jonathan完成得非常迅速,每天通過郵件向Derry和我彙報完成進度,同時提出一些他在完成題目過程中的思考和疑問。最後隻花了一周時間非常完美地完成了這三道題。我覺得考慮到他英語專業的背景和過去大型機的開發經曆,這一切簡直不可思議。
現在Jonathan在SAP成都Hybris開發團隊工作了1年多的時間,已經成長為團隊裡開發的中堅力量,赢得了團隊裡所有同僚們的信任。
下文是Zhang Jonathan(張健)的原創文章。
本文介紹的Hybris全稱是Hybris ECP(Enterprise Commerce Platform), 為簡單起見,下面一律簡稱為Hybris。
Hybris是SAP旗下的電商平台産品,在國外電商産品評測中都位居前列,是兼顧擴充性和易用性的綜合性平台。下圖為gartner的2017電商産品評測報告。
注1: 上圖報告來自網站
<a href="https://www.hybris.com/en/gmc32-gartner-mq-digital-commerce">https://www.hybris.com/en/gmc32-gartner-mq-digital-commerce</a>
這篇文章将結合hybris的産品展示頁面,簡單介紹一下hybris的主要概念和工程結構。
首先介紹下一些hybris特有的概念。
在hybris裡,accelerator是指由一些hybris功能子產品構成的,能完成b2b和b2c等電商場景的hybris執行個體。一般譯為加速器,用于模拟和示範用途,也可以根據客戶需求做一些簡單的定制開發直接用于生産環境。
recipe是用來安裝hybris的一些腳本,具體存在于hybris的installer檔案夾下的recipe子檔案夾。可以用來安裝加速器,SAP整合版本乃至docker版本的hybris執行個體,每個recipe擁有以自己名字命名的檔案夾,裡面具有一個build.gradle檔案, 其内容是所有安裝此recipe需要的腳本。
從業務來講,extension是服務于某個hybris業務的功能子產品。從工程來講,解壓hybris後,bin檔案夾的每個子檔案夾内都包含一個工程檔案夾,每個工程檔案夾都是一個extension. recipe安裝的元件就是若幹extension的組合。
hybris的設計具有很好的産品可擴充性,這表現為Hybris提供了很多模闆工程(template extension)供客戶參考,擴充,或直接使用。本文介紹的産品頁面的View層就存在于yacceleratorstorefront這個模闆内。
我們再來介紹一下hybris的總體結構劃分。
Hybris和很多主流Web應用一樣,使用Spring Framework進行開發。以常見的使用Spring MVC的工程為例,一般可簡單分為前端頁面(View層),Spring MVC Controller和Spring注入的Service(Controller層),整合ORM架構的DAO(Model層)。
Hybris大緻劃分為三層,和經典MVC不同在于: Hybris前端頁面和Spring MVC Controller統一為View層,Service和DAO統一為Service層,Facade(即DTO資料傳輸對象層)在中間單獨為一層。這三層都分别存在于一個extension内,繼而構成hybris工程的整體。
注2: 上圖的DTO, Converter和Populator的概念将在後續系列文章詳細介紹,這裡隻需簡單了解成它們的作用就是把業務資料從資料庫裡讀取出來并且進行格式轉換便于提供給Controller用于最終将資料展現在UI上。DAO和DTO都不是Hybris特有的概念,而是軟體系統設計中的通用概念,其定義如下:
本次示範安裝的是hybris 6.5的release版本,安裝包是大小為2GB左右的zip檔案。以windows為例,解壓後,簡單用下面幾個指令就可從installer檔案夾啟動一個hybris的執行個體。其中的initialize步驟是資料初始化的過程,時間較長請耐心等待,我們使用的b2c_china這一recipe就是SAP成都研究院的Hybris開發團隊開發的中國定制版加速器。
在hybris啟動完畢後,用如下連結打開首頁後,任意點選一個産品即可進入産品詳情頁面。
<a href="https://localhost:9002/yacceleratorstorefront?site=electronics">https://localhost:9002/yacceleratorstorefront?site=electronics</a>
因為一個hybris執行個體可以支援多個電商網站共享一套代碼,類似SAP Hybris Cloud for Customer裡的multi-tenant的概念, 是以通路某一網站需要加上site這個參數。
如下圖:
本文接下來将介紹從使用者點選産品連結,到看到該産品的詳情頁面這一過程,Hybris應用背後到底發生了哪些事情。
産品的連結是以”/p/+産品代碼”結尾的一串很長的字元,”/p/”之前的部分是用産品詳細類别和産品名稱拼成的,根路徑是yacceleratorstorefront。
前面也提到過yacceleratorstorefront是hybris主要的view層template extension,它位于bin/ext-template目錄下。在它的web/src目錄下有spring mvc controller的代碼; web/webroot目錄下則包含了所有的前端頁面代碼(使用JSP+Jquery)。
在上述web/src目錄中找到産品頁面展示的ProductPageController裡的方法productDetail(productCode),其中擷取産品明細資料通過調用facade層的productFacade.getProductForCodeAndOptions(productCode, extraOptions) 方法,可以繼續檢視此方法的實作,看它如何傳回産品的DTO對象ProductData。
在facade的具體實作DefaultProductFacade裡,可以看到ProductData是由ProductConverter的convert方法基于ProductModel生成的。那麼什麼是Converter呢?為什麼一定要調用它來生成DTO對象呢?
這裡我們可以先找到DefaultProductFacade的位置,它位于bin/ext-commerce這個檔案夾下的commercefacades。這個extension正如它的命名,實際上還提供了很多如訂單,産品目錄等等的commerce相關的DTO對象。觀察它的結構,可以找到resource檔案夾下有兩個xml檔案,commercefacades-beans.xml和commercefacades-spring.xml。前者是定義DTO對象的地方,後者當然是提供spring配置的。
在Hybris裡,無論DTO對象(以Data結尾的Java類)還是DAO對象(以Model結尾的Java類), 都不是通過直接手動編寫Java代碼來建立的,而是通過在xml檔案裡定義對象屬性, 然後經過編譯,以POJO(Plain old Java object)的形式生成在platform這個extension裡。 通過這種基于配置檔案生成Java類的方式,實作了對象定義和代碼的隔離。這樣即使以後需要給對象增減屬性, 再也不用去逐一添加修改屬性對應的get和set方法,隻需要改變xml裡對應的定義,重新編譯即可。
注3: POJO也不是SAP Hybris的一個專屬概念,而是軟體設計裡的一個通用概念。Wiki定義如下:
<a href="https://en.wikipedia.org/wiki/Plain_old_Java_object">https://en.wikipedia.org/wiki/Plain_old_Java_object</a>
下一篇我們将詳細介紹Hybris的Facade層和Service層, 包括DTO, DAO, Conveter, Populator這些子產品的作用。
要擷取更多Jerry的原創技術文章,請關注公衆号”汪子熙”或者掃描下面二維碼: