溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

如何在Spring中利用REST實(shí)現(xiàn)一個(gè)分頁(yè)功能

發(fā)布時(shí)間:2021-01-16 10:26:51 來(lái)源:億速云 閱讀:422 作者:Leah 欄目:編程語(yǔ)言

本篇文章給大家分享的是有關(guān)如何在Spring中利用REST實(shí)現(xiàn)一個(gè)分頁(yè)功能,小編覺(jué)得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話(huà)不多說(shuō),跟著小編一起來(lái)看看吧。

1.資源與表示

在我們開(kāi)始設(shè)計(jì)分頁(yè)API之前,我們需要清楚地了解頁(yè)面作為資源或資源的表示。我們需要記住許多基本要素

一個(gè)頁(yè)面Page不是REST中的一個(gè)資源,而是其請(qǐng)求的屬性。

以資源名稱(chēng)Product為構(gòu)建分頁(yè)的例子,在高層次上我們確實(shí)有以下三個(gè)選項(xiàng)來(lái)構(gòu)建分頁(yè)。

  • 將產(chǎn)品Product作為資源并使用查詢(xún)字符串來(lái)處理分頁(yè)以及其他參數(shù),例如排序等(例如http://domainname/products?page=1)。

  • 第二個(gè)選項(xiàng)是將頁(yè)面Page用作資源和查詢(xún)字符串進(jìn)行排序。(例如http://domainname/products/page/1?sort_by=date)。

  • 使用頁(yè)面Page作為資源和URL部分進(jìn)行排序。(例如http://domainname/products/date/page/1)

考慮到上述問(wèn)題,讓我們嘗試回答一些在設(shè)計(jì)REST API分頁(yè)時(shí)有用的問(wèn)題。

  • 您是否將頁(yè)面Page視為頁(yè)面中產(chǎn)品的資源?

請(qǐng)記住,REST API不是圍繞任何預(yù)定義的規(guī)則或規(guī)范構(gòu)建的,所有上述三個(gè)選項(xiàng)都是有效的,并且基于上述問(wèn)題的答案。如果我們將頁(yè)面視為資源,則選項(xiàng)3是有效選擇;但如果我們說(shuō)頁(yè)面上的產(chǎn)品是資源,那么選項(xiàng)3不再有效(在第1,2頁(yè)上的產(chǎn)品可能會(huì)在將來(lái)更改),就個(gè)人而言,我會(huì)選擇選項(xiàng)1,因?yàn)閷?duì)我來(lái)說(shuō),頁(yè)面 Page 不是  資源Resouce,它是請(qǐng)求的屬性。

2.可發(fā)現(xiàn)性

可發(fā)現(xiàn)性  有助于使  RESTful API  更加實(shí)用和優(yōu)雅。使REST API  可被發(fā)現(xiàn)經(jīng)常被忽視。以下是REST API可發(fā)現(xiàn)性的高級(jí)摘要 。

  • 有了這個(gè)功能,REST API在對(duì)客戶(hù)端的響應(yīng)中提供完整的URI意味著沒(méi)有客戶(hù)端需要“組合”URI。

  • 客戶(hù)端API獨(dú)立于URI結(jié)構(gòu)。

  • 通過(guò)以上2點(diǎn),API更加靈活,允許開(kāi)發(fā)人員在不破壞API的情況下更改URI架構(gòu)。(請(qǐng)記住,API提供所有URI,它們不是由客戶(hù)端API動(dòng)態(tài)創(chuàng)建的)。

可發(fā)現(xiàn)性與REST API中的HATEOAS密切相關(guān)。REST API分頁(yè)可發(fā)現(xiàn)將通過(guò)"next","previous","first"和"last"鏈路作為響應(yīng)數(shù)據(jù)的一部分。我們正在考慮如何在分頁(yè)期間將此功能添加到您的API。

3.分頁(yè)設(shè)計(jì)考慮因素

在構(gòu)建REST API分頁(yè)界面時(shí),讓我們快速介紹一些要點(diǎn)。

3.1 限制limit

限制允許API和客戶(hù)端控制結(jié)果集中請(qǐng)求的結(jié)果數(shù)。通過(guò)傳遞  limit 參數(shù),您可以指定每個(gè)頁(yè)面要返回的項(xiàng)目數(shù).API可以配置默認(rèn)限制,但應(yīng)允許客戶(hù)端指定限制。

http://hostname/products?page=1&limit=50

在上面的請(qǐng)求中,客戶(hù)端將限制設(shè)置為50.小心,同時(shí)允許客戶(hù)將limit 參數(shù)設(shè)置 , 設(shè)置為極高數(shù)量的限制會(huì)降低API性能。建議在API設(shè)計(jì)期間具有最大允許限制。

3.2 排序

排序總是與搜索和分頁(yè)并排。在設(shè)計(jì)REST API時(shí),提供靈活性,讓客戶(hù)指定排序選項(xiàng),同時(shí)從API返回結(jié)果。建議在設(shè)計(jì)API時(shí)使用  sort_by = [attribute  name] - [asc / desc]模式.API設(shè)計(jì)器應(yīng)將允許的屬性名稱(chēng)指定為sort參數(shù)。例如,您可以使用?name-asc按產(chǎn)品名稱(chēng)排序或?name-desc反向排序。

4. Maven依賴(lài)

我們?cè)赟pring中處理REST分頁(yè)時(shí)介紹了所有基本內(nèi)容。我們?cè)谶@篇文章中使用了以下技術(shù)堆棧,但它可以在任何其他技術(shù)上實(shí)現(xiàn),前提是您在設(shè)計(jì)時(shí)遵循所有基本原則。

  • Spring Boot

  • JPA.

  • Spring Data REST

在本文中使用Spring Data REST的原因之一是Data REST API支持的開(kāi)箱即用功能。

我們將在pom.xml中添加以下依賴(lài)項(xiàng)

  1. Spring Boot JPA

  2. Spring Boot Data REST

  3. 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 + "\"";
 }
}

讓我們快速介紹上面代碼中的幾個(gè)要點(diǎn)。

  1. 我們使用  Pageable作為控制器的參數(shù)之一。這將有助于返回頁(yè)面而不是列表。

  2. Pageable具有所有必需的分頁(yè)信息。

  3. Pageable在Spring JPA中運(yùn)行得非常好,并且透明地處理分頁(yè)。

4.2 Previous 和Next 鏈接

每個(gè)頁(yè)面響應(yīng)將返回鏈接到當(dāng)前頁(yè)面前面和后面的頁(yè),這是基于使用IANA定義鏈接關(guān)系 prev 和  next。但是,如果您當(dāng)前位于結(jié)果的第一頁(yè),則不會(huì)呈現(xiàn)任何 prev鏈接。

我們來(lái)看下面的例子:

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 鏈接指向下一頁(yè)。last 鏈接指向的最后一個(gè)結(jié)果集。

  • self 鏈接提供整個(gè)系列。

  • 底部  page 提供有關(guān)分頁(yè)的信息,包括頁(yè)面大小,總結(jié)果,總頁(yè)數(shù)和當(dāng)前頁(yè)碼。

4.2使用鏈接頭

HTTP標(biāo)頭是REST API的關(guān)鍵方面.HTTP鏈接標(biāo)頭還可用于將分頁(yè)信息傳遞給客戶(hù)端。通過(guò)上述測(cè)試,系統(tǒng)將返回以下附加信息作為L(zhǎng)ink 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" 意思是下一頁(yè)是  page=2;rel="first" 意思是第一頁(yè)總是依賴(lài)page=2.于提供給你的這些鏈接關(guān)系。不要試圖猜測(cè)或構(gòu)建自己的URL。Spring PagedResource提供所有這些信息作為結(jié)果的一部分,我們只需要確保從這些信息中構(gòu)建正確的HTTP頭。在我們的控制器示例中,我們?cè)赾reateLinkHeader方法中構(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 + "\"";
}

以上就是如何在Spring中利用REST實(shí)現(xiàn)一個(gè)分頁(yè)功能,小編相信有部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見(jiàn)到或用到的。希望你能通過(guò)這篇文章學(xué)到更多知識(shí)。更多詳情敬請(qǐng)關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI