【问题标题】:rest - relation context休息 - 关系上下文
【发布时间】:2014-10-17 16:58:48
【问题描述】:

假设我有两个收藏资源:

/persons
/organizations

GET/persons/id/ 返回一个特定的人。同样,GET/organizations/id 返回特定组织。

一个人可以是一个或多个组织的成员。在这种关系上下文中,我们拥有诸如人员在组织中的角色、人员加入组织的日期等数据......

哪些设计最有意义?

  1. 会员资源/memberships/idGET 将关系上下文的数据返回到该资源(以及指向个人和组织的链接)。

  2. /persons/id/organizations/id/organizations/id/persons/idGET 到两者之一返回关系上下文,GET 到另一个重定向(http 状态代码 303)到另一个。

  3. 还有别的吗?

【问题讨论】:

    标签: rest relationship restful-architecture


    【解决方案1】:

    另一种选择是将关系直接嵌入到资源本身中。这使得客户端在使用服务时更容易跟踪资源之间的关系。例如,这是一个假设的person,通过两个membership 资源和其中一个membership 资源与两个organization 资源建立关系:

    "person890": {
        "firstName": "Jane",
        "lastName": "Smith",
        "links": [{
            "rel": "membership",
            "href": "memberships/123"
        }, {
            "link": "membership",
            "href": "memberships/456"
        }]
    }
    
    "membership123": {
        "role": "chairwoman",
        "date: "12/23/2013",
        "term": "3 years",
        "links": [{
            "rel": "person",
            "href": "persons/890",
        }, {
            "rel": "organization",
            "href": "organizations/7575"
        }]
    }
    

    这里的基本原则是HATEOAS——“超媒体作为应用程序状态的引擎”——它使对您的数据了解最少的客户仍然可以与您的 API 交互。

    【讨论】:

    • 我的问题并不是关于仇恨。 /membership 上面有 /organizations/id/persons/id/persons/id/organizations/id,其中一个引用(代码 303)到另一个有什么好处?
    【解决方案2】:

    如果您的问题仅限于结构,我认为没有客观正确的答案。原则上,你应该坚持在你的 API 中保持一致性。如果没有类似的东西已经实现,我认为这取决于你的目标是什么。如果您想让 API 尽可能简单,选项 1 似乎就足够了。

    通常,我会尝试使 API 对客户端尽可能灵活,这样他们就可以通过尽可能少的请求获得所需的准确信息,而不会打扰我实现自定义端点。假设组织可以很大并且有很多成员,而一个人不能成为很多组织的成员,这就是我要做的:

    -我认为没有理由在两边都有两级 URI,所以/persons/id 可以是个人的规范 URI,/persons 可以是所有组织中所有人的分页集合。 organizations/id 可以是组织的 URI,/organizations/id/persons 可以为您提供组织内所有人员的集合,以及该人员的替代 URI。

    • 我认为不需要 303,但这是一个选择问题。如果需要,您可以将 /organizations/id/persons/id 重定向到 /persons/id

    • 保留/memberships/id,如您在 1 中所述。

    • 假设您正在使用某种形式的 HATEOAS,所有资源都应该有指向相关资源的链接。

    我经常实施的其他一些有助于提高可用性和灵活性的想法是:

    • 所有资源都应该有一个指向规范 URI 的自链接。

    • 您应该能够查询集合。就像/memberships?person_id=X 应该生成一个集合的子集,列出该人的所有成员资格实例。

    • 您应该能够扩展资源表示以包含嵌入式表示。它可能是明确的,比如/persons/id?expand=memberships 应该生成一个人的表示,其中包含一个包含所有成员的嵌入式列表的字段,或者你可以使用我称之为缩放协议的东西。您有一个参数,该参数指示应嵌入多少级关系,并随着您在关系中的进展而减少它。因此,/persons/id?zoom=1 将嵌入会员,/persons/id?zoom=2 将嵌入会员,并将 zoom=1 应用于会员表示本身,嵌入组织。

    【讨论】:

    • 谢谢,这让我大开眼界。不过还有一个问题。在您的第一个项目符号中,/organizations/id/persons/id 不应该重定向到/memberships/id 吗?或者在从组织到个人时是否有特定的理由绕过成员资格?
    • 嗯...我希望/organizations/id/persons/id/persons/id 的别名,而不是会员资格。如果这是你的意图,你可以有/organizations/id/memberships/id
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-22
    • 2011-03-10
    • 2017-02-09
    • 2013-06-13
    • 2015-11-18
    相关资源
    最近更新 更多