今天这篇文章来自我的同事,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: 上图报告来自网站
https://www.hybris.com/en/gmc32-gartner-mq-digital-commerce
这篇文章将结合hybris的产品展示页面,简单介绍一下hybris的主要概念和工程结构。
首先介绍下一些hybris特有的概念。
1. accelerator
在hybris里,accelerator是指由一些hybris功能模块构成的,能完成b2b和b2c等电商场景的hybris实例。一般译为加速器,用于模拟和演示用途,也可以根据客户需求做一些简单的定制开发直接用于生产环境。
2. recipe
recipe是用来安装hybris的一些脚本,具体存在于hybris的installer文件夹下的recipe子文件夹。可以用来安装加速器,SAP整合版本乃至docker版本的hybris实例,每个recipe拥有以自己名字命名的文件夹,里面具有一个build.gradle文件, 其内容是所有安装此recipe需要的脚本。
3. extension
从业务来讲,extension是服务于某个hybris业务的功能模块。从工程来讲,解压hybris后,bin文件夹的每个子文件夹内都包含一个工程文件夹,每个工程文件夹都是一个extension. recipe安装的组件就是若干extension的组合。
4. template
hybris的设计具有很好的产品可扩展性,这表现为Hybris提供了很多模板工程(template extension)供客户参考,扩展,或直接使用。本文介绍的产品页面的View层就存在于yacceleratorstorefront这个模板内。
Hybris的层级结构划分
我们再来介绍一下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开发团队开发的中国定制版加速器。
cd $HYBRIS_HOME_DIR/installer install.bat -r b2c_china setup install.bat -r b2c_china initialize install.bat -r b2c_china start
在hybris启动完毕后,用如下链接打开首页后,任意点击一个产品即可进入产品详情页面。
https://localhost:9002/yacceleratorstorefront?site=electronics
因为一个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定义如下:
https://en.wikipedia.org/wiki/Plain_old_Java_object
下一篇我们将详细介绍Hybris的Facade层和Service层, 包括DTO, DAO, Conveter, Populator这些模块的作用。
要获取更多Jerry的原创技术文章,请关注公众号"汪子熙"或者扫描下面二维码: