【问题标题】:REST how to POST or PUT without full entity(@RequestBody)REST 如何在没有完整实体的情况下发布或放置(@RequestBody)
【发布时间】:2020-05-08 10:04:23
【问题描述】:

我有一个包含字段的实体“投票”:

private Integer id;
private LocalDate date;
private LocalTime time = LocalTime.now();
private User user;
private Restaurant restaurant;

我知道对于 REST POST,我应该使用这样的资源模式:

/votes

如果有更新:

/votes/{voteId}

大概我应该像这样在我的控制器中从前端接收全票实体:

@PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Vote> create(@RequestBody Vote vote)

但我不需要它来创建或更新该实体,我只需要这样的 restaurantId:

@PostMapping
public void create(@RequestParam int restaurantId) {
        voteService.create(SecurityUtil.getUserId(), restaurantId);
    }

那么,使用这样的资源模式是正确的选择,还是我错了?

对于 POST 创建:

/votes?restaurantId=10

PUT 更新:

/votes/{voteId}?restaurantId=10

【问题讨论】:

  • PUT /votes/{voteId}?restaurantId=? 在我看来,您更新了现有 VoterestaurantId 属性。至于其他事情,我不确定到底是什么问题。你能再澄清一点吗?
  • 我想创建和更新投票。例如,如果我使用@RequestBody 投票,那么我应该发送它的参数,例如:private Integer id;私人 LocalDate 日期;私人 LocalTime 时间 = LocalTime.now();私人用户用户;私人餐厅餐厅;但是当我创建那个实体时,我不认识他们中的任何一个。此参数在服务层上创建。
  • 还是不明白。您的评论与原始问题有什么关系?

标签: java rest post uri put


【解决方案1】:

你应该把它改成:

@PostMapping
public void create(@RequestParam("restaurantId") int restaurantId) {
    voteService.create(SecurityUtil.getUserId(), restaurantId);
}

您应该在@RequestParam("param_name") 中提及参数名称

【讨论】:

  • 谢谢,但我的问题不是这个。
  • 路径参数URI模板为/votes/{restaurantId},与/votes/{voteId}相同。
【解决方案2】:

为什么不使用路径参数?将get参数传递给POST和PUT有点奇怪。

@PostMapping("/{restaurantId}")
public void createPost(@NonNull @PathVariable(value = "restaurantId") String restaurantId) {
    voteService.create(SecurityUtil.getUserId(), restaurantId);
}

@PutMapping("/{restaurantId}")
public void createPut(@NonNull @PathVariable(value = "restaurantId") String restaurantId) {
    voteService.create(SecurityUtil.getUserId(), restaurantId);
}

【讨论】:

  • 我正在创建投票,而不是餐厅。我以为我必须使用更新示例投票/{voteId}?restaurantId=10,而我不能像这样使用投票/{voteId}/{restaurantId}
  • 您可以将两者混合使用。 @PathVariable(value = "restaurantId") 和 @RequestBody 投票 它将使 API 更清洁 /votes//
【解决方案3】:

那么,使用这样的资源模式是正确的选择,还是我错了?

“视情况而定”。

URI 的拼写与机器无关; /0d905ca3-c848-4bc5-bc4a-658fbec88ab5 是一个非常好的使用路径。人类可读的拼写只是对人类的一种方便——像/votes 这样的“RESTful”拼写与使用 UUID 相比,不再是 REST,但是当操作员翻阅日志试图识别流量模式时,他们可能会更开心第二个选择。

POST,作为方法标记,很好。请参阅It's Okay to Use POST(菲尔丁,2009 年)。

PUT,然而,听起来不像你想要的。从语义上讲,PUT 的意思是“用当前消息的有效负载替换资源的当前表示”。这是一种远程创作 方法,当与GET 搭配使用时,会为您提供一个文档存储:

PUT 是您在万维网上用来编辑主页的方法。

GET /home-page

(make changes locally)

PUT /home-page

该 PUT 请求的正文是主页的预期新版本。

在你的情况下:

PUT /votes/{voteId}?restaurantId=10

应该有一个看起来像你会读到的负载

GET /votes/{voteId}?restaurantId=10

它需要是资源的完整表示。

并不意味着它需要是entity的完整表示;资源是文档的概括; 查看到您的实体数据。远程创作发送视图的新表示,并且对实体进行匹配更改是服务器的工作。见Jim Webber 2011

如果您不想以这种方式进行更新,那很好 -- 但是您不应该使用 PUT,因为这违背了与所有其他资源(您应该使用 POST)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多