在 REST 中,我们如何处理返回资源集合的多种方式?

Posted

技术标签:

【中文标题】在 REST 中,我们如何处理返回资源集合的多种方式?【英文标题】:In REST, how do we deal with multiple ways to return a resource collection? 【发布时间】:2022-01-01 03:35:02 【问题描述】:

我们有一个名为messages 的资源。我们希望有两种列出其收藏的方式。一种是只返回强制性且已被查看的消息;另一个,所有的消息。每个都有另一个不需要的字段,因此我们不想返回它们。例如

一个响应应该是这样的:

public class MessageListingResponse 
    private Long messageId;
    private String title;
    private String imageUrl;
    private LocalDateTime createdAt;
    private Boolean isViewed;

另外一个是这样的:

public class MandatoryMessageListingResponse 
    private Long messageId;
    private String title;
    private String imageUrl;
    private LocalDateTime createdAt;
    private String description;

我找不到这种情况的通用规则。那么,REST 后面是哪个选项呢?

/messages/mandatories /messages?view=mandatories /messages?mandatoryListing=true /mandatory-messages

【问题讨论】:

【参考方案1】:

我找不到这种情况的通用规则。那么,REST 之后是哪个选项?

REST 不关心您为资源标识符使用的拼写约定。

特别是,机器不关心标识符的拼写是否与资源的语义匹配(提醒:URL 缩短器work

/messages/mandatories
/messages?view=mandatories
/messages?mandatoryListing=true
/mandatory-messages

这些都很好

有一些纯粹的机械差异;使用 html 表单作为 URI 模板时,带有键值对的查询很方便。当使用点段和相对分辨率来描述同一层次结构中的其他标识符时,路径层次结构很方便。

标识符作为文本显示在许多地方 - 我们将 URI 粘贴到消息中,它们在浏览器历史记录中被跟踪,它们出现在您的访问日志中。所以我们有很多不同的人在不同的上下文中查看标识符。尝试选择对所有人都可以容忍的拼写;但尽你所能优化最重要的体验。

【讨论】:

你是对的,但不建议将第一个和最后一个作为最佳 REST 实践。当然,最后你可以随心所欲。【参考方案2】:

这是基于意见的临界点,但我会这样做。 最 RESTful 的方式是使用查询参数,例如 /messages?view=mandatories。这个问题(可能不是您的用例的问题,您需要考虑一下)是响应模型需要与/messages 相同,这意味着您需要有一个模型跟随(合并MessageListingResponseMandatoryMessageListingResponse):

public class MessageListingResponse 
    private Long messageId;
    private String title;
    private String imageUrl;
    private LocalDateTime createdAt;
    private Boolean isViewed;
    private String description;

如果不希望这样做(我也会避免这样做),那么我会采用不那么 RESTful 的方法,例如 /messages/mandatories。它不是那么 RESTful,因为messages 是您的资源,并且以下路径信息应该是一个 ID,以便您只能收到一条消息。另一种可能性是/messages/view:mandatories 之类的东西,我理解这对大多数人来说可能看起来很奇怪。无论您使用哪种结构,通过这种方法,您都可以为此拥有一个特定的模型,因此您可以为每个端点拥有非常特定的模型,从而避免在某些情况下为 null 而在另一种情况下不是 null 的属性。

【讨论】:

如果消息和强制消息是两个独立的类,那么它们可能需要 /messages 和 /mandatories【参考方案3】:

首先,如果是消息,那么/messages应该在那里,因为资源是消息。

之后,messages/mandatories 表示有一个强制列表,它是消息的子集。您是否打算使用 put、post 或 patch 添加或更新强制消息,messages/mandatories 是正确的方法。

但如果它只是强制消息的过滤器,最好的方法是使用GET,如下所示:/messages?status=mandatories

status 是指示消息是否为必填项的字段

【讨论】:

我最初也是这么想的,但是看了REST文档后发现所有子集示例都使用了一个路径变量id,表示子集是一个消息的变量,但那是并非如此,因为“强制”只是消息的不同表示,因此不是单个消息的子集。来源:restfulapi.net/resource-naming 在“1.2. 集合和子集合资源”段落。

以上是关于在 REST 中,我们如何处理返回资源集合的多种方式?的主要内容,如果未能解决你的问题,请参考以下文章

当相关资源属于不同的微服务时,如何处理 REST API 路径?

如何处理 REST api 中的关系

我如何处理rest-client 500错误响应并不断在我的循环中抓取?

使用 KissXML 处理 wcf Rest Web 服务 - 我应该如何处理命名空间问题

收集结果的 RESTful API 中应该如何处理异常?

微服务架构中的分布式事务,如何处理超时和失败的提交