java - 使用服务模式和使用独立存储库 Spring Data REST 有什么区别?
问题描述
单独使用 Spring Data REST 存储库和围绕它实现“服务”模式(即ItemService
,ItemServiceImpl
等等)有什么区别?
乍一看,功能或多或少是相同的,不同之处在于服务方法允许更好的定制,但它也会产生大量样板代码(实现和控制器)。这是使用这两种方法的示例(外观Payment
和CreditCard
实体) - Oliver Drotbohm 的 RESTBucks。
那里的支付抽象使用使用的“服务”模式(PaymentService、PaymentImpl 和 PaymentController 以及 web 文件夹中的所有方法),而订单直接通过 Spring Data REST 公开。
解决方案
tl;博士
支付功能存在于更高的抽象级别,因为它不遵循已建立的 HTTP 资源模式(收集资源、项目资源,通常:此处描述的那些),因此需要自定义服务实现。相反,订单聚合的生命周期确实遵循这些模式,因此除了 Spring Data REST 公开和一些自定义之外不需要任何东西。在此处查找有关两个实现部分如何相互关联的概念性概述。
细节
这是一个很好的问题。示例应用程序旨在展示 API 的不同部分如何由不同的需求驱动,以及如何使用 Spring Data REST 来处理遵循既定模式的部分,同时通过更高级别的方面来增强它需要表达业务流程。
该应用程序分为两个主要部分:以Order
通过不同阶段采取的聚合为中心的订单处理。可以在此处找到有关这些的概念性概述。因此,我们的订单 API 的一部分将遵循标准模式:可过滤的集合资源以查看所有订单、添加新订单等。这就是 Spring Data REST 的亮点。
支付部分不同。它需要以某种方式融入订单处理的 URI 和功能空间。我们通过以下步骤实现:
- 我们在专门的服务中实现所需的功能。存储库交互与必要的抽象级别不匹配,因为我们必须验证对
Order
和Payment
聚合的业务约束。这种逻辑需要存在于某个地方:在服务中。 - 我们通过Spring MVC 控制器公开该功能,因为我们(当前)不需要像列出所有付款这样的标准模式。请记住,该示例的重点是对订购流程进行建模,而不是会计后端。支付资源被混合到订单的 URI 空间中:
/orders/{id}/payment
. - 我们使用超媒体元素来指示何时可以通过有条件地添加指向这些资源的链接来触发功能,以便客户可以使用这些元素的存在或不存在来决定提供哪些 UI 可供性来触发该功能。
以下是我认为这种方法的优点:
- 您只需手动编码从业务角度来看重要的部分。无需为遵循完善模式的 API 部分实现大量样板代码。
- 客户不需要关心接缝的确切位置。使用超媒体元素,API 对客户端来说就像一回事。服务器甚至可以将支付资源移动到不同的 URI 空间或不同的服务。
资源
推荐阅读
- python-3.x - 即使指向 3.8.8 exe,Visual Studio Code 也会报告 python 3.7.3 Interpreter
- sql - 仅当 3 列的值相同时才返回行
- regex - Notepad++ 正则表达式:如何防止 notepad++ 在搜索中嵌入不需要的字符?
- php - 是否可以在没有作曲家的情况下使用 php 电子表格?
- javascript - 从 useRef() 获取输入值时获取 useState 是滞后的
- php - PHP-FPM 与 PHP 中的不同语言环境
- python - 为什么在子级上使用打印时调用父类的__str__函数
- scala - 使用 Scala Spark 在不同组中计算复杂统计数据的困难
- java - 使用 spring boot / thymyleaf 重定向到 HTML 页面
- go - 是自定义命名类型的转换函数还是语言构造