我开始也想了很久,看了问答区的很多回答,觉得都没有讲到点子上,后面自己翻看了一下这个插件的源码才搞懂的。
首先,我们要知道:
List<Product> productList = productMapper.selectList();
这一句当中,productList的实际类型是什么?
我查了一下官方的文档,是这样解释的:
//分页时,实际返回的结果list类型是Page<E>,如果想取出分页信息,需要强制转换为Page<E>,//或者使用PageInfo类
也就是说,productList实际上指向的是一个Page对象。而我们自己写的productListVo仅仅是一个简单的List对象。
那么,为什么我们在这一句中,一定要传入一个Page对象呢?
我们翻看一下new PageInfo(productList);中的构造方法是怎样工作的:
public PageInfo(List<T> list, int navigatePages) {
if (list instanceof Page) {
Page page = (Page) list;
this.pageNum = page.getPageNum();
this.pageSize = page.getPageSize();
this.orderBy = page.getOrderBy();
this.pages = page.getPages();
this.list = page;
this.size = page.size();
this.total = page.getTotal();
//由于结果是>startRow的,所以实际的需要+1
if (this.size == 0) {
this.startRow = 0;
this.endRow = 0;
} else {
this.startRow = page.getStartRow() + 1;
//计算实际的endRow(最后一页的时候特殊)
this.endRow = this.startRow - 1 + this.size;
}
} else if (list instanceof Collection) {
this.pageNum = 1;
this.pageSize = list.size();
this.pages = 1;
this.list = list;
this.size = list.size();
this.total = list.size();
this.startRow = 0;
this.endRow = list.size() > 0 ? list.size() - 1 : 0;
}
if (list instanceof Collection) {
this.navigatePages = navigatePages;
//计算导航页
calcNavigatepageNums();
//计算前后页,第一页,最后一页
calcPage();
//判断页面边界
judgePageBoudary();
}
}
我们发现,如果传进来的是一个Page对象,将会根据这个Page对象计算相应的数值,此时Page对象的total为数据库中实际数据的总条数,而不是我们查出来的List的大小。包括当前实际处于的页数pageNum也是准确的。代码如下所示:
this.total = page.getTotal();
this.pageNum = page.getPageNum();
但是,我们仍然会发现,如果传入的参数不是Page对象,而是直接传入一个List的话,又是怎么处理的呢?我们发现,处理过程非常简单粗暴:
else if (list instanceof Collection) {
this.pageNum = 1;
this.pageSize = list.size();
this.pages = 1;
this.list = list;
this.size = list.size();
this.total = list.size();
this.startRow = 0;
this.endRow = list.size() > 0 ? list.size() - 1 : 0;
}
此时,直接把当前页数设置为第1页(实际可能不是第1页),总数total设置为List的大小,然而我们数据库中的数据肯定不止这个List这么大,因此,此时计算出来的页面信息全是错误的!
List<Product> productList = productMapper.selectList();
因此,如果我们先传入Mapper返回来的这个productList(实际上也是一个Page对象),那么我们在执行
PageInfo pageResult = new PageInfo(productList);
的时候,算出来的什么pageNum啊,total啊都是实际数据库中的数值,而不是简单的1和List的大小。
但是,我们最后又需要传给前端produstListVoList,因此,我们在构造函数算完这些值后,然后在替换其中的productList为productListVoList,前端既能收到productListVoList,又能得到正确的页面信息。
所以,老师第一步传入productList只是借来算页面信息的,实际展示给前端的还是展示productListVoList对象。
希望能帮助到一些同学,有错误欢迎指出。
更多详细内容,欢迎参考我的博客:https://blog.csdn.net/qq_19782019