使用自己的端点(这被称为服务分层,具有许多好处),但不要与您的端点紧密耦合。
首先,我不会按数字ID查询,因为这与您的实现紧密绑定。如果您将URL用作车库标识符,则将获得更多的灵活性,并且可以轻松地添加对其他系统中的车库的支持。
使用超媒体控件(即链接和表单)在汽车列表上添加搜索表单。假设您的汽车列表看起来像这样(为简洁起见,排除了方案和主机)
<cars self="/cars">
<car href="/cars/0"/>
<car href="/cars/1"/>
...
</cars>
注意:您需要为汽车添加一些摘要属性(例如注册、制造商、型号等),以使搜索有意义,而不必返回完整的汽车实体。
要添加搜索功能,我们可以添加类似于
<cars self="/cars">
<car href="/cars/0"/>
<car href="/cars/1"/>
...
<form name="search" action="/cars" method="get">
<input name="garage" type="URL"/>
</form>
</cars>
在您的资源库(例如数据库)中,如果您的汽车存储了它们所在车库的URL,则可以执行此查询而无需查询任何车库,并且如上所述,支持在完全不同的系统中拥有车库,假设另一个系统使用您的
媒体类型或您支持其媒体类型。
显然,在搜索时您需要访问车库的URL,这可以通过进行车库搜索来完成。例如:
<garages self="/garages">
<garage href="/garage/0"/>
<garage href="/garage/1"/>
...
<form name="search" action="/garages" method="get">
<input name="paint" type="string"/>
<!-- other things to search for can go here -->
</form>
</garages>
所以,当用户想在多个车库中搜索汽车时,他们首先搜索那些车库,并将感兴趣的车库添加到列表中(这只是一组URL列表)。然后使用车库列表作为输入搜索汽车。
在这种情况下,车库和汽车仅由URL耦合。
您可以通过在车库集合中添加指向汽车搜索的链接来进一步扩展此功能。例如,假设我们搜索了黄色涂漆的车库,我们可能会得到一个像这样的集合。
<garages self="/garages?paint=yellow">
<garage href="/garage/24"/>
<garage href="/garage/36"/>
...
</garages>
为了获取此集合的汽车列表,我们可以添加以下链接。
<garages self="/garages?paint=yellow">
<garage href="/garage/24"/>
<garage href="/garage/36"/>
<link rel="cars" href="/cars?garage=/garage/24,/garage/36"/>
</garages>
这个方法对于小型的车库列表是可行的,但当车库列表增长时会变得麻烦,此时汽车的URL将变得过长。相反,我们可以使用搜索的URL作为输入参数。例如:
<garages self="/garages?paint=yellow">
<garage href="/garage/24"/>
<garage href="/garage/36"/>
<link rel="cars" href="/cars?garages=/garages?paint=yellow"/>
</garages>
在这种情况下,当您跟随汽车链接时,您的服务将需要执行车库查询,检索每个车库的汽车列表,然后返回合并的汽车列表。除了更短的URL之外,此查询的好处是它始终会为您提供带有黄色油漆的车库中的汽车列表,即使车库的油漆库存发生变化。
您的服务如何获取车库中的汽车列表?车库实体可以有一个指向汽车集合的链接,例如。
<garage self="/garage/24">
... details about the garage ...
<link rel="cars" href="/cars?garage=/garages/24"/>
</garages>
正如我在开头所说,使用您自己的终端节点,但不要通过假设它们是您自己的终端节点而紧密耦合它们。为实体构建超媒体控件,当您的服务需要使用它们时,将其视为任何其他外部API。
最后(略微偏题),为了支持大量汽车和车库的集合,您可以向您的集合添加分页功能,例如:
<garages self="/garages?page=2">
<garage href="/garage/10"/>
<garage href="/garage/11"/>
...
<link rel="next" href="/garages?page=3"/>
<link rel="prev" href="/garages"/>
</garages>
你甚至可能希望让你的集合符合
RFC5005 Paged Feeds和
Complete Feeds,以便可以使用标准工具消耗它们。
更新:
以下是一个带有超媒体控制的JSON车库集合示例,使用了上述一些概念:
{
"self": "/garages?paint=yellow&page=2",
"garages": [
{
"href": "/garage/24"
},
{
"href": "/garage/36"
}
],
"next": {
"href": "/garages?paint=yellow"
},
"prev": {
"href": "/garages?paint=yellow&page=3"
},
"cars": {
"href": "/cars?garages=/garages?paint=yellow"
},
"search": {
"href": "/garages?paint=yellow",
"method": "GET",
"inputs": {
... form input parameters go here ...
}
}
}