休息资源分离

Rest resource separation

假设我们有一个 api enpoint 来处理超级英雄资源:

资源模型如下:

public class SuperHero
{
    public int Id { get; set; }

    public string Name { get; set; }

    public int Age { get; set; }
}

现在一个产品负责人说他们想介绍超级英雄团队。截至目前,给定的团队有一个名字和至少一个英雄。我可以看到两个选项可以继续。

1) 直截了当

引入新资源:

api/teams POST - creates a team

资源模型如下所示:

public class Team
{
    public int Id { get; set; }

    public string Name { get; set; }

    public IEnumerable<int> SuperHeroes { get; set; }
}

这样 api 用户将发送一个创建团队的请求。超级英雄列表必须指定且非空

2) 重新审视要求

什么是

team has a name and at least one hero attached

究竟是什么意思? 好吧,没有英雄,团队肯定还没有准备好拯救世界。但这是它存在的障碍吗?我们真的需要阻止用户创建一个没有英雄的团队吗?

让我们分别介绍一个团队和附属的超级英雄作为资源和子资源:

我的感觉是第二种方法有助于端点的简单性和责任分离。从性能的角度来看也可能更好,因为获取团队可能并不意味着用户需要关联的超级英雄列表。同时,它迫使 api 消费者使用两个调用而不是一个调用来创建一个准备就绪的团队。

这里应该问哪些额外的问题才能选择正确的选项?

创建团队

创建团队时,您可以允许消费者向其添加英雄

POST /api/teams HTTP/1.1
Host: example.org
Content-Type: application/json

{
  "name": "justice-league",
  "heroes": [
    "batman",
    "superman",
    "wonder-woman"
  ]
}

英雄附加到团队

要将 英雄 添加到 团队 ,您可以:

POST /api/teams/avengers/heroes HTTP/1.1
Host: example.org
Content-Type: application/json

{
  "value": [
    "captain-america",
    "iron-man"
  ]
}

在语义上将成员附加到集合的位置。

替换团队英雄

PUT /api/teams/avengers/heroes HTTP/1.1
Host: example.org
Content-Type: application/json

{
  "value": [
    "captain-america",
    "iron-man",
    "hulk",
    "thor"
  ]
}

你也可以考虑:

PUT /api/heroes/harley-quinn/team HTTP/1.1
Host: example.org
Content-Type: application/json

{
  "value": "suicide-squad"
}

在语义上替换 hero 所属的 team

团队

分离英雄

要从团队中删除英雄,您可以:

DELETE /api/teams/avengers/heroes/iron-man HTTP/1.1
Host: example.org

甚至:

DELETE /api/heroes/iron-man/team HTTP/1.1
Host: example.org

请记住,您的持久性模型不需要像您的 API 模型。