【问题标题】:How to implement a PUT correctly in Spring boot?如何在 Spring boot 中正确实现 PUT?
【发布时间】:2023-01-24 11:35:13
【问题描述】:

根据RFC 2616,尝试正确实施Put

“PUT 方法请求将封闭的实体存储在 提供的请求 URI。如果 Request-URI 指的是一个已经存在的 资源,封闭的实体应该被认为是一个修改过的 驻留在源服务器上的版本。如果请求 URI 不指向现有资源,并且该 URI 能够 被请求用户代理定义为新资源, 原始服务器可以使用该 URI 创建资源。”

简而言之,如果资源存在,则对其进行修改;如果不存在,则根据提供的id创建。 现在我有了这样的实现,RFC 2616 声明当创建元素时,它还必须返回位置 URI。 而我就这样离开了。

@PutMapping("/{id}")
public ResponseEntity<Item> update(
       @PathVariable("id") Long id,
       @RequestBody Item updatedItem) {

   Optional<Item> updated = service.update(id, updatedItem);

   return updated
           .map(value -> ResponseEntity.ok().body(value))
           .orElseGet(() -> {
               Item created = service.create(updatedItem);
               URI location = ServletUriComponentsBuilder.fromCurrentRequest()
                       .path("/{id}")
                       .buildAndExpand(created.getId())
                        .toUri();
                   return ResponseEntity.created(location).body(created);
            });
}

问题是Optional,所以为了良好的实践,应该在服务中使用和检查它。
另一个问题是实体的映射,它应该放在服务中,但如果 URI 位置介于两者之间,我不知道如何将它分开......

关于如何重构它的任何解决方案? 考虑到可选项在服务中使用,与映射相同,但 URI 进入控制器。

【问题讨论】:

    标签: java spring spring-boot rest jpa


    【解决方案1】:

    当使用Data Access Layer 实现REST Api 时,http protocol 规则并未严格适用。比方说,在Spring Boot 或任何其他框架的情况下,您执行的 URI 只会触发一个 Service 来访问您的数据库。

    事实上,您甚至可以使用 GETPOST 代替 PUT,它会起作用。 在这里,你的资源是一个数据库或你的记录(在你的数据库中),你的http调用不直接与你的数据库交互,但它是你的Service Layer到你的Spring Data Api

    简而言之,如果资源存在,则对其进行修改;如果它不存在 它是根据提供的id创建的

    在这种情况下,这是您的 save 方法,它将创建或更新您的记录。

    我会建议你这个重构:

    @PutMapping("/items")
    public ResponseEntity<Item> update(
           @PathVariable("id") Long id,
           @RequestBody Item itemToUpdate) {
    
       Optional<Item> updatedItem = service.update(id, itemToUpdate);
    
       return updatedItem
               .map(value -> ResponseEntity.ok().body(value))
               .orElseGet(() -> {
                   Item createdItem = service.create(itemToUpdate);
                   URI location = ServletUriComponentsBuilder.fromCurrentRequest()
                           .path("/{id}")
                           .buildAndExpand(createdItem.getId())
                            .toUri();
                    return ResponseEntity.created(location).body(createdItem);
            });
    }
    

    【讨论】:

      猜你喜欢
      • 2017-07-23
      • 2020-06-22
      • 1970-01-01
      • 2019-05-25
      • 1970-01-01
      • 2017-06-17
      • 2020-06-01
      • 1970-01-01
      相关资源
      最近更新 更多