所以我的问题是,为什么幂等行为与HTTP方法相关联?我不是在寻找什么是幂等行为的解释,而是我们是如何将这些HTTP方法标记的?
这样,交换消息的通用、领域无关的参与者可以做出有用的贡献。
RFC 7231在其
idempotent的定义中指出了一个具体的例子。
幂等方法之所以与众不同,是因为如果客户端在能够读取服务器响应之前发生通信故障,则可以自动重复请求。例如,如果客户端发送PUT请求并且在接收到任何响应之前关闭了底层连接,则客户端可以建立新连接并重试幂等请求。它知道重复请求将具有相同的预期效果,即使原始请求成功,响应也可能不同。
客户端或中间件不需要了解您的定制API或其底层实现就可以这样操作。所有必要的信息都在规范中(RFC 7231对
PUT和
idempotent的定义),以及服务器宣布支持PUT的资源中。
请注意,PUT需要幂等请求处理,但对于POST并非禁止。具有幂等POST请求处理程序甚至具有
safe的处理程序并不是错误的。但是,仅具有元数据和HTTP规范的
通用组件将不知道或发现POST请求处理程序是否幂等。
我不明白这会影响Java实现或为RestFul服务所做的后端实现吗?
没有什么魔法;使用PUT并不会自动更改服务的底层实现;技术上讲,它甚至不会限制底层实现。它所做的是清楚地记录责任所在。
这类似于Fielding 2002年的观察关于GET是安全的
HTTP不要求GET的结果必须是安全的。它要求操作的语义是安全的,因此如果由此导致任何损失(顺便说一句,钱被认为是财产),那么这是实现的错误,而不是接口或接口使用者的错误。
重要的一点要认识到,就是在HTTP中,并不存在“资源层次结构”。例如,
/addresses
和
/addresses/1
之间并没有任何关系——对其中一个的消息不会影响缓存另一个的表示。认为
/addresses
是一个“集合”,而
/addresses/1
是“/addresses集合中的项”是实现细节,仅供源服务器使用。
(过去的情况是,POST的语义将指向下级资源,例如请参见
RFC 1945;但即使那时下级标识符的拼写也不受约束。)
我的意思是PUT /employee是否可行或者必须是PUT/employee/<employee-id>?
PUT /employee
的语义是“用我提供的表示替换/employee的当前表示”。如果
/employee
是一个集合的表示,则通过PUT传递集合的新表示来修改该集合是完全可以的。
GET /collection
200 OK
{/collection/1, collection/2}
PUT /collection
{/collection/1, /collection/2, /collection/3}
200 OK
GET /collection
200 OK
{/collection/1, /collection/2, /collection/3}
PUT /collection
{/collection/4}
200 OK
GET /collection
200 OK
{/collection/4}
如果这不是你想要的;如果你想要“追加”到集合中,而不是替换整个表示,则对于集合应用
PUT
具有错误的语义。你可以把项表示放到项资源中,或者在集合上使用其他方法(如POST或PATCH)。
GET /collection
200 OK
{/collection/1, collection/2}
PUT /collection/3
200 OK
GET /collection
200 OK
{/collection/1, /collection/2, /collection/3}
PATCH /collection
{ op: add, path: /4, ... }
200 OK
GET /collection
200 OK
{/collection/1, /collection/2, /collection/3, /collection/4 }
PUT
的语义是应该用请求的有效负载提供的内容替换调用端点的当前表示。如果之前没有可用的,则 PUT 可以创建一个,这会导致实际资源的创建。通过让实现者定义接收到的有效负载将执行什么操作,POST
请求的语义甚至更加模糊。因此,“PUT
更新,POST
创建”在一般情况下并不正确,只是对这些操作的过度简化视图。 - Roman Vottner