Api 包含或不包含资源子级的RESTful方式?
假设我有一个Api 包含或不包含资源子级的RESTful方式?,api,rest,nested,Api,Rest,Nested,假设我有一个team对象,它有一个name属性、一个city属性和一个players属性,其中players属性是一个可能有许多玩家的数组。这在一个SQL数据库中表示,该数据库包含一个团队表和一个玩家表,其中每个玩家都有一个名称和一个团队id 基于这个简单的数据结构构建一个RESTful api,我怀疑在点击/teams/:id时是否有明确的规则,返回对象是否应该/可能包括一个玩家列表 我有一个观点,需要展示一支球队,以及球员的名字,所以: 1:是否应该/teams/:id将场景后面的两个表连接
team
对象,它有一个name
属性、一个city
属性和一个players
属性,其中players
属性是一个可能有许多玩家的数组。这在一个SQL数据库中表示,该数据库包含一个团队
表和一个玩家
表,其中每个玩家都有一个名称
和一个团队id
基于这个简单的数据结构构建一个RESTful api,我怀疑在点击/teams/:id
时是否有明确的规则,返回对象是否应该/可能包括一个玩家列表
我有一个观点,需要展示一支球队,以及球员的名字,所以:
1:是否应该/teams/:id
将场景后面的两个表连接起来,并返回完整的team
对象,以及一个players属性,即名称和id的数组
2:是否应该将/teams/:id
连接到场景后面的两个表中,并返回team
对象,该对象带有一个players属性,即一个仅包含id的数组,然后必须逐个查询到/players/:id
3:应该打两个电话吗,一个打给/teams/:id
,一个打给/teams/:id/players
4:是否应该像这样使用查询字符串/teams/:id?fields=姓名、城市、球员
如果选择2个或3个,那么如何处理这样的情况,即一个团队也可能有多个城市,从而在DB中生成另一个城市表以保持其正常化?然后是否应在/teams/:id/cities
处创建新端点
创建RESTful API时,是数据库中的规范化数据结构决定了API中的端点吗?通常使用RESTful API时,最好由用例决定API的端点,而不一定是数据结构
如果您有时只需要团队,有时只需要团队中的玩家,有时同时需要这两个,我会有3个不同的调用,可能类似于/teams/:id
,/players/:teamid
和玩家团队/:teamid
(或类似的调用)
您希望以这种方式执行此操作的原因是,它将需要为任何给定页面发出的HTTP请求数量降至最低。在所有典型的性能问题中,HTTP请求数量过多通常是最常见的性能问题之一,也是最容易避免的问题之一
话虽如此,您也不想疯狂到创建过度膨胀的API。仔细考虑典型的用例,并对其进行调用。不要只是为了实现你能想到的所有可能的组合。记住。我建议如下:
GET /teams
{
"id" : 12,
"name" : "MyTeam"
"players" :
{
"self" : "http://my.server/players?teamName=MyTeam"
},
"city" :
{
"self" : "http://my.server/cities/MyCity"
}
}
GET /cities
GET /cities/{cityId}
GET /players
GET /players/{playerId}
然后,您可以使用URI调用以获取所需的任何其他相关资源。如果希望灵活地嵌入值,可以使用?展开,例如:
GET /teams?expand=players
{
"id" : 12,
"name" : "MyTeam"
"players" :
{
"self" : "http://my.server/players?teamName=MyTeam",
[
{
"name" : "Mary",
"number" : "12"
},
{
"name" : "Sally",
"number" : "15"
}
]
},
"city" :
{
"self" : "http://my.server/cities/MyCity"
}
}
非常感谢你的回答。/player teams/:teamid方法很有趣,以前从未见过。与/teams/:id?字段=姓名、城市、球员?清晰度相比,这种方法有什么优势。我更喜欢使用更干净、查询字符串更少的方法,因为我认为它们更清晰。如果你只看路线player teams/:team id
,你就知道你能通过什么和不能通过什么,并且对你能得到什么有一个合理的猜测。使用查询字符串,您并不总是知道a)可以传递哪些字段,b)这些字段的有效值是什么。如果您需要那么多端点,您是否会以许多端点结束,例如玩家城市
,团队城市
,城市团队玩家
?非常可能。如果你有很多方法需要对你的信息进行切分,另一种方法可能是有一个更通用的端点,你可以在其中应用过滤器,比如players?filter.city=louisville
还要注意“需要”这个词的用法。正如我在最初的回答中所说的,不要只是实现你能想到的任何组合。只实现你真正要使用的那些。谢谢,看起来很棒。为了确保我理解您的设计理念,/teams/:id/players
可能仍然是一个端点,当只需要一个团队的玩家列表时,当需要团队信息和球员列表时,/teams/:id?expand=players
将是一个端点?我不会同时实现查询字符串和/teams/:id/players。你应该选一个你喜欢的。如果你同时做这两件事,那么你必须支持多种方式永远做同一件事。如果我想要一个团队中的所有玩家,我将使用可选的查询参数?teamName=MyTeam提供/players作为端点。至于第二位,是的,我可以选择/teams/:id?expand=players。