根据我的理解,repository
确实很糟糕,service
完成了所有业务逻辑,controller
收到了请求。所以当一个请求进来时,顺序通常是controller
- > service
- > repository
然后将数据传回客户端。
我现在面临的问题是我的大部分apis都涉及多个存储库。例如,获取用户的电子邮件列表的请求。我需要首先解码加密的字符串(在UserService
中完成)。如果成功,请使用从字符串解密的id
来搜索电子邮件(在EmailService
中完成)。在这种情况下,请求首先路由到EmailController
然后调用EmailService
。我应该做所有的解密并在UserRepository
调用EmailService
或者让UserService
处理所有这些吗?此外,如果我想返回ResponseEntity
,EmailService
应该返回电子邮件或ResponseEntity
列表,还是有EmailController
来构建ResponseEntity
?
确实有不同的方法,但无论如何我认为真的要遵循两条规则。
第一条规则:继续进行的一致性。 如果根据某些条件决定一种或两种方式,最重要的是对任何应用程序用例一致地应用它。
如果您创建不需要的变体,代码读取和可维护性将成为一场噩梦。
第二条规则:设计可重复使用并设计功能设计,而不是每个实体/资源的“驴”一对一层设计,因为每种实体/资源并不是独立存在的。
在这里你可以参考这个用例:
获取用户的电子邮件列表的请求
这是一种处理方式。 我不是说这是“道路”。这只是我的方式。
1)在其余控制器和服务层之间进行一对一映射可以简化您的设计:
EmailController
-> EmailService
UserController
-> UserService
但请注意,它有一个警告。
如果在不同的服务类中重复类似的逻辑,则可能意味着应引入多个休息控制器使用的可重用服务。
在这种情况下,您可以拥有控制器,Controller和Service层之间的一对一映射,即:EmailController
,它与EmailService
以及EmailController
使用的其他多种常用服务进行通信。
从您的上下文中,这是一个应该引入公共服务的具体示例。 假设这个任务:
“我需要首先解码加密的字符串”
在由不同控制器处理的多个用例中执行,例如EmailController
和UserController
,在专用服务中提取处理要好得多,而不是在EmailService
和UserService
中复制它。
所以EmailController
会有这些依赖:
- EmailController -> EmailService -> EncryptingService
UserController
也是如此:
- UserController -> UserService -> EncryptingService
2)服务的设计并不总是与存储库层一对一映射。
存储库确实设计为可由任何需要它们完成任务的服务重用。
所以当然UserService
必然会与UserRepository
沟通。
但是,如果UserService
还需要检索一些与User
实体没有直接关联的电子邮件实体作为实体关系,UserService
必须与EmailRepository
进行交互才能完成此任务。
因此,根据您的需求,您可以在UserService
中将一对一映射作为依赖关系:
- UserService -> UserRepository
或更多依赖项:
- UserService -> UserRepository -> EmailRepository
3)关于这最后一个问题
另外,如果我想返回ResponseEntity,EmailService应该返回电子邮件列表还是ResponseEntity,还是让EmailController构建ResponseEntity?
不要混淆责任,否则图层会失去价值。
服务执行/返回功能性事物,必须设计为以这种方式工作。
ResponseEntity
包装必须在处理HTTP响应的层中执行,因此仅在Rest控制器中执行。
正如你所说的那样,Services
包含业务逻辑,所以他们不应该关心解密,IMO应该隐藏在Repository
实现中,这是因为业务逻辑与CRUD逻辑混合导致你的设计问题。
Repositories
可以返回分页结果,这是一个可以在Service
和Repository
层中的接口。然后在Controller
中将分页结果转换为ResponseEntity
,以响应请求。不要让ResponseEntity
冒险在Controller
之外。