0

请原谅我,因为我对这个 RESTFUL 的东西还是新手,我一直在阅读博客等......而且他们都有不同的实现/指南,唯一真正的指南是指定超媒体是什么的 Richardson 成熟度模型。

我知道超媒体设计的好处是具有通过根 URL 驱动机器/用户交互的注释链接,并且它将像链接更改时一样可以进化,使用幂等/安全的 http 动词等增强缓存......

我正在尝试设计一个 RESTFUL API Web 服务,并且我计划使用通用媒体类型,例如 HAL 或 Collection+Json 或警报器等......或者可能创建我自己的媒体类型,我认为我不想进入正确的现在...

使用通用媒体类型,我将有一个有效负载、一个数据结构或 DTO 对象,无论你怎么称呼它,比如“具有许多申请人模型和许多地址的应用程序模型等......”

1)我必须在某处指定数据结构定义吗?或某种形式的模板?我已经看到了一些示例,他们将这些数据的定义以人类可读的格式放置在“someurl/doc”中?或者我们应该使用类似 json 模式的东西吗?

2)我见过的一些例子用来自 vcard/foaf 等的链接中的类型修饰了他们的数据项......例如。“名称”:“ http://xmlns.com/foaf/0.1/name ”。这意味着什么?我看到的一些示例像引用了它们的 someurl/doc#name 来描述名称对象等...

3)这是否意味着如果Application Model的payload发生变化,合约的解释器也会发生变化?因此所有客户端都像以前一样中断,就像在 SOAP 中一样?

4)另一种选择,我认为我可以有一个可进化的项目结构,比如具有名称、值、提示的集合+json项目对象,它形成了实际的结构,这样在使用它的客户端上就会有最小的合同变化。

请就我应该如何设计我的对象提出建议,基本上说我有一个应用程序对象,其中包含多个具有多个地址的申请人以简化问题。

乔什

4

1 回答 1

3

当前的最佳做法是尽可能避免创建新的内容类型,因此您回避它是正确的。

  1. 取决于你的听众。使用他们最容易消费的任何东西。他们是可以理解模式的通用自动化代理,还是专门为您的 API 工作的开发人员。无论如何,你总是需要人类可读的文档,所以我会从那里开始。如果您选择接受application/x-www-form-urlencoded请求正文,那么 HTML 表单将是提供工作模板的好方法。
  2. 这定义了字段的“类型”。所以nameafoaf:name告诉你被调用的字段name包含一个 type 的值http://xmlns.com/foaf/0.1/name。您应该阅读 RDF(资源描述格式),并查看 Turtle 和 N3 之类的表示,这应该会更清楚。URI(而不是简单的字符串)关系的概念来自那里,尽管链接关系与 RDF 属性(例如owl:sameAsor )不同foaf:name。两者都表示为有向图中的边。
  3. 请进一步解释,您是指添加/删除的字段还是完全不同的内容类型?我认为后者是不同的资源,应该有不同的 URI。您的客户需要了解或能够忽略您将来对资源所做的任何更改。
  4. 您建议的所有内容类型都应该以这种方式进化。这正是 HATEOAS 的前提。

在我看来,您的设计是一个简单的树结构,具有一个根资源,包含一个集合列表,每个集合都包含一个叶资源列表。我似乎在这里遗漏了一些东西,因为这没有什么复杂的。

我将假设申请人是指申请工作的人,而地址是指他们居住或工作的地方(而不是电子邮件地址)。下面的一些内容可能很明显,但我将其包括在可能遇到此问题的其他读者中。

使用 HAL 的示例实现将是:

要求:

GET / HTTP/1.1
Host: example.com
Accept: application/hal+json

回复:

HTTP/1.1 200 OK

{ "_links": {
    "self": { "href": "/" },
    "http://example.com/docs/applicant": [
      { "href": "/applicant1" },
      { "href": "/applicant2" },
      { "href": "/applicant3" }]
} }

然后,客户端将查找具有关系的超链接http://example.com/docs/applicant,这只是一个字符串,fishmonkeygiraffe如果您愿意,也可以是 - 使字符串成为 http URL 允许客户端开发人员更轻松地找到您的文档,以及通过为其添加前缀来确定关系范围一个唯一的字符串:您自己的域。响应格式可以是任何支持超文本的格式,例如 HTML,只要客户端知道如何在其中找到超链接(<LINK> 和 <A> 元素),或者您可以在 HTTP Link 标头中返回它们,但是如果需要将检索到的资源写入磁盘,则客户端负责存储它们。

然后客户端请求它想要查看的那个:

GET /applicant1 HTTP/1.1
Host: example.com
Accept: application/hal+json

回复:

HTTP/1.1 200 OK

{ "_links": {
    "self": { "href": "/applicant1" },
    "http://example.com/docs/applicant-address": [
      { "href": "/applicant1/address1" },
      { "href": "/applicant1/address2" },
      { "href": "/applicant1/address3" }]
} }

显然“applicant1”可以是任何你喜欢的东西,例如“applicants/1”或“vacancies/sweet-manager/applicants/dave-smith”。客户端只是按照给定的 URL。

然后客户端选择一个类型的超链接http://example.com/docs/applicant-address来检索:

GET /applicant1/address1 HTTP/1.1
Host: example.com
Accept: application/hal+json

回复:

HTTP/1.1 200 OK

{ "_links": {
    "self": { "href": "/applicant1/address1" },
    "edit-form": { "href": "/applicant1/address1/edit" },
    "http://example.com/docs/applicant": { "href": "/applicant1" }
  },

  "street": "5 Dungeon Drive",
  "town": "Snotty Hill",
  "county": "London",
  "postcode": "NE5 2LT",
  "country": "GB",
}

现在客户想要修改地址,所以它遵循带有“edit-form”关系的超链接:(请参阅IANA 链接关系

GET /applicant1/address1/edit HTTP/1.1
Host: example.com
Accept: text/html

回复:

HTTP/1.1 200 OK

<!DOCTYPE HTML>
<form action="/applicant1/address1" method="POST">
  <input name="street" value="5 Dungeon Drive">
  et cetera
</form>

导致:

POST /applicant1/address1 HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded

street=5%20Dungeon%20Drive&...

我使用了 HAL,因为 HAL 就像 XML+XLink 的 JSON 版本,只是在 SO 示例中键入更简单;)即它是一种支持超媒体的通用解析格式,仅此而已。所有交互都由链接关系引导。Web 浏览器知道如何处理rel="stylesheet"链接,因为它知道这种关系意味着什么。上面引用的 IANA 定义的链接关系列表是您应该首先选择的链接关系列表(itemcollection非常有用),然后如果您要查找的内容不够具体,请尝试查找与您的行业相关的链接关系的公开列表(例如查看市场领导者发布的 API)并尽可能重复使用这些列表。这将使工具变得可互操作,因为它们都在寻找相同的链接关系。您在问题中的都柏林核心示例是一个类似的公开定义的 RDF 属性存储库。

对于超链接,耦合(契约)不是客户端和你的站点之间,而是客户端和一组关系。这些关系应该尽可能地广为人知(这就是维基百科所说的“对超媒体的一般理解”的意思)。
对于资源字段,如果您希望对资源进行一般处理,那么我会推荐一个基于 RDF 的解决方案,使用与您的业务领域密切相关的知名 RDF 属性。存在几个 RDF 序列化为 JSON,但目前没有明确的领导者。此时您最好只支持 XML。博客文章JSON 到 RDF 的六个简单步骤可能是学习 RDF 基础知识的一种方式。

于 2013-06-12T09:32:33.177 回答