通过REST更新资源(PUT / POST)

时间:2017-07-20 21:58:07

标签: rest http post spring-boot put

通过REST更新资源时,是否应该在正文中包含要更新的值或整个对象(要更新的当前值和值)?

如果User对象看起来像这样

User (id, name, age, sex)  

如果我的请求如下所示,我想更新仅限他的姓名和年龄

PUT /users/1

{"name":"john","age":18}

或者像这样:

PUT /users/1

{"name":"john","age":18, "sex":"m"}

在服务器端看起来应该是什么样的?

@RequestMapping(value = "/{userId}", method = PUT, consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<String> updateUser(@PathVariable final int userId, @RequestBody User u){
    //fetch user by ID 
    user.setName(u.getName())
    user.setAge(u.getAge())
    user.setSex(u.getSex()) //this will be empty?

    return new ResponseEntity<String>(gson.toJson(user), HttpStatus.OK);
}

或者我可以找出请求体中没有包含哪些变量并执行类似这样的操作

if(u.getName()!=null){
     user.setName(u.getName())
}
if(u.getAge()!=null){
     user.setAge(u.getAge())
}
if(u.getSex()!=null){
     user.setSex(u.getSex())
}

是否有正确/错误的方法来实现这一目标,还是只做最简单的事情?

1 个答案:

答案 0 :(得分:3)

PUT请求必须是幂等的,并且应该作为其有效负载提供它正在替换的实体的完整表示。 (https://tools.ietf.org/html/rfc7231#section-4.3.4

  

PUT方法请求目标资源的状态      用表示定义的状态创建或替换      包含在请求消息有效负载中。

部分JSON对象PUT请求为PATCH Content-Type: application/merge-patch+jsonhttps://tools.ietf.org/html/rfc7396

要考虑的事情。您可能有多个客户端同时更新实体,使用PUT可能最终覆盖其他客户端所做的更改。

在这种情况下,您可能需要设置pre-condition以检查对象是否在请求客户端获取实体,进行更改并提交PUT / PATCH请求之间更新。例如,前置条件可以是最后更新的时间戳,散列(Etag)或版本号;或者您可以使用“最后写入获胜”方法,这种方法在最终一致的系统中很常见。这一切都取决于您的系统和情况。

在服务器端,如果您支持部分更新,那么就像您在示例中提供的那样,您将识别请求中包含的属性集,并仅设置提供的特定属性。