对于最新的稳定版本,请使用 Spring Data REST 5.0.4spring-doc.cadn.net.cn

元数据

本节详细介绍了基于 Spring Data REST 的应用程序所提供的各种形式的元数据。spring-doc.cadn.net.cn

应用级配置语义 (ALPS)

ALPS 是一种用于定义应用层语义简单描述的数据格式,其复杂度与 HTML 微格式(microformats)类似。ALPS 文档可用作一种 profile(配置文件),用于解释具有与应用无关媒体类型(例如 HTML、HAL、Collection+JSON、Siren 等)的文档的应用语义。这提高了 profile 文档在不同媒体类型间的可重用性。
— M. Admundsen / L. Richardson / M. Foster
https://tools.ietf.org/html/draft-amundsen-richardson-foster-alps-00

Spring Data REST 为每个导出的仓库提供了一份 ALPS 文档。该文档包含了有关每个仓库的 RESTful 转换和属性的信息。spring-doc.cadn.net.cn

Spring Data REST 应用的根路径包含一个 profile 链接。假设你有一个同时包含 persons 及其关联的 addresses 的应用,那么根文档将如下所示:spring-doc.cadn.net.cn

{
  "_links" : {
    "persons" : {
      "href" : "http://localhost:8080/persons"
    },
    "addresses" : {
      "href" : "http://localhost:8080/addresses"
    },
    "profile" : {
      "href" : "http://localhost:8080/profile"
    }
  }
}

配置文件链接(profile link)是用于包含应用级详细信息的地方,其定义见RFC 6906ALPS 草案规范旨在定义一种特定的配置文件格式, 我们将在本节稍后部分进行探讨。spring-doc.cadn.net.cn

如果你访问 localhost:8080/profile 处的 profile 链接,你会看到类似以下的内容:spring-doc.cadn.net.cn

{
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/profile"
    },
    "persons" : {
      "href" : "http://localhost:8080/profile/persons"
    },
    "addresses" : {
      "href" : "http://localhost:8080/profile/addresses"
    }
  }
}
在根级别,profile 是一个单一链接,无法提供多个应用程序配置文件。 因此,您必须导航到 /profile 才能找到每个资源元数据的链接。

如果你导航到 /profile/persons 并查看 Person 资源的 profile 数据,你会看到类似以下示例的内容:spring-doc.cadn.net.cn

{
  "version" : "1.0",
  "descriptors" : [ {
    "id" : "person-representation", (1)
    "descriptors" : [ {
      "name" : "firstName",
      "type" : "SEMANTIC"
    }, {
      "name" : "lastName",
      "type" : "SEMANTIC"
    }, {
      "name" : "id",
      "type" : "SEMANTIC"
    }, {
      "name" : "address",
      "type" : "SAFE",
      "rt" : "http://localhost:8080/profile/addresses#address"
    } ]
  }, {
    "id" : "create-persons", (2)
    "name" : "persons", (3)
    "type" : "UNSAFE", (4)
    "rt" : "#person-representation" (5)
  }, {
    "id" : "get-persons",
    "name" : "persons",
    "type" : "SAFE",
    "rt" : "#person-representation"
  }, {
    "id" : "delete-person",
    "name" : "person",
    "type" : "IDEMPOTENT",
    "rt" : "#person-representation"
  }, {
    "id" : "patch-person",
    "name" : "person",
    "type" : "UNSAFE",
    "rt" : "#person-representation"
  }, {
    "id" : "update-person",
    "name" : "person",
    "type" : "IDEMPOTENT",
    "rt" : "#person-representation"
  }, {
    "id" : "get-person",
    "name" : "person",
    "type" : "SAFE",
    "rt" : "#person-representation"
  } ]
}
1 一个详细的 Person 资源属性列表,标识为 #person-representation,列出了各属性的名称。
2 支持的操作。此处说明如何创建一个新的Person
3 namepersons,这表明(因为它是复数形式)应将 POST 请求应用于整个集合,而不是单个 person
4 typeUNSAFE,因为此操作可能会改变系统的状态。
5 rt#person-representation,表示返回的资源类型将是 Person 资源。
此 JSON 文档的媒体类型为 application/alps+json。这与之前的 JSON 文档不同,后者具有 媒体类型 application/hal+json。这些格式彼此不同,并遵循不同的规范。

当你查看一个集合资源时,也可以在 profile 集合中找到一个 _links 链接,如下例所示:spring-doc.cadn.net.cn

{
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/persons" (1)
    },
    ... other links ...
    "profile" : {
      "href" : "http://localhost:8080/profile/persons" (2)
    }
  },
  ...
}
1 此 HAL 文档表示 Person 集合。
2 它有一个指向相同 URI 的profile链接,用于元数据。

同样,默认情况下,profile 链接提供 ALPS。但是,如果您使用 Accept 标头,它可以提供 application/alps+jsonspring-doc.cadn.net.cn

超媒体控制类型

ALPS 为每个超媒体控件显示类型。它们包括:spring-doc.cadn.net.cn

表1. ALPS 类型
类型 描述

语义spring-doc.cadn.net.cn

一个状态元素(例如 HTML.SPANHTML.INPUT 等)。spring-doc.cadn.net.cn

安全spring-doc.cadn.net.cn

一种超媒体控件,用于触发安全且幂等的状态转换(例如 GETHEAD)。spring-doc.cadn.net.cn

幂等spring-doc.cadn.net.cn

一种超媒体控件,用于触发不安全但幂等的状态转换(例如 PUTDELETE)。spring-doc.cadn.net.cn

不安全spring-doc.cadn.net.cn

一种超媒体控件,用于触发不安全且非幂等的状态转换(例如 POST)。spring-doc.cadn.net.cn

在前面所示的表示部分中,来自应用程序的数据片段被标记为 SEMANTICaddress 字段是一个链接,涉及通过安全的 GET 请求进行检索。因此,它被标记为 SAFE。超媒体操作本身则按照上表所示映射到相应的类型。spring-doc.cadn.net.cn

带有投影的 ALPS

如果你定义了任何投影(projections),它们也会列在 ALPS 元数据中。假设我们还定义了 inlineAddressnoAddresses, 它们将出现在相关操作内部。(关于这两个投影的定义和讨论,请参见“Projections”一节。)也就是说,GET 将出现在整个集合的操作中,而 GET 也会出现在单个资源的操作中。以下示例展示了 get-persons 子章节的替代版本:spring-doc.cadn.net.cn

...
  {
    "id" : "get-persons",
    "name" : "persons",
    "type" : "SAFE",
    "rt" : "#person-representation",
    "descriptors" : [ { (1)
      "name" : "projection",
      "doc" : {
        "value" : "The projection that shall be applied when rendering the response. Acceptable values available in nested descriptors.",
        "format" : "TEXT"
      },
      "type" : "SEMANTIC",
      "descriptors" : [ {
        "name" : "inlineAddress", (2)
        "type" : "SEMANTIC",
        "descriptors" : [ {
          "name" : "address",
          "type" : "SEMANTIC"
        }, {
          "name" : "firstName",
          "type" : "SEMANTIC"
        }, {
          "name" : "lastName",
          "type" : "SEMANTIC"
        } ]
      }, {
        "name" : "noAddresses", (3)
        "type" : "SEMANTIC",
        "descriptors" : [ {
          "name" : "firstName",
          "type" : "SEMANTIC"
        }, {
          "name" : "lastName",
          "type" : "SEMANTIC"
        } ]
      } ]
    } ]
  }
...
1 出现了一个新属性 descriptors,其中包含一个数组,该数组有一个条目 projection
2 projection.descriptors 中,我们可以看到 inLineAddress。它会渲染 addressfirstNamelastName。 在投影中渲染的关系会导致将数据字段内联包含。
3 noAddresses 提供一个仅包含 firstNamelastName 的子集。

有了所有这些信息,客户端不仅可以推断出可用的 RESTful 转换,而且在某种程度上还能推断出与后端交互所需的数据元素。spring-doc.cadn.net.cn

向您的 ALPS 描述添加自定义详情

您可以创建自定义消息,这些消息将显示在您的 ALPS 元数据中。为此,请创建 rest-messages.properties 文件,如下所示:spring-doc.cadn.net.cn

rest.description.person=A collection of people
rest.description.person.id=primary key used internally to store a person (not for RESTful usage)
rest.description.person.firstName=Person's first name
rest.description.person.lastName=Person's last name
rest.description.person.address=Person's address

这些 rest.description.* 属性定义了用于显示 Person 资源的详细信息。它们会按如下方式修改 person-representation 的 ALPS 格式:spring-doc.cadn.net.cn

...
  {
    "id" : "person-representation",
    "doc" : {
      "value" : "A collection of people", (1)
      "format" : "TEXT"
    },
    "descriptors" : [ {
      "name" : "firstName",
      "doc" : {
        "value" : "Person's first name", (2)
        "format" : "TEXT"
      },
      "type" : "SEMANTIC"
    }, {
      "name" : "lastName",
      "doc" : {
        "value" : "Person's last name", (3)
        "format" : "TEXT"
      },
      "type" : "SEMANTIC"
    }, {
      "name" : "id",
      "doc" : {
        "value" : "primary key used internally to store a person (not for RESTful usage)", (4)
        "format" : "TEXT"
      },
      "type" : "SEMANTIC"
    }, {
      "name" : "address",
      "doc" : {
        "value" : "Person's address", (5)
        "format" : "TEXT"
      },
      "type" : "SAFE",
      "rt" : "http://localhost:8080/profile/addresses#address"
    } ]
  }
...
1 rest.description.person 的值映射到整个表示中。
2 rest.description.person.firstName 的值映射到 firstName 属性。
3 rest.description.person.lastName 的值映射到 lastName 属性。
4 rest.description.person.id 的值映射到 id 属性,该字段通常不会显示。
5 rest.description.person.address 的值映射到 address 属性。

提供这些属性设置将使每个字段都具有一个额外的 doc 属性。spring-doc.cadn.net.cn

Spring MVC(它是 Spring Data REST 应用程序的核心)支持本地化,这意味着你可以将包含不同消息的多个属性文件打包在一起。

JSON Schema

JSON Schema 是 Spring Data REST 支持的另一种元数据形式。根据其官网介绍,JSON Schema 具有以下优势:spring-doc.cadn.net.cn

上一节所示,您可以通过从根 URI 导航到 profile 链接来访问这些数据。spring-doc.cadn.net.cn

{
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/profile"
    },
    "persons" : {
      "href" : "http://localhost:8080/profile/persons"
    },
    "addresses" : {
      "href" : "http://localhost:8080/profile/addresses"
    }
  }
}

这些链接与之前展示的相同。要获取 JSON Schema,您可以使用以下 Accept 请求头进行调用:application/schema+jsonspring-doc.cadn.net.cn

在这种情况下,如果你运行 curl -H 'Accept:application/schema+json' localhost:8080/profile/persons,你将看到类似如下的输出:spring-doc.cadn.net.cn

{
  "title" : "org.springframework.data.rest.webmvc.jpa.Person", (1)
  "properties" : { (2)
    "firstName" : {
      "readOnly" : false,
      "type" : "string"
    },
    "lastName" : {
      "readOnly" : false,
      "type" : "string"
    },
    "siblings" : {
      "readOnly" : false,
      "type" : "string",
      "format" : "uri"
    },
    "created" : {
      "readOnly" : false,
      "type" : "string",
      "format" : "date-time"
    },
    "father" : {
      "readOnly" : false,
      "type" : "string",
      "format" : "uri"
    },
    "weight" : {
      "readOnly" : false,
      "type" : "integer"
    },
    "height" : {
      "readOnly" : false,
      "type" : "integer"
    }
  },
  "descriptors" : { },
  "type" : "object",
  "$schema" : "https://json-schema.org/draft-04/schema#"
}
1 导出的类型
2 属性列表

如果你的资源包含指向其他资源的链接,那么还有更多细节需要考虑。spring-doc.cadn.net.cn

当你查看一个集合资源时,也可以在 profile 集合中找到一个 _links 链接,如下例所示:spring-doc.cadn.net.cn

{
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/persons" (1)
    },
    ... other links ...
    "profile" : {
      "href" : "http://localhost:8080/profile/persons" (2)
    }
  },
  ...
}
1 此 HAL 文档表示 Person 集合。
2 它有一个指向相同 URI 的profile链接,用于元数据。

再次说明,profile 链接默认服务于 ALPS。如果您为其提供 Accept 头部application/schema+json,它将呈现 JSON Schema 表示形式。spring-doc.cadn.net.cn