42

维基百科有:

统一的界面

统一接口约束是任何 REST 服务设计的基础。 [14] 统一的接口简化并解耦了架构,使每个部分都可以独立发展。该接口的四个指导原则是:

资源识别

在请求中标识单个资源,例如在基于 Web 的 REST 系统中使用 URI。资源本身在概念上与返回给客户端的表示是分开的。例如,服务器可以从其数据库中以 HTML、XML 或 JSON 的形式发送数据,这些都不是服务器的内部表示,无论如何它都是同一个资源。

通过这些表示来操纵资源

当客户端持有资源的表示,包括任何附加的元数据时,它有足够的信息来修改或删除资源。

自我描述的消息

每条消息都包含足够的信息来描述如何处理该消息。例如,调用哪个解析器可以由 Internet 媒体类型(以前称为 MIME 类型)指定。响应还明确表明它们的可缓存性。

超媒体作为应用程序状态的引擎(AKA HATEOAS)

客户端仅通过服务器在超媒体内动态识别的动作(例如,通过超文本中的超链接)进行状态转换。除了应用程序的简单固定入口点之外,客户端不假定任何特定操作可用于任何特定资源,而不是先前从服务器接收的表示中描述的那些。

我正在听一个关于这个主题的讲座,讲师说:

“当有人使用我们的 API 时,如果您能够获取客户对象并且您知道有订单对象,那么您应该能够以与获取客户对象相同的模式获取订单对象。这些 URI 是会看起来像彼此。”

这让我觉得错了。与 URI 的外观或一致性无关,因为它是 URI 的使用方式(识别资源、通过表示、自描述消息和仇恨来操纵资源)。

我认为这根本不是统一接口的意思。它到底是什么意思?

4

4 回答 4

52

使用接口将类与其依赖项的实现分离是一个非常古老的概念。在 REST 中,您使用相同的概念将客户端与 REST 服务的实现分离。为了定义这样的接口(客户端和服务之间的契约),您必须使用标准。这是因为如果你想要一个互联网规模的 REST 服务网络,你必须强制执行全局概念,比如标准,以使它们相互理解。

  • 资源标识- 您使用 URI (IRI) 标准来标识资源。在这种情况下,资源是 Web 文档。

  • 通过这些表示操作资源- 您使用 HTTP 标准来描述通信。因此,例如 GET 意味着您要检索有关 URI 标识资源的数据。您可以使用 HTTP 方法和 URI 来描述操作。

  • 自描述消息- 您使用标准 MIME 类型和(标准)RDF 词汇来使消息具有自描述性。因此客户端可以通过检查语义来找到数据,而不必知道服务使用的特定于应用程序的数据结构。

  • 超媒体作为应用程序状态的引擎(又名 HATEOAS)——您使用超链接和可能的URI 模板将客户端与特定于应用程序的 URI 结构分离。您可以使用语义注释这些超链接,例如IANA 链接关系,以便客户了解它们的含义。

于 2014-09-25T23:29:24.550 回答
11

任何 ReSTful 架构都应遵守的统一接口约束实际上意味着,与数据一起,服务器响应还应宣布可用的操作和资源。

他的论文第 5 章中,Roy Fielding(ReST 架构风格的创始人)指出,使用统一接口的目的是:

简化和改进全球架构和交互的可见性

换句话说,查询资源应该允许客户端在事先不知道的情况下请求其他动作和资源

JSON-API规范提供了一个很好的例子:

{
  "links": {
    "self": "http://example.com/articles",
    "next": "http://example.com/articles?page[offset]=2",
    "last": "http://example.com/articles?page[offset]=10"
  },
  "data": [{
    "type": "articles",
    "id": "1",
    "attributes": {
      "title": "JSON API paints my bikeshed!"
    },
    "relationships": {
      "author": {
        "links": {
          "self": "http://example.com/articles/1/relationships/author",
          "related": "http://example.com/articles/1/author"
        },
      },
      "comments": {
        "links": {
          "self": "http://example.com/articles/1/relationships/comments",
          "related": "http://example.com/articles/1/comments"
        }
      }
    },
    "links": {
      "self": "http://example.com/articles/1"
    }
  }]
}

只需分析这个单一的响应,客户就知道:

  1. 查询了什么articles在本例中)
  2. 结构文章对象 ( id, title, author, comments)如何
  3. 如何检索相关对象(即author、 的列表comments
  4. 有更多文章(,10基于当前响应长度和分页链接)

我希望这有帮助。
对于那些对该主题充满热情的人,我强烈建议阅读Roy Thomas Fielding 的论文

于 2018-04-07T10:08:43.977 回答
3

您的问题有点宽泛,您似乎要求重述您的定义。您是在寻找示例还是您不了解具体说明的内容。

我同意这一行:

这些 URI 看起来彼此相似

根本上是错误的。为了满足统一接口约束,URI 不需要看起来彼此相似。需要提供一种统一的方式来发现标识资源的 URI。这种统一的方式对每种消息类型都是唯一的,并且必须有一些约定的格式。例如,在 HTML 中,一个文档资源通过一个简单的标签链接到另一个文档资源:

<a href="URI of related resource" rel="defined relationship">fallback relationship</a>

HTTP 服务器将 html 作为文本/html 资源类型返回,浏览器具有约定的解析方式。锚标记是具有相关资源的唯一标识符的超媒体控件 (HATEOAS)。

唯一没有涉及的一点是操纵。HTML 有另一个很棒的例子,form 标签:

<form action="URI" method="verb">
  <input name=""></input>
</form>

同样,浏览器知道如何解释这个元信息来定义在 URI 上作用的资源的表示。不幸的是,HTML 只允许你 GET 和 POST 动词......

在基于 JOSN 的服务中更常见的是,当您检索 Person 资源时,很容易操纵该表示,然后将其 PUT 或 PATCH 直接返回到它的规范 URL。修改它不需要预先存在的资源知识。现在,当我们编写客户端代码时,我们完全被这样一种想法所包围,即我们确实需要在使用它之前知道形状……但这实际上只是为了使我们的解析器高效且简单。我们可以制作解析器来分析资源每个部分的语义,并通过解释修改的意图来修改它。IE:使人大 10 岁的命令将解析资源以查找年龄,识别年龄,然后将 10 年添加到该值,然后将该资源发送回服务器。拥有期望年龄位于 $.age 的 JSON 路径的代码是否更容易?绝对......但这不是特别必要的。

于 2014-08-11T17:22:40.783 回答
2

好的,我想我明白这意味着什么。

来自菲尔丁的论文:

将 REST 架构风格与其他基于网络的风格区别开来的核心特征是它强调组件之间的统一接口(图 5-6)。通过将软件工程的通用性原则应用于组件接口,简化了整个系统架构并提高了交互的可见性。

他是说组件之间的接口必须相同。IE。在客户端和服务器之间以及任何中介之间,所有这些都是组件。

于 2014-08-07T01:33:03.247 回答