【问题标题】:Up to what level information should be atomized in a web service?在 Web 服务中应该将信息原子化到什么级别?
【发布时间】:2013-10-20 07:47:02
【问题描述】:

我正在实现一个 REST Web 服务,我想知道是否有任何关于如何将服务公开的信息原子化的约定。到目前为止,我一直无法找到令人满意的解决方案,所以现在我向互联网上最伟大的人提问:P

例如,假设我想实现一个 API 来访问某种库注册表,所以我们有一个路径为 /books 的资源。例如,通过阅读/books/123,我们将获得以下 XML 数据:

<?xml version="1.0" encoding="utf-8"?>
<book>
    <title>Visit Catalonia</title>
    <author>J. Hans</author>
    <year>2000</year>
</book>

假设作者信息有误,我想通过 Web 服务的 API 更改它。我提出了两种可能的选择,每种都有优点和缺点:

选项 1: 使用以下数据向/books/123 发出 HTTP PUT 方法:

<?xml version="1.0" encoding="utf-8"?>
<book>
    <author>G. Robinson</author>        
</book>

优点:

  • 只需要实现 1 个资源处理程序:/books/BOOKID
  • 我们可以修改数据中定义的 XML 标记的尽可能多的信息(例如:添加上面的代码,我们也会更新图书的年份)。

缺点:

  • GET 方法总是返回关于一本书的所有数据;我们不能只访问一条信息。在此示例中,获取所有数据不是问题,但如果 /book/123 也有一个带有图书内容本身的标签以便在线阅读呢?

选项 2: 向/books/123/author发出HTTP PUT方法发送数据:

<?xml version="1.0" encoding="utf-8"?>
<author>G. Robinson</author>

优点:

  • 可以以任意深度访问信息:API 客户端只需下载他/她需要的信息。

缺点:

  • 我们无法通过单个 HTTP 请求获取或修改多条信息。
  • 实施起来很困难:子资源与信息字段一样多。

因此,总而言之,我的问题是是否有任何普遍接受的约定可以在 Web 服务中公开信息。当然,在管理少量数据的简单 Web 服务中,这不是问题,但如果我们公开真实世界的数据库怎么办?

非常感谢您。

【问题讨论】:

  • 我很困惑。您的 PUT 请求与您的问题有什么关系?
  • 这只是一个访问资源的例子。我要问的是应该沿着网络资源稀疏到什么程度的深度信息。换句话说:创建少量资源来检索或写入大量数据还是创建许多资源来检索/写入少量数据更好?
  • 啊,好的。我不认为有一个好的答案。我认为您需要根据使用情况进行优化。我倾向于从大量资源开始,并在它们之间进行更多导航,如果这有助于优化,用户可以选择传递参数以内联(即嵌入)一些资源。

标签: database rest service web


【解决方案1】:

远程接口(如 Web 服务)通常是粗粒度的。这样可以最大限度地减少网络开销。

使用数据向/books/123 发出 HTTP PUT

<?xml version="1.0" encoding="utf-8"?>
<book>
    <author>G. Robinson</author>        
</book>

在我看来,这本书不再有&lt;title&gt;&lt;year&gt;。您 PUT 到 /books/123 的数据应包括所有关于图书的相关信息,即使是未更改的信息。

/books/123/author 发出带有数据的HTTP PUT

<?xml version="1.0" encoding="utf-8"?>
<author>G. Robinson</author>

是您期望从本地界面而不是远程界面获得的那种精细控制。如果使用粗粒度界面一次更新整本书数据的成本过高(例如,如果书籍数据还包含书籍的全文并且您经常只需要更新单个属性),则在粗粒度界面之外使用此接口.

【讨论】:

  • 这很好;我没有考虑本地/远程问题。事实上,选项 1 相当令人困惑,因为缺少其他书籍字段实际上破坏了数据模型。关于选项 2,定义资源 /book/ID/info/book/ID/content 是否是个好主意?在这种情况下,获取/book/ID 将获取/放置整个数据,而其他两个子资源将获取/放置它们对应的信息。
  • 另一种选择是使用 PATCH 代替 PUT 用于 /books/123/。这将清楚地表明客户端只发送它想要更改的内容。
  • OMG,我以前从未听过 PATCH 方法……真丢脸!
【解决方案2】:

我相信您可以两者兼得,具体取决于您要支持的客户需求/情况:

  • GET/POST /books/123 :您获取并发布(创建/更新)完整的图书属性
  • GET/POST /books/123/author :您获取并发布(创建/更新)本书的作者

您没有理由不能同时使用这两个选项。客户可以根据他们所处的情况遵循其中一个或另一个...在创建新书条目或更新整个条目时,选项 1 似乎更合适...而如果您在客户端 UI 中允许更新,则选项 2一次“一个财产”。因此,这可能在很大程度上取决于您想要支持的客户“意图”/情况......您在设计时应该考虑到这一点。

我刚刚阅读了一篇关于 InfoQ 的精彩文章,其中涉及到了其中的一些要点(以及其他内容)。看看“不要暴露你的领域模型”和“根据意图设计你的 API”点 - http://www.infoq.com/news/2013/10/gotober-do-dont-webapi

【讨论】:

  • 文章给出了一些我没有想到的建议,所以谢谢你的链接。然而,这个问题似乎相当“开放”,其解决方案确实高度依赖于客户的需求。还是不太满意:D
  • 确实,似乎没有“最佳设计”的概括……需要尝试根据要支持的用例进行优化。但是,如果您没有明确的客户端用例并且想要支持不同的应用程序,这将很棘手,在这种情况下,方法/选项的组合可能是一个不错的选择。但同样,似乎没有“一般准则”来做到这一点:p
猜你喜欢
  • 1970-01-01
  • 2012-01-29
  • 1970-01-01
  • 1970-01-01
  • 2011-01-20
  • 2010-09-13
  • 2011-09-25
  • 2019-12-02
  • 2015-07-27
相关资源
最近更新 更多