Sping boot (二)—— 分頁功能的實現
分頁功能是一個spring boot項目常常用到的功能,所以這篇文章主要介紹一下兩種簡單的分頁。
其實從網上我們可以看到比較常用的分頁查詢方法是用Pageable插件,但是我並不會用這個東西(手動捂臉),其實也是自己沒去學的原因。所以這裏介紹兩種超級簡單的分頁查詢,一種是通過Page類實現,另一種是通過對結果集的手動分頁實現。
本文采用的例子便是筆者上一篇文章所寫
Page類實現分頁查詢
1、非條件查詢
在UserRepository類裏面新增這樣一個方法:
Page<UserInfo> findAll(Pageable pageable);
然後來到UserController類裏面,新增分頁查詢接口:
//分頁查詢
@GetMapping(value = "/page")
private Page<UserInfo> findByPage(@RequestParam("pageNo")Integer pageNo, @RequestParam("pageSize")Integer pageSize){
Page<UserInfo> page = userRepository.findAll(new PageRequest(pageNo,pageSize)); //pageNo從第幾頁開始查,pageSize頁面條數
return page;
}
這樣,我們調用這個接口所返回的便是已經分頁好的數據了,是不是超級簡單?讓我們來看看實際測試結果。
截圖不是很方便,實際結果如下:
{
"content": [
{
"id": 1,
"name": "小紅",
"type": null
},
{
"id": 2,
"name": "小明",
"type": null
},
{
"id": 4,
"name": "小軍",
"type": null
},
{
"id": 5,
"name": "小強",
"type": null
},
{
"id": 6,
"name": "小張",
"type": null
},
{
"id": 7,
"name": "小李",
"type": null
},
{
"id": 8,
"name": "小剛",
"type": null
},
{
"id": 9,
"name": "小澤",
"type": null
},
{
"id": 10,
"name": "小力",
"type": null
},
{
"id": 11,
"name": "小總",
"type": null
}
],
"pageable": {
"sort": {
"sorted": false,
"unsorted": true,
"empty": true
},
"offset": 0,
"pageSize": 10,
"pageNumber": 0,
"unpaged": false,
"paged": true
},
"totalElements": 11,
"totalPages": 2,
"last": false,
"number": 0,
"size": 10,
"sort": {
"sorted": false,
"unsorted": true,
"empty": true
},
"numberOfElements": 10,
"first": true,
"empty": false
}
可以看到,完整的結果裏面是有很多東西的,當然大部分我們是不需要的,我們只需要保留下content(第0頁的10條數據)、totalElements(總記錄條數)、totalPages(總頁數)、pageNumber(頁碼)、pageSize(頁面大小)這五種數據。那麼怎麼獲得它們呢?很簡單,用Page類自帶的方法就可以獲得了。
page.getContent();
page.getTotalElements();
page.getTotalPages();
page.getSize();
page.getNumber();
這個時候我們再創建一個結果類,把需要的數據封裝到結果類裏面,由接口返回出來,就可以得到我們想要的結果了。
新建一個結果類ResultDto
public class ResultDto {
private Integer pageNo;
private Integer pageSize;
private Long totalRecord;
private Integer totalPage;
private List<UserInfo> results;
public ResultDto(){
super();
}
public ResultDto(Integer pageNo, Integer pageSize, Long totalRecord, Integer totalPage, List<UserInfo> results){
this.pageNo = pageNo;
this.pageSize = pageSize;
this.totalRecord = totalRecord;
this.totalPage = totalPage;
this.results = results;
}
public Integer getPageNo() {
return pageNo;
}
public void setPageNo(Integer pageNo) {
this.pageNo = pageNo;
}
public Integer getPageSize() {
return pageSize;
}
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
}
public Long getTotalRecord() {
return totalRecord;
}
public void setTotalRecord(Long totalRecord) {
this.totalRecord = totalRecord;
}
public Integer getTotalPage() {
return totalPage;
}
public void setTotalPage(Integer totalPage) {
this.totalPage = totalPage;
}
public List<UserInfo> getResults() {
return results;
}
public void setResults(List<UserInfo> results) {
this.results = results;
}
}
然後再修改一下分頁查詢的接口:
//分頁查詢
@GetMapping(value = "/page")
private ResultDto findByPage(@RequestParam("pageNo")Integer pageNo, @RequestParam("pageSize")Integer pageSize){
Page<UserInfo> page = userRepository.findAll(new PageRequest(pageNo,pageSize)); //pageNo從第幾頁開始查,pageSize頁面條數
ResultDto result = new ResultDto(page.getNumber(),page.getSize(),page.getTotalElements(),page.getTotalPages(),page.getContent());
return result;
}
最後運行一下,就會發現它返回的結果變成了這樣子:
這樣看上去就舒服了很多,不會有那麼多你不想要的信息,簡潔明瞭。這裏其實也就提到了一個結果類的思想,很多時候我們在調用接口時需要返回的信息是有要求的,這時我們就要自己建一個結果類來規範返回的信息。
- 注意:參數pageNo和pageSize中pageNo是一個坑點,因爲一般我們是從第一頁開始查詢,但在java我們是從第0頁開始查詢,所以這裏就要注意你傳過來的參數值了,假如你是前後端分離開發的,那你就要跟前端商量好,傳過來的值是啥意思。
2、條件查詢
在entity類裏面新增一個type字段用於測試
@Column(name = "type")
private Integer type;
public Integer getType() {
return type;
}
public void setType(Integer type) {
this.type = type;
}
新增字段後記得手動去數據庫設置type值,然後在UserRepository類裏面新增這樣一個方法:
Page<UserInfo> findByType(Integer type,Pageable pageable);
接着在UserController類裏面新增接口:
//條件分頁查詢
@GetMapping(value = "/typepage")
private ResultDto findByTypePage(@RequestParam("type")Integer type,@RequestParam("pageNo")Integer pageNo, @RequestParam("pageSize")Integer pageSize){
Page<UserInfo> page = userRepository.findByType(type,new PageRequest(pageNo,pageSize)); //pageNo從第幾頁開始查,pageSize頁面條數
ResultDto result = new ResultDto(page.getNumber(),page.getSize(),page.getTotalElements(),page.getTotalPages(),page.getContent());
return result;
}
最後運行測試一下,就可以得到結果了。
總結:條件分頁查詢和非條件分頁查詢其實屬於同一種方法,改變的只是增加了一個字段條件而已,這個分頁查詢方法也十分簡單,相信你們看一遍就會了。接下來講一個粗暴的分頁方法:分頁工具類。
分頁工具類實現查詢結果分頁
簡述:從之前的學習中我們知道,很多時候我們查詢出來的結果是一個List數組,而分頁無非就是將這個List數組進行再處理,分段罷了,當我們理解了分頁的本質之後,就可以製作這樣一個分頁工具類,手動對結果進行分頁。而分頁工具最大的優點就是查詢和分頁是分開的,這樣無論你做多複雜的查詢,只要是個List數組,我分頁工具就能把你分頁!
分頁工具類PageUtils:
public class PageUtils<T> {
//頁碼
private int pageNo;
//頁面大小
private int pageSize;
//總記錄條數
private long totalRecord;
//總頁數
private int totalPage;
//每頁的開始
private int start;
//當前頁面記錄集
private List<T> results;
public void doPage(List<T> lists){
int count = lists.size();
setTotalRecord(count);
setTotalPage(count % pageSize == 0 ? count / pageSize : count / pageSize + 1);
setStart(getPageNo() * getPageSize());
setResults(lists.subList(getStart(),
(count - getStart()) > getPageSize() ? getStart() + getPageSize() : count));
}
public PageUtils(){
super();
}
public PageUtils(int pageNo, int pageSize){
this.pageNo = pageNo;
this.pageSize = pageSize;
}
public int getStart() {
return start;
}
public void setStart(int start) {
this.start = start;
}
public List<T> getResults() {
return results;
}
public void setResults(List<T> results) {
this.results = results;
}
public int getPageNo() {
return pageNo;
}
public void setPageNo(int pageNo) {
this.pageNo = pageNo;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public long getTotalRecord() {
return totalRecord;
}
public void setTotalRecord(long totalRecord) {
this.totalRecord = totalRecord;
}
public int getTotalPage() {
return totalPage;
}
public void setTotalPage(int totalPage) {
this.totalPage = totalPage;
}
}
寫好工具類之後,就可以直接到controller層UserController類裏面寫接口了:
@GetMapping(value = "/utilpage")
private ResultDto findByUtil(@RequestParam("pageNo")Integer pageNo, @RequestParam("pageSize")Integer pageSize){
PageUtils<UserInfo> page = new PageUtils<>(pageNo,pageSize);
List<UserInfo> users = userRepository.findAll();
page.doPage(users);
ResultDto result = new ResultDto(page.getPageNo(),page.getPageSize(),
page.getTotalRecord(),page.getTotalPage(),page.getResults());
return result;
}
運行一下,再postman裏面查看結果:
到此,關於分頁的兩個方法就介紹完了。