Spring中的REST分頁
本文將介紹在REST API中實現分頁的基礎知識。我們將專注於使用Spring Boot和Spring Data 在Spring MVC中構建REST分頁。
分頁是一種處理大結果資料集的機制。在REST API中實現分頁並沒有什麼不同,但需要一些額外的思考過程。為REST API提供流暢有效的分頁可以增加使用者體驗並有助於構建高效,快速的REST API。我們使用Spring Boot作為示例。
1.資源與表示
在我們開始設計分頁API之前,我們需要清楚地瞭解頁面作為資源或資源的表示。我們需要記住許多基本要素
一個頁面Page不是REST中的一個資源,而是其請求的屬性。
以資源名稱Product為構建分頁的例子,在高層次上我們確實有以下三個選項來構建分頁。
- 將產品Product作為資源並使用查詢字串來處理分頁以及其他引數,例如排序等(例如http://domainname/products?page=1)。
- 第二個選項是將頁面Page用作資源和查詢字串進行排序。(例如http://domainname/products/page/1?sort_by=date)。
- 使用頁面Page作為資源和URL部分進行排序。(例如http://domainname/products/date/page/1)
考慮到上述問題,讓我們嘗試回答一些在設計REST API分頁時有用的問題。
- 您是否將頁面Page視為頁面中產品的資源?
請記住,REST API不是圍繞任何預定義的規則或規範構建的,所有上述三個選項都是有效的,並且基於上述問題的答案。如果我們將頁面視為資源,則選項3是有效選擇;但如果我們說頁面上的產品是資源,那麼選項3不再有效(在第1,2頁上的產品可能會在將來更改),就個人而言,我會選擇選項1,因為對我來說,頁面 Page 不是 資源Resouce,它是請求的屬性。
2.可發現性
可發現性 有助於使 RESTful API 更加實用和優雅。使REST API 可被發現經常被忽視。以下是REST API可發現性的高階摘要 。
- 有了這個功能,REST API在對客戶端的響應中提供完整的URI意味著沒有客戶端需要“組合”URI。
- 客戶端API獨立於URI結構。
- 透過以上2點,API更加靈活,允許開發人員在不破壞API的情況下更改URI架構。(請記住,API提供所有URI,它們不是由客戶端API動態建立的)。
可發現性與REST API中的HATEOAS密切相關。REST API分頁可發現將透過"next","previous","first"和"last"鏈路作為響應資料的一部分。我們正在考慮如何在分頁期間將此功能新增到您的API。
3.分頁設計考慮因素
在構建REST API分頁介面時,讓我們快速介紹一些要點。
3.1 限制limit
限制允許API和客戶端控制結果集中請求的結果數。透過傳遞 limit 引數,您可以指定每個頁面要返回的專案數.API可以配置預設限制,但應允許客戶端指定限制。
http://hostname/products?page=1&limit=50
在上面的請求中,客戶端將限制設定為50.小心,同時允許客戶將limit 引數設定 , 設定為極高數量的限制會降低API效能。建議在API設計期間具有最大允許限制。
3.1 排序
排序總是與搜尋和分頁並排。在設計REST API時,提供靈活性,讓客戶指定排序選項,同時從API返回結果。建議在設計API時使用 sort_by = [attribute name] - [asc / desc]模式.API設計器應將允許的屬性名稱指定為sort引數。例如,您可以使用?name-asc按產品名稱排序或?name-desc反向排序。
4. Maven依賴
我們在Spring中處理REST分頁時介紹了所有基本內容。我們在這篇文章中使用了以下技術堆疊,但它可以在任何其他技術上實現,前提是您在設計時遵循所有基本原則。
- Spring Boot
- JPA.
- Spring Data REST
在本文中使用Spring Data REST的原因之一是Data REST API支援的開箱即用功能。
我們將在pom.xml中新增以下依賴項
- Spring Boot JPA
- Spring Boot Data REST
- HATEOS和Web
<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 + "\""; } } |
讓我們快速介紹上面程式碼中的幾個要點。
- 我們使用 Pageable作為控制器的引數之一。這將有助於返回頁面而不是列表。
- Pageable具有所有必需的分頁資訊。
- Pageable在Spring JPA中執行得非常好,並且透明地處理分頁。
4.2 Previous 和Next 連結
每個頁面響應將返回連結到當前頁面前面和後面的頁,這是基於使用IANA定義連結關係 prev 和 next。但是,如果您當前位於結果的第一頁,則不會呈現任何 prev連結。
我們來看下面的例子:
curl http://localhost:8080/products
{ "_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 } } |
讓我們深入瞭解響應資料中的一些有趣事實
- next 連結指向下一頁。last 連結指向的最後一個結果集。
- self 連結提供整個系列。
- 底部 page 提供有關分頁的資訊,包括頁面大小,總結果,總頁數和當前頁碼。
4.2使用連結頭
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標頭的重要性。
所有這些示例和程式碼片段的實現都可以在GitHub專案中找到
相關文章
- REST framework:分頁RESTFramework
- Django REST framework 分頁DjangoRESTFramework
- Django REST framework API 指南(17):分頁DjangoRESTFrameworkAPI
- Spring JPA 分頁Spring
- [Django REST framework - 自動生成介面文件、分頁]DjangoRESTFramework
- Spring專案處理分頁(邏輯和物理分頁)Spring
- Spring 指南(瞭解REST)SpringREST
- rest_framework之分頁器RESTFramework
- SpringMVC+Spring Data JPA +Bootstrap 分頁實現和模糊查詢分頁SpringMVCboot
- Spring Data JPA REST Query CriteriaSpringREST
- django-rest-framework 基礎四 過濾、排序、分頁、異常處理DjangoRESTFramework排序
- Spring boot方式使用MyBatis-Plus分頁操作Spring BootMyBatis
- PHP中物件導向的分頁類PHP物件
- 29.Spring Boot中異常處理與REST格式處理Spring BootREST
- Django REST Framework中的Serializer relationsDjangoRESTFramework
- PageHelper 分頁外掛使用中的那些“坑”
- Oracle資料庫中的分頁查詢Oracle資料庫
- Django的分頁Django
- Spring MVCD框架中呼叫HanLP分詞的方法SpringMVC框架HanLP分詞
- 使用JBang構建Spring Boot Rest API教程Spring BootRESTAPI
- mysql分頁-limit offset分頁MySqlMIT
- Spring統一返回Json工具類,帶分頁資訊SpringJSON
- Spring Boot原始碼:使用MongoDB MongoTemplate公開REST在幾分鐘內實現CRUD功能Spring Boot原始碼MongoDBREST
- [譯] Spring REST API 與 OAuth2:處理 AngularJS 中的 Token 重新整理問題SpringRESTAPIOAuthAngularJS
- MongoDB 的分頁(Pagination)MongoDB
- ssh的分頁操作
- Oracle的特性分頁Oracle
- jstl 寫的分頁JS
- Spring Boot入門系列(十六)使用pagehelper實現分頁功能Spring Boot
- Spring Cloud Netflix—宣告性REST客戶端:FeignSpringCloudREST客戶端
- 3、Spring Cloud Rest工程建立(通過IDEA建立)SpringCloudRESTIdea
- 分庫分表後的分頁查詢
- flask 分頁 | 翻頁Flask
- 如何使用Spring Boot,Spring Data和H2 DB實現REST APISpring BootRESTAPI
- Spring Boot使用過濾器和攔截器分別實現REST介面簡易安全認證Spring Boot過濾器REST
- spring boot(二)整合mybatis plus+ 分頁外掛 + 程式碼生成Spring BootMyBatis
- Spring Boot 參考指南(使用RestTemplate呼叫REST服務)Spring BootREST
- asyUI分頁中,如何實現頁面跳轉,再返回時,...UI