←←←←←←←←←←←← 快!點關注程序員
本文將介紹在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數據庫教學視頻及架構學習思惟導圖
禿頂程序員的不易,看到這裏,點了關注吧!點關注,不迷路,持續更新!!!