分页和排序

本节介绍了 Spring Data REST 如何使用 Spring Data Repository 的分页和排序抽象。要熟悉这些特性,请参阅您使用的 repository 实现对应的 Spring Data 文档(例如 Spring Data JPA)。

分页

Spring Data REST 不会返回大型结果集中的所有内容,而是会识别一些影响页大小和起始页码的 URL 参数。

如果您扩展了 PagingAndSortingRepository<T, ID> 并访问所有实体的列表,您将获得指向前 20 个实体的链接。要将页大小设置为其他任何数字,请添加一个 size 参数,如下所示

http://localhost:8080/people/?size=5

前面的示例将页大小设置为 5。

要在您自己的查询方法中使用分页,您需要更改方法签名,使其接受额外的 Pageable 参数,并返回 PageSlice 而不是 List。例如,以下查询方法会导出到 /people/search/nameStartsWith 并支持分页

@RestResource(path = "nameStartsWith", rel = "nameStartsWith")
public Page findByNameStartsWith(@Param("name") String name, Pageable p);

Spring Data REST 导出器会识别返回的 Page/Slice 并在响应体中为您提供结果,就像它处理非分页响应一样,但会向资源添加额外的链接来表示数据的前一页和下一页。

每个分页响应都会使用 IANA 定义的链接关系 prevnext,基于当前页返回指向结果的前一页和下一页的链接。但是,如果您当前位于第一页结果,则不会渲染 prev 链接。对于最后一页结果,则不会渲染 next 链接。

考虑以下示例,我们将页大小设置为 5

curl localhost:8080/people?size=5
{
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/persons{&sort,page,size}", (1)
      "templated" : true
    },
    "next" : {
      "href" : "http://localhost:8080/persons?page=1&size=5{&sort}", (2)
      "templated" : true
    }
  },
  "_embedded" : {
  	… data …
  },
  "page" : { (3)
    "size" : 5,
    "totalElements" : 50,
    "totalPages" : 10,
    "number" : 0
  }
}

在顶部,我们看到 _links

1 self 链接提供了包含一些选项的完整集合。
2 next 链接指向下一页,假设页大小相同。
3 底部是关于页设置的额外数据,包括页大小、总元素数、总页数以及您当前正在查看的页码。
在命令行上使用 curl 等工具时,如果您的语句中包含与号 (&),则需要将整个 URI 用引号括起来。

请注意,selfnext URI 实际上是 URI 模板。它们不仅接受 size,还接受 pagesort 作为可选标志。

如前所述,HAL 文档的底部包含关于页的一系列详细信息。这些额外信息使您可以轻松配置滑块或指示器等 UI 工具,以反映用户查看数据时的整体位置。例如,前面示例中的文档显示我们正在查看第一页(页码从 0 开始)。

以下示例显示了我们跟随 next 链接时发生的情况

$ curl "http://localhost:8080/persons?page=1&size=5"
{
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/persons{&sort,projection,page,size}",
      "templated" : true
    },
    "next" : {
      "href" : "http://localhost:8080/persons?page=2&size=5{&sort,projection}", (1)
      "templated" : true
    },
    "prev" : {
      "href" : "http://localhost:8080/persons?page=0&size=5{&sort,projection}", (2)
      "templated" : true
    }
  },
  "_embedded" : {
	... data ...
  },
  "page" : {
    "size" : 5,
    "totalElements" : 50,
    "totalPages" : 10,
    "number" : 1 (3)
  }
}

这看起来非常相似,除了以下几点不同

1 next 链接现在指向另一页,表示它相对于 self 链接的视角。
2 现在出现一个 prev 链接,为我们提供了回到上一页的路径。
3 当前页码现在是 1(表示第二页)。

此功能允许您将屏幕上的可选按钮映射到这些超媒体控件,使您无需硬编码 URI 即可实现 UI 体验的导航功能。事实上,用户可以从页大小列表中选择,动态更改提供的内容,而无需重写顶部或底部的 nextprev 控件。

排序

Spring Data REST 识别使用 repository 排序支持的排序参数。

要按特定属性对结果进行排序,请添加一个 sort URL 参数,其值为要排序的属性名称。您可以通过在属性名称后附加逗号 (,) 以及 ascdesc 来控制排序方向。以下示例将使用在 PersonRepository 上定义的 findByNameStartsWith 查询方法,针对所有名称以字母“K”开头的 Person 实体,并添加按 name 属性降序排列的排序数据。

curl -v "http://localhost:8080/people/search/nameStartsWith?name=K&sort=name,desc"

要按多个属性对结果进行排序,请根据需要添加任意数量的 sort=PROPERTY 参数。它们会按照在查询字符串中出现的顺序添加到 Pageable 中。结果可以按顶级属性和嵌套属性排序。使用属性路径表示法来表达嵌套排序属性。不支持按可链接关联(即指向顶级资源的链接)进行排序。