Spring中的REST分頁的實(shí)現(xiàn)代碼
本文將介紹在REST API中實(shí)現(xiàn)分頁的基礎(chǔ)知識。我們將專注于使用Spring Boot和Spring Data 在Spring MVC中構(gòu)建REST分頁。
分頁是一種處理大結(jié)果數(shù)據(jù)集的機(jī)制。在REST API中實(shí)現(xiàn)分頁并沒有什么不同,但需要一些額外的思考過程。為REST API提供流暢有效的分頁可以增加用戶體驗(yàn)并有助于構(gòu)建高效,快速的REST API。我們使用Spring Boot作為示例。
1.資源與表示
在我們開始設(shè)計(jì)分頁API之前,我們需要清楚地了解頁面作為資源或資源的表示。我們需要記住許多基本要素
一個頁面Page不是REST中的一個資源,而是其請求的屬性。
以資源名稱Product為構(gòu)建分頁的例子,在高層次上我們確實(shí)有以下三個選項(xiàng)來構(gòu)建分頁。
- 將產(chǎn)品Product作為資源并使用查詢字符串來處理分頁以及其他參數(shù),例如排序等(例如http://domainname/products?page=1)。
- 第二個選項(xiàng)是將頁面Page用作資源和查詢字符串進(jìn)行排序。(例如http://domainname/products/page/1?sort_by=date)。
- 使用頁面Page作為資源和URL部分進(jìn)行排序。(例如http://domainname/products/date/page/1)
考慮到上述問題,讓我們嘗試回答一些在設(shè)計(jì)REST API分頁時(shí)有用的問題。
- 您是否將頁面Page視為頁面中產(chǎn)品的資源?
請記住,REST API不是圍繞任何預(yù)定義的規(guī)則或規(guī)范構(gòu)建的,所有上述三個選項(xiàng)都是有效的,并且基于上述問題的答案。如果我們將頁面視為資源,則選項(xiàng)3是有效選擇;但如果我們說頁面上的產(chǎn)品是資源,那么選項(xiàng)3不再有效(在第1,2頁上的產(chǎn)品可能會在將來更改),就個人而言,我會選擇選項(xiàng)1,因?yàn)閷ξ襾碚f,頁面 Page 不是 資源Resouce,它是請求的屬性。
2.可發(fā)現(xiàn)性
可發(fā)現(xiàn)性 有助于使 RESTful API 更加實(shí)用和優(yōu)雅。使REST API 可被發(fā)現(xiàn)經(jīng)常被忽視。以下是REST API可發(fā)現(xiàn)性的高級摘要 。
- 有了這個功能,REST API在對客戶端的響應(yīng)中提供完整的URI意味著沒有客戶端需要“組合”URI。
- 客戶端API獨(dú)立于URI結(jié)構(gòu)。
- 通過以上2點(diǎn),API更加靈活,允許開發(fā)人員在不破壞API的情況下更改URI架構(gòu)。(請記住,API提供所有URI,它們不是由客戶端API動態(tài)創(chuàng)建的)。
可發(fā)現(xiàn)性與REST API中的HATEOAS密切相關(guān)。REST API分頁可發(fā)現(xiàn)將通過"next","previous","first"和"last"鏈路作為響應(yīng)數(shù)據(jù)的一部分。我們正在考慮如何在分頁期間將此功能添加到您的API。
3.分頁設(shè)計(jì)考慮因素
在構(gòu)建REST API分頁界面時(shí),讓我們快速介紹一些要點(diǎn)。
3.1 限制limit
限制允許API和客戶端控制結(jié)果集中請求的結(jié)果數(shù)。通過傳遞 limit 參數(shù),您可以指定每個頁面要返回的項(xiàng)目數(shù).API可以配置默認(rèn)限制,但應(yīng)允許客戶端指定限制。
http://hostname/products?page=1&limit=50
在上面的請求中,客戶端將限制設(shè)置為50.小心,同時(shí)允許客戶將limit 參數(shù)設(shè)置 , 設(shè)置為極高數(shù)量的限制會降低API性能。建議在API設(shè)計(jì)期間具有最大允許限制。
3.2 排序
排序總是與搜索和分頁并排。在設(shè)計(jì)REST API時(shí),提供靈活性,讓客戶指定排序選項(xiàng),同時(shí)從API返回結(jié)果。建議在設(shè)計(jì)API時(shí)使用 sort_by = [attribute name] - [asc / desc]模式.API設(shè)計(jì)器應(yīng)將允許的屬性名稱指定為sort參數(shù)。例如,您可以使用?name-asc按產(chǎn)品名稱排序或?name-desc反向排序。
4. Maven依賴
我們在Spring中處理REST分頁時(shí)介紹了所有基本內(nèi)容。我們在這篇文章中使用了以下技術(shù)堆棧,但它可以在任何其他技術(shù)上實(shí)現(xiàn),前提是您在設(shè)計(jì)時(shí)遵循所有基本原則。
- Spring Boot
- JPA.
- Spring Data REST
在本文中使用Spring Data REST的原因之一是Data REST API支持的開箱即用功能。
我們將在pom.xml中添加以下依賴項(xiàng)
- 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 + "\""; } }
讓我們快速介紹上面代碼中的幾個要點(diǎn)。
- 我們使用 Pageable作為控制器的參數(shù)之一。這將有助于返回頁面而不是列表。
- Pageable具有所有必需的分頁信息。
- Pageable在Spring JPA中運(yùn)行得非常好,并且透明地處理分頁。
4.2 Previous 和Next 鏈接
每個頁面響應(yīng)將返回鏈接到當(dāng)前頁面前面和后面的頁,這是基于使用IANA定義鏈接關(guān)系 prev 和 next。但是,如果您當(dāng)前位于結(jié)果的第一頁,則不會呈現(xiàn)任何 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 } }
讓我們深入了解響應(yīng)數(shù)據(jù)中的一些有趣事實(shí)
- next 鏈接指向下一頁。last 鏈接指向的最后一個結(jié)果集。
- self 鏈接提供整個系列。
- 底部 page 提供有關(guān)分頁的信息,包括頁面大小,總結(jié)果,總頁數(shù)和當(dāng)前頁碼。
4.2使用鏈接頭
HTTP標(biāo)頭是REST API的關(guān)鍵方面.HTTP鏈接標(biāo)頭還可用于將分頁信息傳遞給客戶端。通過上述測試,系統(tǒng)將返回以下附加信息作為Link HTTP標(biāo)頭的一部分。
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.于提供給你的這些鏈接關(guān)系。不要試圖猜測或構(gòu)建自己的URL。Spring PagedResource提供所有這些信息作為結(jié)果的一部分,我們只需要確保從這些信息中構(gòu)建正確的HTTP頭。在我們的控制器示例中,我們在createLinkHeader方法中構(gòu)建標(biāo)頭。
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 + "\""; }
總結(jié)
在這篇文章中,我們學(xué)習(xí)了如何在Spring和Spring Boot中實(shí)現(xiàn) REST分頁。我們討論了如何構(gòu)建響應(yīng)以及在REST API響應(yīng)中使用鏈接HTTP標(biāo)頭的重要性。
所有這些示例和代碼片段的實(shí)現(xiàn)都可以在GitHub項(xiàng)目中找到
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Java簡單實(shí)現(xiàn)SpringMVC+MyBatis分頁插件
- SpringMvc+Mybatis+Pagehelper分頁詳解
- springmvc 分頁查詢的簡單實(shí)現(xiàn)示例代碼
- Spring Data JPA 復(fù)雜/多條件組合分頁查詢
- spring data jpa分頁查詢示例代碼
- spring boot和mybatis集成分頁插件
- bootstrap-table實(shí)現(xiàn)服務(wù)器分頁的示例 (spring 后臺)
- 在Spring Boot中使用Spring-data-jpa實(shí)現(xiàn)分頁查詢
- Spring MVC結(jié)合Spring Data JPA實(shí)現(xiàn)按條件查詢和分頁
相關(guān)文章
解決SpringBoot項(xiàng)目在啟動后自動關(guān)閉的問題
今天搭建了一個SpringBoot項(xiàng)目,但是在啟動之后就自行關(guān)閉了,下面通過本文給大家介紹SpringBoot項(xiàng)目在啟動后自動關(guān)閉問題及解決方法,需要的朋友可以參考下2023-08-08Spring Boot @Conditional注解用法示例介紹
這篇文章主要給大家介紹了關(guān)于Spring Boot @Conditional注解用法的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Spring Boot具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11Log4j2?重大漏洞編譯好的log4j-2.15.0.jar包下載(替換過程)
Apache?開源項(xiàng)目?Log4j?的遠(yuǎn)程代碼執(zhí)行漏洞細(xì)節(jié)被公開,由于?Log4j?的廣泛使用,該漏洞一旦被攻擊者利用會造成嚴(yán)重危害,下面小編給大家?guī)砹薒og4j2?重大漏洞編譯好的log4j-2.15.0.jar包下載,感興趣的朋友一起看看吧2021-12-12SpringBoot集成Shiro進(jìn)行權(quán)限控制和管理的示例
這篇文章主要介紹了SpringBoot集成Shiro進(jìn)行權(quán)限控制和管理的示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-03-03java.sql.SQLTimeoutException異常的正確解決方法(親測有效!)
在我們編寫程序的時(shí)候,有時(shí)候要進(jìn)行復(fù)雜的查詢時(shí),就會出現(xiàn)執(zhí)行sql時(shí)間過長,引起頁面執(zhí)行不了并提示執(zhí)行腳本超時(shí),這就是我們遇到超時(shí)異常,這篇文章主要給大家介紹了關(guān)于java.sql.SQLTimeoutException異常的正確解決方法,需要的朋友可以參考下2024-02-02運(yùn)行Jar包出現(xiàn)提示xxx中沒有主清單屬性報(bào)錯問題解決方法
這篇文章主要介紹了運(yùn)行Jar包出現(xiàn):xxx中沒有主清單屬性報(bào)錯,當(dāng)出現(xiàn)報(bào)錯:xxx中沒有主清單屬性,解決方法也很簡單,在pom.xml配置中,加上相應(yīng)配置即可,需要的朋友可以參考下2023-08-08