Spring 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里面查看结果:
到此,关于分页的两个方法就介绍完了。