←←←←←←←←←←←← 快!点关注程序员
本文将介绍在REST API中实现分页的基础知识。咱们将专一于使用Spring Boot和Spring Data 在Spring MVC中构建REST分页。web
分页是一种处理大结果数据集的机制。在REST API中实现分页并无什么不一样,但须要一些额外的思考过程。为REST API提供流畅有效的分页能够增长用户体验并有助于构建高效,快速的REST API。咱们使用Spring Boot做为示例。spring
在咱们开始设计分页API以前,咱们须要清楚地了解页面做为资源或资源的表示。咱们须要记住许多基本要素sql
一个页面Page不是REST中的一个资源,而是其请求的属性。数据库
以资源名称Product为构建分页的例子,在高层次上咱们确实有如下三个选项来构建分页。缓存
考虑到上述问题,让咱们尝试回答一些在设计REST API分页时有用的问题。bash
请记住,REST API不是围绕任何预约义的规则或规范构建的,全部上述三个选项都是有效的,而且基于上述问题的答案。若是咱们将页面视为资源,则选项3是有效选择;但若是咱们说页面上的产品是资源,那么选项3再也不有效(在第1,2页上的产品可能会在未来更改),就我的而言,我会选择选项1,由于对我来讲,页面 Page 不是 资源Resouce,它是请求的属性。架构
可发现性 有助于使 RESTful API 更加实用和优雅。使REST API 可被发现常常被忽视。如下是REST API可发现性的高级摘要 。app
可发现性与REST API中的HATEOAS密切相关。REST API分页可发现将经过"next","previous","first"和"last"链路做为响应数据的一部分。咱们正在考虑如何在分页期间将此功能添加到您的API。框架
在构建REST API分页界面时,让咱们快速介绍一些要点。
3.1 限制limit
限制容许API和客户端控制结果集中请求的结果数。经过传递 limit 参数,您能够指定每一个页面要返回的项目数.API能够配置默认限制,但应容许客户端指定限制。
在上面的请求中,客户端将限制设置为50.当心,同时容许客户将limit 参数设置 , 设置为极高数量的限制会下降API性能。建议在API设计期间具备最大容许限制。
3.2排序
排序老是与搜索和分页并排。在设计REST API时,提供灵活性,让客户指定排序选项,同时从API返回结果。建议在设计API时使用 sort_by = [attribute name] - [asc / desc]模式.API设计器应将容许的属性名称指定为sort参数。例如,您可使用?name-asc按产品名称排序或?name-desc反向排序。
咱们在Spring中处理REST分页时介绍了全部基本内容。咱们在这篇文章中使用了如下技术堆栈,但它能够在任何其余技术上实现,前提是您在设计时遵循全部基本原则。
在本文中使用Spring Data REST的缘由之一是Data REST API支持的开箱即用功能。
咱们将在pom.xml中添加如下依赖项
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-hateoas</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
复制代码
4.1 REST控制器:
@RestController
public class ProductRESTController {
@Autowired
private ProductService productService;
@Autowired private EntityLinks links;
@GetMapping(value = "/products", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity < PagedResources < ProductEntity >> AllProducts(Pageable pageable, PagedResourcesAssembler assembler) {
Page < ProductEntity > products = productService.findAllProducts(pageable);
PagedResources < ProductEntity > pr = assembler.toResource(products, linkTo(ProductRESTController.class).slash("/products").withSelfRel());
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.add("Link", createLinkHeader(pr));
return new ResponseEntity < > (assembler.toResource(products, linkTo(ProductRESTController.class).slash("/products").withSelfRel()), responseHeaders, HttpStatus.OK);
}
private String createLinkHeader(PagedResources < ProductEntity > pr) {
final StringBuilder linkHeader = new StringBuilder();
linkHeader.append(buildLinkHeader(pr.getLinks("first").get(0).getHref(), "first"));
linkHeader.append(", ");
linkHeader.append(buildLinkHeader(pr.getLinks("next").get(0).getHref(), "next"));
return linkHeader.toString();
}
public static String buildLinkHeader(final String uri, final String rel) {
return "<" + uri + ">; rel=\"" + rel + "\"";
}
}
复制代码
让咱们快速介绍上面代码中的几个要点。
4.2 Previous 和Next 连接
每一个页面响应将返回连接到当前页面前面和后面的页,这是基于使用IANA定义连接关系 prev 和 next。可是,若是您当前位于结果的第一页,则不会呈现任何 prev连接。
咱们来看下面的例子:
{
"_embedded": {
"productEntities": [
...data...
]
},
"_links": {
"first": {
"href": "http://localhost:8080/products?page=0&size=20"
},
"self": {
"href": "http://localhost:8080/products"
},
"next": {
"href": "http://localhost:8080/products?page=1&size=20"
},
"last": {
"href": "http://localhost:8080/products?page=4&size=20"
}
},
"page": {
"size": 20,
"totalElements": 100,
"totalPages": 5,
"number": 0
}
}
复制代码
让咱们深刻了解响应数据中的一些有趣事实
4.3使用连接头
HTTP标头是REST API的关键方面.HTTP连接标头还可用于将分页信息传递给客户端。经过上述测试,系统将返回如下附加信息做为Link HTTP标头的一部分。
Link →<http://localhost:8080/products?page=0&size=20>; rel="first", <http://localhost:8080/products?page=1&size=20>; rel="next"
复制代码
rel="next" 意思是下一页是 page=2;rel="first" 意思是第一页老是依赖page=2.于提供给你的这些连接关系。不要试图猜想或构建本身的URL。Spring PagedResource提供全部这些信息做为结果的一部分,咱们只须要确保从这些信息中构建正确的HTTP头。在咱们的控制器示例中,咱们在createLinkHeader方法中构建标头。
private String createLinkHeader(PagedResources < ProductEntity > pr) {
final StringBuilder linkHeader = new StringBuilder();
linkHeader.append(buildLinkHeader(pr.getLinks("first").get(0).getHref(), "first"));
linkHeader.append(", ");
linkHeader.append(buildLinkHeader(pr.getLinks("next").get(0).getHref(), "next"));
return linkHeader.toString();
}
public static String buildLinkHeader(final String uri, final String rel) {
return "<" + uri + ">; rel=\"" + rel + "\"";
}
复制代码
在这篇文章中,咱们学习了如何在Spring和Spring Boot中实现 REST分页。咱们讨论了如何构建响应以及在REST API响应中使用连接HTTP标头的重要性。
欢迎你们加入粉丝群:963944895,群内免费分享Spring框架、Mybatis框架SpringBoot框架、SpringMVC框架、SpringCloud微服务、Dubbo框架、Redis缓存、RabbitMq消息、JVM调优、Tomcat容器、MySQL数据库教学视频及架构学习思惟导图
秃顶程序员的不易,看到这里,点了关注吧!点关注,不迷路,持续更新!!!