从产品展现页面谈谈Hybris系列之二: DTO, Converter和Populator

文章做者:张健(Zhang Jonathan)

上一篇文章 从产品展现页面谈谈Hybris的特有概念和设计结构 咱们讲解了Hybris一些特有的概念以及大致架构,而且介绍了Facade层里是如何定义DTO(Data Transfer Object)对象。前端

一个还没有回答的问题: 为何DTO(在上一篇文章的具体例子里是Java类ProductData)会由Converter来生成?spring

这篇文章就今后问题开始。数据库

咱们再次翻出上一篇文章展现过的这张架构图。设计模式

当咱们打开一个Hybris应用网页,好比某个Product(产品)的明细页面时, 背后实际上执行了下列的逻辑:数据结构

  1. Service层从数据库里把数据取出,以Model(又称为DAO对象)的形式返回给Facade层。架构

  2. Facade层调用Converter, 在Populator的帮助下,基于Model生成了DTO。框架

  3. 明细页面的Controller将其对应的JSP路径返回给Hybris框架。url

上述步骤完成以后,咱们便可看到数据填充完毕以后的Hybris Product明细页面。设计

本文将详细介绍上述步骤(2), 即DTO的生成逻辑。code

DAO

当点击这个名为DSC-H20 BLUE的产品图片后,

能够跳转到它的明细页面。

其中DAO的生成,也就是下图137行代码里的变量productModel的生成逻辑,会在下一篇文章即这个系列的第三篇文章详细阐述。 本文咱们重点介绍DTO(第138行变量productData的生成逻辑)。

如今咱们能够简单地把DAO对象,即变量productModel理解成它包含了DSC-H20 BLUE这个产品在数据库里存储的明细。

若是有ABAP开发经验的朋友,能够把这个变量包含的内容类比成ABAP里经过OPEN SQL从透明表里取出的数据。 这些数据因为格式缘由还不能直接给上层的UI作展现,而须要通过进一步的加工和处理。这些加工由下文的converter和populator来完成。

DTO

以前咱们介绍了DTO(productData)是由第138行的convert方法生成的。这个方法的调用者是getProductConverter方法返回的一个Converter的实例,该实例其实是Spring框架帮咱们注入的一个Bean。对Bean这个概念不熟悉的朋友能够用关键字"Spring Bean"在百度或者Google上搜索。

那么ProductConverter这个Bean的Spring相关定义在Hybris项目文件夹的什么地方呢?

  1. Converter

前一篇文章从产品展现页面谈谈Hybris的特有概念和设计结构介绍过,产品相关的Facade层存在于bin/ext-commerce/commercefacades这个extension。而在其中的resource/commercefacades-spring.xml文件中能够找到productConverter的定义:

第137行到139行代表实际注入的populators属性是一个列表(List),这个List里的每个元素是ProductPopulator。 从List这个数据结构咱们能够猜测到,Converter主要是经过调用1个或多个Populator来生成DTO对象的。

  1. Populator

咱们再来看看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的原创技术文章,请关注公众号"汪子熙"或者扫描下面二维码:

相关文章
相关标签/搜索