简体   繁体   English

RestController 设计之争——Spring 启动 REST API

[英]RestController design struggle - Spring Boot REST API

I'm quite new into REST API development.我对 REST API 开发很陌生。 I have decided to create a Blog application using Spring Boot and I'm really struggling with the design and structure of my app.我决定使用 Spring Boot 创建一个博客应用程序,我真的在为我的应用程序的设计和结构而苦苦挣扎。

Right now my app consists of Post and Comment models and repositories.现在我的应用程序由 Post 和 Comment 模型和存储库组成。 For both models, I have created service classes (PostService and CommentService).对于这两种模型,我都创建了服务类(PostService 和 CommentService)。 In these classes, I have all the business logic (just simple CRUD right now).在这些类中,我拥有所有的业务逻辑(现在只是简单的 CRUD)。

Now I am scratching my head about the design of my @RestControler for Posts.现在我对我的@RestControler for Posts 的设计摸不着头脑。 In PostController I have exposed these actions:在 PostController 中,我公开了这些操作:

@PostMapping("/api/posts/create")
public Post create(@RequestBody Post post) { ... }

@GetMapping("/api/posts")
public List<Post> findAll() { ... }

@GetMapping("/api/posts/{id}")
public Post findById(@PathVariable("id") Long id) { ... }

@PutMapping("/api/posts/{id}")
public Post update(@RequestBody Post post) { ... }

@DeleteMapping("/api/posts/{id}")
public void delete(@PathVariable Long id) { ... }

Now I'm getting to my question.现在我要回答我的问题了。 I am wondering what is correct design of adding a Comment to the Post.我想知道在帖子中添加评论的正确设计是什么。

  1. Should I expose all CRUD method for Comment using CommentController class and use create method?我应该使用 CommentController class 公开所有评论的 CRUD 方法并使用 create 方法吗?
  2. Is it ok to add a new method addComment to PostController which will create a new Comment?可以向 PostController 添加新方法addComment来创建新评论吗?

In my head adding a Comment to the Post belongs to the Post, but I really don't know.在我的脑海中为帖子添加评论属于帖子,但我真的不知道。

Could some of give me some advice regarding this matter?有人能给我一些关于这个问题的建议吗?

Thanks a lot!非常感谢!

Bye, Tom再见,汤姆

If I were you, I'd consider REST Design Principles from the OpenAPI Specification and would follow resource -> sub-resource -> method||identifier pattern.如果我是你,我会考虑 OpenAPI规范中的 REST 设计原则,并遵循resource -> sub-resource -> method||identifier模式。 This would probably be the most KISS and clean design for the readability and understanding purposes.出于可读性和理解的目的,这可能是最 KISS 和最干净的设计。

@PostMapping("/api/posts/") //you don't need /create as a separate URI
public Post create(@RequestBody Post post) { ... }

@GetMapping("/api/posts") //This is OK.
public List<Post> findAll() { ... }

@GetMapping("/api/posts/{id}") //OK, however {id} should be optional, hence you can combine this and upper methods in one method.
public Post findById(@PathVariable("id") Long id) { ... }

@PutMapping("/api/posts/{id}") //OK.
public Post update(@RequestBody Post post) { ... }

@DeleteMapping("/api/posts/{id}") //OK.
public void delete(@PathVariable Long id) { ... }

and now, for the comments API design, I would have contain them under posts resource, and would have added these corresponding URIs:现在,对于 API 设计的评论,我会将它们包含在帖子资源下,并添加这些相应的 URI:

@GetMapping("/api/posts/{id}/comments/{commendId}") //commentId is optional
@PostMapping("/api/posts/{id}/comments/") //you don't need any {commendId} here, just post the payload

and etc. I hope you can come up with method signatures and other method mappings.等等。我希望你能想出方法签名和其他方法映射。

You can also see the RESTful naming conventions here您还可以在此处查看 RESTful 命名约定

To be honest I don't think that someone can give you the perfect answer here.老实说,我不认为有人可以在这里给你完美的答案。 It is often a personal decision.这通常是个人决定。 In common you can say the following about a REST API.通常,您可以对 REST API 说以下内容。

  • the path should only represent your data structure in the database.路径应该只代表您在数据库中的数据结构。 So for example /api/posts例如/api/posts

  • No verbs in your path.路径中没有动词。 What you want to do should be handled by the RequestType (GET, POST, PUT, PATCH, DELETE, etc.)想做的事情应该由 RequestType 处理(GET、POST、PUT、PATCH、DELETE 等)

Now to your case.现在谈谈你的情况。 I can really good understand why you are struggling.我真的很能理解你为什么挣扎。 I think here are two options:我认为这里有两个选择:

  1. PostsController帖子控制器

    You say a Comment is always a part of a Post and because of this you design your API like this.您说Comment始终是Post的一部分,因此您像这样设计您的 API。

     @PostMapping("/api/posts/{id}/comment") public Comment create(@PathVariable Long id), @RequestBody Comment comment) {... }
  2. CommentsController评论控制器

    You handle Comment as an own object and the Post is just a relation you add to it by attribute.您将Comment作为自己的 object 处理,而Post只是您通过属性添加到它的关系。

     @PostMapping("/api/comments") public Comment create(@RequestBody Comment comment) {... }

So it is always is it a Subset vs make own Object structure .所以它总是一个子集自己的 Object 结构 I think in this case here I would prefer option 2 because I think you want do more operations on this object.我认为在这种情况下,我更喜欢选项 2,因为我认为您想在此 object 上执行更多操作。

Also you can than design your API in the way that every Controller starts with the object that will be handled /api/OBJECT/xxx/yyy您也可以设计您的 API,使每个 Controller 都以 object 开头,将被处理/api/OBJECT/xxx/yyy

UPDATE更新

After reading the comment from @gulliva I think also a good way is to use this URL @PostMapping("/api/posts/{id}/comment") but put it in the CommentsController .在阅读了@gulliva 的评论后,我认为还有一个好方法是使用这个 URL @PostMapping("/api/posts/{id}/comment")但把它放在CommentsController中。 I think this is a good way.我认为这是一个好方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM