嗯,这里发生了几件事。
首先,您可以简单地添加指向任何常见“全局”资源的链接。尽管我很讨厌将 REST 架构与网站进行比较,但网站是一个合适的示例。考虑一下 SO 上的许多资源都具有指向通用“全局”资源的链接——例如主页、/questions、/tags、/badges 和 /users。
资源是“静态的”并且从不更改这一事实不会影响您是否通过另一个资源作为 HATEOS 的一部分将资源作为链接提供,这是一个正交问题。
第二点是,没有什么可以说整个服务可以从每个资源中持续访问。您可以在您的服务中拥有“众所周知的”入口点,并且这些入口点可以有据可查(外部)。唯一的缺点是,如果某个关系的 URL 发生变化(例如 /questions 到 /questions-2),那么客户端可能不会自动获取这些 URL。但这可能不是问题,因为通过更改 URL,您可能会更改影响客户端的其他内容(例如有效负载),以至于旧客户端可能与新 URL 不兼容。
让客户“知道”事物在嵌套系统中的位置也不是问题。例如,如果他们“知道”,如文档所述,他们只能从 /home 资源访问 /version,并且每个其他资源都有到 /home 的路径(直接或间接),那么这不是问题任何一个。当它想要 /version 时,它应该知道获取它的路径是什么。
只要客户根据您告诉它的内容而不是“它的想法”来遍历图表,那么一切都很好。如果客户端当前正在处理 /blog/daily_news/123 资源,并且它有一个指向“parent”的链接 rel,其 url 是 /blog,并且 /blog 有一个指向 /version 的链接 rel “version”,那么客户端可以遍历图(遍历父 rel 到 /blog,版本 rel 到 /version)。客户端不应该做的(除非另有说明)是它不应该假设它可以随时访问 /version 。由于它没有从 /blog/daily_news/123 链接,客户端不应该只是跳到它。rel 不存在,所以客户“不知道”。
这是关键点。它不存在的事实意味着它现在不是一个选项,无论出于何种原因,也不是客户端任务强制指出这一点,因为 URL 空间不在它的手中,它在服务的手中。服务控制它,而不是客户端。
如果 /version 突然消失,那是另一个问题。也许他们超时并且不再被允许“看到” /version,也许你删除了它。此时客户端将简单地出错“找不到版本 rel”,然后退出。这是一个无关的问题,只是一个事实(当资源突然消失在你的背后,你还能做什么)。
问题补充:
如果我理解这意味着:如果 /home 没有过期,并且我们导航到 /blog(其中包含返回 /home 的 rel),那么 /home 的 rel 方法仍然可以立即从 /blog 中“访问”,对吗?
不,不是。这是关键点。除了一些专门记录的全局资源(带外),您不应遍历当前资源中未指定的任何链接。/home 是否未过期根本不相关。
服务器当然可以发送适当的缓存指令,让您知道您可以缓存 /home 一段时间,但您仍然应该遍历 rel 到 /home 以获取您认为存在的任何链接。
如果 /home 很好地缓存在您的客户端上,那么这种遍历实际上是免费的,但从逻辑和语义上讲,您应该坚持遍历链接的协议。
因为如果它没有被缓存,那么你根本不知道当你回来时会有什么 rels 存在。是的,99.999999% 的时间它总是相同的,并且为服务器没有发送适当的缓存头而感到羞耻,但根据定义,服务器并没有向你承诺任何东西,所以你,客户端和它,服务器,一次又一次地吃掉一个有效的静态资源的处理成本。
通过强制您的客户遵循这些步骤,也许通过缓存和预处理进行内部优化以使这些静态遍历快速有效,您坚持使用 HATEOS 模型,并遵循系统以使其最佳而不是预先假设在代码级别并跳过您认为已经拥有的 rels。
这样,无论服务器做什么,您的代码都将始终有效。谁知道他们什么时候可以打开或关闭缓存,你的代码当然不应该关心,而不是在决定是否取消引用链接的级别。
HATEOS 的前提是服务器负责并授权其 URL 空间。在没有服务器指导的情况下随意跳动是不合规范的,这不是您要导航的图表。REST 用于更粗粒度的操作,但适当的缓存等可以使您的客户端快速高效地跳过这些环节。