当前位置:  开发笔记 > 编程语言 > 正文

REST复杂/复合/嵌套资源

如何解决《REST复杂/复合/嵌套资源》经验,为你挑选了2个好方法。

我试图围绕解决基于REST的API中的概念的最佳方式.不包含其他资源的平面资源没有问题.我遇到麻烦的地方是复杂的资源.

例如,我有一本漫画书的资源.ComicBook上有如各种属性author,issue number,date,等.

漫画书也有一份1..n封面清单.这些封面是复杂的对象.它们包含大量关于封面的信息:艺术家,日期,甚至是封面的64位编码图像.

对于GETComicBook我可以回相声,和所有的封面,包括他们的base64'ed图像.获得一部漫画可能不是什么大不了的事.但是假设我正在构建一个客户端应用程序,希望在表格中列出系统中的所有漫画.
该表将包含ComicBook资源中的一些属性,但我们当然不希望显示表中的所有封面.返回1000本漫画书,每本漫画书都有多个封面,这将导致大量数据流过网络,在这种情况下,最终用户不需要这些数据.

我的直觉是制作Cover资源并ComicBook包含封面.所以现在Cover是一个URI.GET漫画书现在可以使用,而不是Cover我们为每个封面发回一个URI 的巨大资源,客户可以根据需要检索封面资源.

现在我在创建新漫画方面遇到了问题.当我创建一个时,我肯定想要创建至少一个封面Comic,事实上这可能是一个商业规则.
所以现在我卡住了,我要么强制客户端通过先提交给执行业务规则Cover,获得URI为盖,然后POST荷兰国际集团一个ComicBook与URI列表,或者我POSTComicBook需要在寻找不同的资源比它吐出出.传入的资源是POSTGET深拷贝,其中传出的GETs包含对依赖资源的引用.

Cover在任何情况下,资源可能都是必要的,因为我确信作为客户,我想在某些情况下解决覆盖方向问题.因此,无论依赖资源的大小如何,问题都以一般形式存在.一般来说,如何处理复杂的资源而不强迫客户只是"知道"这些资源是如何组成的?



1> Alex..:

@ray,优秀的讨论

@jgerman,不要忘记仅仅因为它是REST,并不意味着必须从POST设置资源.

您选择在任何给定的资源表示中包含的内容取决于您.

您单独引用的封面的情况仅仅是创建父资源(漫画书),其子资源(封面)可以交叉引用.例如,您可能还希望分别提供对作者,发布者,字符或类别的引用.您可能希望单独创建这些资源,也可以在漫画书之前创建这些资源,将其作为子资源引用.或者,您可能希望在创建父资源时创建新的子资源.

您的封面的具体情况稍微复杂一点,因为封面确实需要漫画书,反之亦然.

但是,如果您将电子邮件视为资源,并将发件人地址视为子资源,您显然仍可以单独引用该地址.例如,从地址获取所有内容.或者,使用先前的地址创建新邮件.如果电子邮件是REST,您可以很容易地看到许多交叉引用的资源可用:/ received-messages,/ draft-messages,/ from-addresses,/ to-addresses,/ addresses,/ subject,/ attachments,/ folders ,/ tags,/ categories,/ labels,et al.

本教程提供了交叉引用资源的一个很好的示例. http://www.peej.co.uk/articles/restfully-delicious.html

这是自动生成数据的最常见模式.例如,您不会为新资源发布URI,ID或创建日期,因为这些是由服务器生成的.然而,当您获得新资源时,您可以检索URI,ID或创建日期.

您的二进制数据示例.例如,您希望将二进制数据作为子资源发布.获取父资源后,您可以将这些子资源表示为相同的二进制数据,或表示二进制数据的URI.

表单和参数已经与资源的HTML表示不同.发布导致URL的二进制/文件参数不是一个延伸.

当您获得新资源的表单(/ comic-books/new),或者获取表单来编辑资源(/ comic-books/0/edit)时,您要求提供表单特定的资源表示.如果将其发布到内容类型为"application/x-www-form-urlencoded"或"multipart/form-data"的资源集合中,则要求服务器保存该类型表示.服务器可以使用保存的HTML表示或其他任何方式进行响应.

您可能还希望允许将HTML,XML或JSON表示发布到资源集合,以用于API或类似目的.

您也可以在描述时代表您的资源和工作流程,同时考虑漫画书后发布的封面,但要求漫画书有封面.示例如下.

允许延迟创建封面

允许创建漫画书所需的封面

允许交叉引用封面

允许多个封面

创建漫画书草稿

创建漫画书封面草稿

发布漫画书草稿

GET /漫画书
=> 200好,获取所有漫画书.

GET /漫画书/ 0
=> 200 OK,获得带封面的漫画书(id:0)(/ cover/1,/ covers/2).

GET /漫画书/ 0 /封面
=> 200好,获取漫画书封面(身份:0).

GET/cover
=> 200 OK,获取所有封面.

GET/
cover/1 => 200 OK,获取封面(id:1)与漫画书(/漫画书/ 0).

GET /漫画书/新
=> 200 OK,获取表格创建漫画书(表格:POST/draft-comic-books).

POST/draft-comic-books
title = foo
author = boo
publisher = goo
published = 2011-01-01
=> 302 Found,位置:/ draft-comic-books/3,重定向到草稿漫画书(id:3)with封面(二进制).

GET/draft-comic-books/3
=> 200 OK,获得有封面的漫画书(id:3).

GET/draft-comic-books/3/covers
=> 200 OK,获取漫画书的封面(/ draft-comic-book/3).

GET/draft-comic-books/3/covers/new
=> 200 OK,获取表格为草稿漫画书制作封面(/ draft-comic-book/3)(表格:POST/draft-comic-books/3 /盖子).

POST/draft-comic-books/3/
cover cover_type = front
cover_data =(binary)
=> 302 Found,位置:/ draft-comic-books/3/covers,重定向到草稿漫画书的新封面(/ draft-comic) -book/3 /覆盖/ 1).

GET/draft-comic-books/3/publish
=> 200 OK,获取表格发布漫画书(id:3)(表格:POST /已发表 - 漫画书).

POST/published-comic-books
title = foo
author = boo
publisher = goo
published = 2011-01-01
cover_type = front
cover_data =(binary)
=> 302 Found,位置:/ comic-books/3,重定向到已出版的漫画书(id:3)有封面.


@GaryMcGill在他的例子中,/ draft-comic-books/3/publish只返回一个HTML表单(不修改任何数据).
@Stephane,重定向只是让控制器更简单.即使对于API,创建控制器返回新内容的位置,然后让show controller处理新内容的显示也更简单.尽管如此,API的客户端更好/更简单地获取内容而不用重定向.

2> Ray Toal..:

将封面视为资源绝对符合REST的精神,特别是HATEOAS.所以是的,一个GET请求http://example.com/comic-books/1会给你一本书1的表示,其中的属性包括一组封面的URI.到现在为止还挺好.

你的问题是如何处理漫画创作.如果您的业务规则是一本书有0或更多封面,那么您没有问题:

POST http://example.com/comic-books

无盖漫画书数据将创建一个新的漫画书并返回服务器生成的id(假设它回来为8),现在你可以像这样添加封面:

POST http://example.com/comic-books/8/covers

在实体主体的封面.

现在你有一个很好的问题,如果你的业务规则说总是必须至少有一个封面会发生什么.以下是一些选择,您在问题中确定了第一个选项:

    首先强制创建封面,现在基本上覆盖非依赖资源,或者将初始封面放在创建漫画书的POST的实体主体中.正如您所说,这意味着您要创建POST的表示形式将与您获取的表示形式不同.

    定义主要,初始或首选或其他指定封面的概念.这可能是一个建模黑客,如果你这样做,就像调整你的对象模型(你的概念或商业模型)以适应技术.不是一个好主意.

你应该权衡这两个选择,而不是简单地允许无盖漫画.

你应该选择哪三种选择?不太了解你的情况,但回答一般的1..N依赖资源问题,我会说:

如果您可以使用0..N作为RESTful服务层,那就太好了.如果至少需要一个,RESTful SOA之间的层可能会处理进一步的业务约束.(不确定这看起来如何,但它可能值得探索......最终用户通常不会看到SOA.)

如果你只是必须建模一个1..N约束,那么问问自己封面是否只是可共享的资源,换句话说,它们可能存在于漫画书以外的东西上.现在,它们不依赖于资源,您可以先创建它们,然后在POST中提供创建漫画书的URI.

如果您需要1..N且封面仍然依赖,只需放松您的直觉以保持POST和GET中的表示相同,或使它们相同.

最后一项解释如下:


  ...
  ...
  ...BASE64...
  ...BASE64...
  ...URI...
  ...URI...

当您发布POST时,如果您拥有它们(从其他书籍中借用),则允许现有的uris,但也可以放入一个或多个初始图像.如果您要创建图书并且您的实体没有初始封面图片,请返回409或类似的回复.在GET上你可以返回URI ..

所以基本上你允许POST和GET表示"相同",但你只是选择不在GET上"使用"封面图像,也不在POST上覆盖.希望有道理.

推荐阅读
农大军乐团_697
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有