java Spring REST URI存在性检查
让我们假设一个简单的基于Spring的RESTful API,其中包含一些嵌套资源
- A
User
是由每个人创建的用于访问API的根实体 - 每个
User
都可以创建Posts
,因此没有创建者Post
就不可能存在 - A
User
还可以注释现有的Posts
,因此AComment
属于APost
对于此API,我选择了以下RESTful路由:
/api/users
用于User
/api/users/{userId}/posts
代表Post
/api/users/{userId}/posts/{postId}/comments
用于{}
关于我的问题,我是否应该验证父资源是否存在?例如,对于请求GET /api/users/2/posts/3/comments/7
,我是否应该确保实体User(2)
和Post(3)
也存在?我是否还必须确保实体彼此相关,并且不使用任何现有的x任意资源
示例
@PostMapping("/api/users/{userId}/posts/{postId}/comments")
public void create(@PathVariable("userId") Long userId, @PathVariable("postId") Long postId, @RequestBody CommentPayload payload) {
// userService.existsByIdWithPostId(userId, postId); ???
commentService.createForPost(postId, payload);
}
要在数据库中创建注释,userId
是完全不相关的,只需要postId
。我应该仍然确保具有userId
X的用户存在,并且具有具有postId
Y的帖子,还是应该忽略它
如果是,我如何才能做到这一点?因为像Optional<Comment> findByUserIdAndPostIdAndId(...)
这样不断增长的JPA/存储库查询似乎不是一个解决方案。。。验证是否应该在几个查询中进行?包含所有父ID会使实际查询复杂化。此外,标识符必须通过所有层(服务层、安全层)传递,这使内部API变得复杂
# 1 楼答案
简短回答:是的,您必须检查父/根实体是否存在,是的,您需要定义实体之间的关系
答案很长:
没有用户就无法创建帖子,这一事实不必通过URL结构进行检查。URL仅用于澄清所请求的资源。检查必须直接在代码中完成。检查记录的存在不需要额外的工作和方法,这是因为实体之间的关系
当您使用
/users/{userId}/posts
API为用户添加帖子时,需要使用id=[userId]
将帖子添加到用户的帖子列表中,因此您调用相关的存储库方法来获取用户记录(如findById
),这本身就是使用id=[userId]
检查用户是否存在的行为。因为如果存储库返回null,您就知道用户不存在要设计好的、高效的、可理解的API,请遵循以下简单规则:
如果资源可以单独访问,那么它必须有一个基本URL作为/[entity],否则使用父子模式(就像您的帖子一样)
请注意,此规则不能一直有效,很多时候您需要自定义API并将其更改为更高效
因此,如果用户可以看到其他用户的帖子,那么您应该设计如下API:
/users
[对用户实体的请求]/posts
[请求发布实体]然后,对于针对特定用户帖子的请求,您应该使用
/users/{userId}/posts
来创建新帖子或阅读它们,对于针对特定帖子评论的请求,您应该使用/posts/{postId}/comments
据我所知,你的应用程序的设计不需要
/comments
,因为所有评论都与帖子相关,应该由相关帖子访问(如上所述)。如果评论可以单独访问(比如有一个页面列出所有评论,而不关心它们的相关帖子),那么您需要/comments
API来进行更多的澄清