扩展单一 ID REST 端点以支持多个 ID

Extend Single ID REST endpoint to support multiple IDs

我有一个 ID REST API,我需要对其进行扩展以支持多个(最多 10Ks)ID。基本上 运行 更新所有相关 ID,而不是在网络中发送 10Ks 请求。

当前端点:

@POST
@Path("{id}/update")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public ResponseVO updateBlockReason(@PathParam("id") int id, List<RequestVo> requestVo) {

一个选项suggested is comma-delimited values as stackexchange's answers-by-ids

Usage of /answers/{ids} GET

{ids} can contain up to 100 semicolon delimited ids. To find ids programmatically look for answer_id on answer objects.

similar answers

是这样的

http://our.api.com/Product/<id1>,<id2> :as James suggested can be an option since what comes after the Product tag is a parameter

但这对我来说似乎很尴尬,RequestVo 对所有 ID 都是一样的( 目前 很好,但以后添加这样的支持会更难)

看来我需要更改 Path 变量以将其添加到 RequestVO

这意味着 ID 将是一个 JSON 键,例如

[{
"id" : "1",
"name": "myAttribute"
"toggle": true
},
{
"id" : "2",
"name": "mySecondAttribute"
"toggle": false
}
]

这是正确的方法还是我遗漏了什么?

提前感谢您的任何 comments\answers

当前请求语音

@Data
@AllArgsConstructor
@NoArgsConstructor
public class RequestVO {

 private String name;
 private boolean toggle;
 // will add now private int id
 }

我还担心如果我想(要求之一)使用相同的请求(如 name=doA,toggle=true)更新 10Ks ID,我将不得不复制请求 VO 而不是单独发送 ID

我发现路径 product/{id}/update 有问题,因为您可以通过将 @Put-request 映射到 product/{id} 本身来实现类似的行为。 Request-mapping 已经明确了 READ、WRITE 的区别。 此外,是否在 restful url 中使用动词本身就是一个话题。

假设您可以使用多个端点,这可能看起来像 /products/{id}

因为您想 batch/bulk 更新产品,您现在可以将 @Put-requests 映射到 /products,并在 RequestBody 中列出更新的产品。请记住,这会使响应变得有些复杂,因为您可能需要 return Http-207 来回答列表中每个元素更新的正确状态。

I want 1 logical endpoint for update

您可以为此使用逻辑服务方法,但实际上没有端点。 您已经在批量更新路径中提到了 /{id} 的问题。 如果你真的、真的需要,我会从 /products/{id} 中删除 @Put-mapping 并重定向到 /products,其中更新内容将是单个元素列表,或者更复杂一点,由 mediaType 区分(再次表示两个端点, 一个 url)。

编辑: 我只是碰巧明白了VO-issue。您不是在更新产品,而是在更新产品的一部分(名称 RequestVO 误导了我)。 这对我来说闻起来像 @Patch-mapping,其中产品的某些部分得到更新。 所以我仍然会使用 /products 但使用 @Patch-mapping.

When a client needs to replace an existing Resource entirely, they can use PUT. When they’re doing a partial update, they can use HTTP PATCH.

这会带来另一个问题,仅当 id 未知时才使用 @Post(通常在创建某些内容并分配 id 之前,更新使用 @Put 并重新使用分配的 id) 使用 post 在技术上是可行的,但由于 idempotece 不可取。

最好的方法是将 id 保留在您的 RequestVO DTO 本身中,而不是像您已经建议的那样保留在 URL 中,因为 URL 中即使有 100 个 ID 也可以您的 URL 非常大,您正在谈论 10K 个 ID。

而且在未来,单个 id 的位长度可能会增加,或者稍后您可能需要更新 50k 甚至 100k 个对象。

根据maximum length of a URL,URL长度没有一般规范,但是特别长的URL通常是错误的,URLs超过 2,000 个字符无法在最流行的网络浏览器中使用

所以我认为你的第二种方法在这里是最好的并且对未来的目的也有好处。

您可能还想使用 PUT 请求,因为它对更新请求更有意义。所以你的代码会变成这样:

@PUT
@Path("/update")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public ResponseVO updateBlockReason(List<RequestVo> requestVo) {

为什么不将请求正文中的 ID 列表作为 JSON 数组传递?代码将是:

@POST
@Path("/update/ids")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public ResponseVO updateBlockReason(@RequestBody List<Integer> ids, List<RequestVo> requestVo) {
...
}