2010-07-14 54 views
11

据说在一个定义良好的RESTful系统中,客户端只需要知道根URI或几个众所周知的URI,并且客户端应该通过这些初始URI发现所有其他的链接。我明白这个方法的好处(解耦客户端),但对我的缺点是,客户端需要发现链接的每个尝试访问的东西,即给定资源的层次结构如下时间:连通性和HATEOAS

/collection1 
collection1 
    |-sub1 
    |-sub1sub1 
|-sub1sub1sub1 
     |-sub1sub1sub1sub1 
    |-sub1sub2 
    |-sub2 
    |-sub2sub1 
    |-sub2sub2 
    |-sub3 
    |-sub3sub1 
    |-sub3sub2 

如果我们按照“客户端只需要知道根URI”的方法,那么客户端应该只知道上面的根URI(即/ collection1),其余的URI应该由客户端通过超媒体链接来发现。我觉得这很麻烦,因为每次客户端需要做一个GET时,比如在sub1sub1sub1sub1上,如果客户端首先在/ collection1上执行GET,并在返回的表示中定义后续链接,然后在子资源上执行多个GET以达到期望的资源?还是我对连通性的理解完全错误?

最好的问候, 苏雷什

+0

只是REST服务是无状态的,客户端不是。因此,客户可以记住以前的资源,它们的URL等等,例如通过嵌套的导航菜单... – inf3rno 2013-11-15 04:04:19

回答

6

当您尝试构建与使用API​​的用户代理的流不匹配的REST API时,您将遇到此不匹配问题。

考虑当您运行客户端应用程序时,用户始终会显示一些初始屏幕。如果您将此屏幕上的内容和选项与根表示相匹配,则可用链接和所需转换将很好地匹配。当用户选择屏幕上的选项时,您可以转换到其他表示,并且应该更新客户端UI以反映新的表示。

如果您试图将REST API建模为某种链接的数据存储库和您的客户端UI作为独立的转换集,那么您会发现HATEOAS非常痛苦。

+0

痛苦并不一定是真实的:我只有这样,项目集合的层次结构,以及客户端在开始时,钻取一个或两个级别,并钻取到特定路径(客户端使用的路径当它关闭时)。客户端的缓存是持久的,所以所有的请求都是有条件的,而且很少有新的表示通过连线,并且刷新可以通过完全关闭缓存在后台异步完成。 – mogsie 2010-07-14 22:59:20

+0

我同意将“API”建模为客户端应用程序的需求可以提供有效的会话,但我认为重点在于API经常适用于许多客户端,而不仅仅是一个客户端。 – mogsie 2010-07-14 23:01:55

+0

@mogsie在许多情况下,为多个客户端构建API可能是可能的,但我认为在大多数情况下,为特定情况构建API效率更高。偶然的重用是REST旨在提供的,而不一定是有计划的重用。 – 2010-07-15 01:11:32

0

我不认为是这样的严格要求。根据我的理解,客户直接访问资源并从此开始是合法的。重要的是,您不需要为状态转换执行此操作,即在/ foo1等操作之后不会自动继续处理/ foo2。最初检索/ products/1234编辑它似乎非常好。服务器总是可以返回,比如重定向到/ shop/products/1234以保持向后兼容(这对于搜索引擎,书签和外部链接也是可取的)。

4

是的,客户端应用程序应该遍历链接是正确的,但是一旦发现资源,保留对该资源的引用并使用它的时间比一个请求更长时间没有任何问题。如果你的客户有永久记忆的可能性,它可以这样做。

考虑网络浏览器如何保留其书签。您可能在浏览器中可能会有一百或者一百个书签,并且您可能在页面层次结构中发现了其中的一些,但浏览器尽职地记住了它们,而不需要记住它们找到它们的路径。

更丰富的客户端应用程序可以记住sub1sub1sub1sub1的URI,并在它仍然有效时重用它。它很可能仍然代表着同样的事情(它应该)。如果因任何其他客户原因(4xx)不再存在或失败,您可以重新执行步骤以查看是否可以找到合适的替代品。

当然Darrel Miller说:-)

+1

我喜欢你的比喻。有这样的想法,一切都连接在一起,不能连接的东西。谷歌在这个意义上成为所有导航的根源,但人们总是保存捷径(书签)。但是,如果你不在谷歌那么你基本上不存在。 – Alex 2014-12-10 16:53:07

+0

谢谢。或者,更确切地说:如果谷歌没有路径到页面,它就不存在。有点像这个谜语:“如果一棵树落在一片森林里,没有人在那里听到它,它会发出什么声音?” – mogsie 2014-12-17 09:30:29