Spring 应用程序中的应用程序层
Posted
技术标签:
【中文标题】Spring 应用程序中的应用程序层【英文标题】:Application layers in Spring application 【发布时间】:2020-09-05 22:40:36 【问题描述】:我正在参与实现 REST API 应用程序,我们坚持将 Spring Boot 作为一个框架。
我们刚刚开始实施该系统,但即使在项目的这个阶段,它也开始觉得应用程序设计有问题。
我们的应用程序有 3 层:
-
控制器层 - 在这一层我们(其中一些是由 spring 自动完成的):
接收客户的请求
将其转换为 dto 对象并验证此 dto
将 dto 和登录用户信息转换为某个对象或 DB 实体 (!) 以调用服务层。
将结果作为从某个对象或 DB 实体 (!) 转换而来的 dto 对象返回给客户端
服务级别 - 在这一层我们:
执行所有业务逻辑,例如外部服务调用
通过 Repository 层调用更改/创建/删除实体
将业务逻辑的结果返回为某个对象或数据库实体对象 (!)
存储库级别 - 在此级别,我们指定将数据库实体返回到服务级别的逻辑。
查询我们的数据库以获取实体并将其原样返回给服务层
我对上述应用程序设计的担忧:
-
所有应用层都知道数据库实体
在实体具有延迟获取代理的情况下,至少控制会话、事务和所有内容应该是相当困难的。
不确定,如果需要,但我们可以引入某种类型的 ServiceDto,因此合同如下:
控制器将经过验证的客户端 dto 转换为 ServiceDto,并将其作为输入调用服务层
Service 使用 ServiceDto 执行业务逻辑,并将业务操作和 ServiceDto 的结果转换为 DB 实体,并以此作为输入调用 Repository 层
存储库接受 db 实体并像以前一样返回 DB 实体
这里唯一可能非常苛刻的是所有这些 DTO 之间的映射
查看某些类型的指南、最佳实践或项目将非常有帮助,这些指南、最佳实践或项目展示了如何在此类应用程序中组织应用程序层之间的通信。
非常感谢!
以下补充
一些代码sn-ps:
class OrderController
@Autowired
private OrderService orderService;
@Autowired
private UserService userService;
public OrderResultDto createOrder(OrderRequestDto dto)
return orderService.makeOrderRequest(userService.getAuthenticatedUser(), dto)
class OrderService
@Autowired
private OrderRepository orderRepo;
public makeOrderRequest(User user, OrderRequestDto dto)
// do some complex business logic
将我们发送到前端的 dto 作为 JSON 分配给 Service 合约似乎不太好……此外,如果我们需要从另一个方法调用此服务,该方法也会绑定到此 dto,这不好。
【问题讨论】:
【参考方案1】:控制器层是面向 Web 的层。它的工作是接受输入,一般来说,将其转换为服务层使用的格式并调用服务。正如您所说,Spring 开箱即用地进行了这种转换,E.G.根据控制器方法参数的类型将 JSON 建模为 DTO。
将 dto 和登录的用户信息转换为某个对象或 db 实体 (!) 以调用服务层。 将结果作为从某个对象或数据库实体(!)转换而来的 dto 对象返回给客户端
这是很差的抽象分离。例如,您将如何管理交易?将“实时”JPA 实体暴露给 Web 层也是危险的。此外,Web 只是您可能希望与服务交互的一种方式。如果您想使用 E.G. 将服务作为计划作业运行会发生什么?石英?从 JPA 实体到 DTO 的转换应该在服务层完成,事务管理也应该这样做。
将业务逻辑的结果作为某个对象或数据库实体对象返回(!) 同样,该服务应该将实体映射到 DTO。应该没有对象从存储库泄漏到服务之外。
控制器可以与 DTO 进行自动对话,这可以是服务的输入/输出。例如。控制器接受 PersonDTO,Spring 使用 jsr-303 bean 验证执行到 DTO 的映射,使用 PersonDTO 调用服务,将 DTO 映射到实体,调用存储库层,将返回的实体映射到 DTO,然后返回 DTO .
从您的问题来看,您的想法似乎非常正确。我唯一要问的是是否需要控制器 DTO 和服务 DTO。使用相同的类就可以了。
【讨论】:
罗伯特,非常感谢您的回复!我添加了一些代码 sn-ps 以突出显示我在这里看到的问题。userService.getAuthenticatedUser()
应该返回 UserDTO
,而不是 User
,OrderService.makeOrderRequest
应该接受 UserDTO
,而不是 User
。我确实认为将 DTO 从请求发送到服务很好,为什么不呢?这是一个 DTO,这就是他们的目的。以上是关于Spring 应用程序中的应用程序层的主要内容,如果未能解决你的问题,请参考以下文章
使用 Spring Data JPA 的服务层中的 Crud 方法