Spring Data Rest 是运行在 Spring Data 之上的一套框架,能够非常方便的将 Spring Data 中的 Repository 映射成 REST 接口。其中有一些基本概念看起来有些陌生,在这里做出一些整理。
协议规范 HATEOAS 与数据格式 HAL
Spring Data Rest 采用了 HATEOAS(Hypermedia as the Engine of Application State)协议规范。HATEOAS 是一套 REST 接口的约束准则,它规定了访问数据的接口命名规范和返回数据应该包含的内容。
HAL(Hypertext Application Language)则规定了数据交换的格式,它规定了诸如 General Resource(对应数据库一个单一实体对象)、Embedded Resource(可以用于嵌入数据库外键关联的实体对象)和 Collection(对应数据库的一个实体集合)等形式,为编写通用库提供了标准。
HATEOAS 与 HAL 相辅相成,HATEOAS 规定了程序应该如何”动态”转换,HAL 规定了程序如何”静态”显示。
样例说明
HAL 非常重要的两个概念是 Resource(资源)和 Link(链接)。Resource 就是我们想要获得的数据的内容,而 Link 则是获取特定数据的索引。
对于初次接触类似 REST 体系的人来说,可能最大的一道障碍就来自于对这两个概念的陌生。来自于 Wikipedia 的这段样例,可以帮助进行理解。
{
"_links": {
"self": {
"href": "http://example.com/api/book/hal-cookbook"
}
},
"id": "hal-cookbook",
"name": "HAL Cookbook"
}
这段代码展示了获取一个实体对象的返回数据。先看第一层,有 id、name 与 _links 三个键。在 HAL 中,所有以 _ 开头的键都可以理解为这个协议规定的必须存在的内容。在具体的框架上,这些内容是由框架生成的。所以,_links 键是这个协议的要求字段。从里层对象的键名不难猜出,_links.self.href 存储的,就是这个实体对象本身的 link。通过访问这个 link,可以得到现在呈现的这个数据,也就是 resource。id 和 name 是用户自己的数据,按照惯例,id 往往对应着数据库的主键。当然,主键可以是任意名字。
{
"_links": {
"self": {
"href": "http://example.com/api/book/hal-cookbook"
}
},
"_embedded": {
"author": {
"_links": {
"self": {
"href": "http://author-example.com"
}
},
"id": "shahadat",
"name": "Shahadat Hossain Khan"
}
},
"id": "hal-cookbook",
"name": "HAL Cookbook"
}
第二段代码展示了 Embedded Resource 的格式。与第一组不同的是,多了一个 _embedded 字段,里面负载了 author 这个数据。书和作者往往是一个外键的关系,这个代码就展示了外键会怎样被显示。事实上,在 Spring Data Rest 里面,外键默认只会展示对应对象的 link,而不会显示完整的数据,这种情况下只会在 _links 中多出一个 author 字段处在与 _links.self 平级的位置。如果想要一同返回完整的数据,数据的内容就会嵌入在 _embedded 里面。
{
"_links": {
"self": {
"href": "http://example.com/api/book/hal-cookbook"
},
"next": {
"href": "http://example.com/api/book/hal-case-study"
},
"prev": {
"href": "http://example.com/api/book/json-and-beyond"
},
"first": {
"href": "http://example.com/api/book/catalog"
},
"last": {
"href": "http://example.com/api/book/upcoming-books"
}
},
"_embedded": {
"author": {
"_links": {
"self": {
"href": "http://author-example.com"
}
},
"id": "shahadat",
"name": "Shahadat Hossain Khan"
}
},
"id": "hal-cookbook",
"name": "HAL Cookbook"
}
第三段代码展示了带导航链接的集合资源。所谓导航链接,可以想象成数据库分页时候,前一页、后一页与第一页、最后一页的功能。对于 Spring Data Rest,还会有包含页码页号每页记录数的 page 信息,帮助实现更加完备的分页功能。