这是我在这个地方找不到相同问题的少数时刻之一,所以我试图描述我的问题并希望得到一些帮助和想法!
比方说...
我想为域模型设计一个 RESTful API,它可能具有如下所示的实体/资源:
class Product
{
String id;
String name;
Price price;
Set<Tag> tags;
}
class Price
{
String id;
String currency;
float amount;
}
class Tag
{
String id;
String name;
}
Run Code Online (Sandbox Code Playgroud)
API 可能如下所示:
GET /products
GET /products/<product-id>
PUT /prices/<price-id>?currency=EUR&amount=12.34
PATCH /products/<product-id>?name=updateOnlyName
Run Code Online (Sandbox Code Playgroud)
当涉及到更新参考文献时:
PATCH /products/<product-id>?price=<price-id>
PATCH /products/<product-id>?price=
Run Code Online (Sandbox Code Playgroud)
可以将产品的价格参考设置为另一个现有价格,或删除该参考。
但是如何将现有标签的新引用添加到产品中?
如果我想将该引用存储在关系数据库中,我需要一个用于该多对多关系的关系表“products_tags”,这为我们带来了一个明确的解决方案:
POST /product_tags [product: <product-id>, tag: <tag-id>]
Run Code Online (Sandbox Code Playgroud)
但是基于文档的 NoSQL 数据库(如 MongoDB)可以将其存储为每个产品的一对多关系,因此我不需要对必须创建的“新资源”进行建模来保存关系。
但
POST /products/<product-id>/tags/ [name: ...]
creates a new Tag (in a Product),
PUT /products/<product-id>/tags/<tag-id>?name=
creates a new Tag with <tag-id> or replaces an existing
Tag with the same id (in a Product),
PATCH /products/<product-id>?tags=<tag-id>
sets the Tag-list and doesn't add a new Tag, and
PATCH /products/<product-id>/tags/<tag-id>?name=...
sets a certain attribute of a Tag.
Run Code Online (Sandbox Code Playgroud)
所以我可能想说一些链接:
ATTACH /products/<product-id>?tags=<tag-id>
ATTACH /products/<product-id>/tags?tag=<tag-id>
Run Code Online (Sandbox Code Playgroud)
所以重点是:
我不想创建新资源,
我不想设置资源的属性,但是
我想将一个资源添加到另一个资源属性,这是一个集合。^^
由于一切都与资源有关,因此可以说:
我想将一个资源附加到另一个资源。
我的问题:哪种方法是正确的以及 URL 应该是什么样子?
您的 REST 是一个应用程序状态驱动程序,并非旨在反映您的实体关系。
因此,REST 中不存在“数据库中是否存在这种情况”的问题。也就是说,您有非常好的 URI。
你说的是ID。什么是标签?标签不是一个简单的字符串吗?为什么它有一个id?为什么它的 id 不是它的名称字符串?
为什么没有PUT /products/<product-id>/tags/tag_name=?
PUT 是幂等的,因此您基本上断言 所引用的产品的标签存在product-id。如果您多次发送此请求,则201 Created第一次和200 OK下一次都会收到。
如果中间有人删除了该标签,您的下一个放置请求将重新创建该标签。这是你想要的吗?
使用乐观并发控制,您每次都会传递文档的ETag a409 Conflict ,如果服务器上有较新的版本b并且差异a..b无法协调,则返回。对于标签,您只需使用 PUT 和 DELETE 动词;所以你不必区分/查看协调。
也就是说,我认为您没有考虑过您的交易边界。你要修改什么?资源?不,您正在修改product资源的值对象;它的标签。那么,根据您的资源模型,您应该使用PATCH. 你关心并发吗?好吧,那么关于 PATCH 你还有更多需要考虑的事情:
HTTP PATCH 的 RFC 是这样说的:
然而,对于 PATCH,所附实体包含一组指令,描述应如何修改当前驻留在源服务器上的资源以生成新版本。PATCH方法会影响Request-URI标识的资源,并且也可能对其他资源产生副作用;即,可以通过应用补丁来创建新资源或修改现有资源。
根据 [RFC2616] 第 9.1 节的定义,PATCH既不安全也不幂等。
我现在可能不会再把奇怪的想法塞进你的脑子里了。如果你想让我在这条路上继续走得更久一点,请评论;)。可以说,还有很多事情可以考虑。
| 归档时间: |
|
| 查看次数: |
2111 次 |
| 最近记录: |