别人写的分页助手插件
如果没有使用springboot
导入依赖

在核心配置文件中加入拦截器

使用
- 如果你使用了这个依赖,那么sql代码你就可以不用写limit
![image]()
- 但是在查询之前,一定将分页功能开启,你只有开启了,你才会有机会使用人家的分页,
注意注意,在执行分页之前一定一定开启分页功能 怎么开启?==》使用PageHelper这个类调用startPage(页号,显示的记录数),然后将页码和页数传进去
![image]()
- 如何通过该插件获取分也相关的数据呢?比如总的数据记录数目等等
==》其实很简单,就是在你的查询语句执行结束之后自己new一个PageInfo,将你的查询结构和你的导航卡片数量传进去
===》什么是导航卡片?就是你前端根据你的总记录数计算出的要显示的总页数,如下图:导航的卡片是10个
![image]()
代码如下:
![image]()
- 那么PageInfo分页信息中存着多少信息呢??如下所示
好的,你问的是 PageInfo 里到底存了多少分页信息,我来帮你详细拆解一下 👇
1. PageInfo 是什么
PageInfo 是 PageHelper 提供的一个 分页结果封装类,它不仅包含了当前页的数据,还包含了与分页相关的所有元信息(比如总条数、总页数、上一页、下一页等),非常方便在前端或接口中直接使用。
2. PageInfo 中包含的信息
PageInfo 类的主要字段如下(以 PageHelper 5.x 版本为例):
| 字段名 | 类型 | 说明 |
|---|---|---|
pageNum |
int |
当前页码 |
pageSize |
int |
每页显示数量 |
size |
int |
当前页实际条数(可能不足 pageSize) |
startRow |
int |
当前页第一条记录在数据库中的行号(从 1 开始) |
endRow |
int |
当前页最后一条记录在数据库中的行号 |
total |
long |
总记录数 |
pages |
int |
总页数 |
list |
List<T> |
当前页的数据列表 |
prePage |
int |
上一页页码(没有则为 0) |
nextPage |
int |
下一页页码(没有则为 0) |
isFirstPage |
boolean |
是否为第一页 |
isLastPage |
boolean |
是否为最后一页 |
hasPreviousPage |
boolean |
是否有上一页 |
hasNextPage |
boolean |
是否有下一页 |
navigatePages |
int |
导航页码数(默认 8) |
navigatepageNums |
int[] |
导航页码数组(比如 [1,2,3,4,5,6,7,8]) |
navigateFirstPage |
int |
导航栏中的第一页页码 |
navigateLastPage |
int |
导航栏中的最后一页页码 |
3. 示例代码
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public PageInfo<User> getUsers(int pageNum, int pageSize) {
// 开启分页
PageHelper.startPage(pageNum, pageSize);
// 查询
List<User> users = userMapper.selectAll();
// 用 PageInfo 包装结果
PageInfo<User> pageInfo = new PageInfo<>(users);
System.out.println("当前页码: " + pageInfo.getPageNum());
System.out.println("每页条数: " + pageInfo.getPageSize());
System.out.println("总条数: " + pageInfo.getTotal());
System.out.println("总页数: " + pageInfo.getPages());
System.out.println("是否第一页: " + pageInfo.isIsFirstPage());
System.out.println("导航页码: " + Arrays.toString(pageInfo.getNavigatepageNums()));
return pageInfo;
}
}
4. 返回 JSON 示例
假设查询第 2 页,每页 10 条,总共有 28 条数据:
{
"pageNum": 2,
"pageSize": 10,
"size": 10,
"startRow": 11,
"endRow": 20,
"total": 28,
"pages": 3,
"list": [...],
"prePage": 1,
"nextPage": 3,
"isFirstPage": false,
"isLastPage": false,
"hasPreviousPage": true,
"hasNextPage": true,
"navigatePages": 8,
"navigatepageNums": [1, 2, 3],
"navigateFirstPage": 1,
"navigateLastPage": 3
}
我们也可以使用Page类来获取分页信息
Page类是PageHelper的内部实现,继承自ArrayList,包含了基础的分页信息:
Page类核心字段和方法:
public class Page<E> extends ArrayList<E> {
// 分页基本信息
private int pageNum; // 当前页码
private int pageSize; // 每页数量
private long total; // 总记录数
private int pages; // 总页数
// 数据库相关
private int startRow; // 起始行号
private int endRow; // 结束行号
// 排序相关
private String orderBy; // 排序字段
// 计算字段
private boolean count = true; // 是否进行count查询
private Boolean reasonable; // 分页合理化
private Boolean pageSizeZero; // pageSize为0时返回所有结果
}
Page类的主要方法:
// 获取分页信息
page.getPageNum(); // 当前页码
page.getPageSize(); // 每页大小
page.getTotal(); // 总记录数
page.getPages(); // 总页数
page.getStartRow(); // 起始行
page.getEndRow(); // 结束行
// 列表操作(继承自ArrayList)
page.size(); // 当前页记录数
page.get(index); // 获取指定位置记录
如何创建page对象?
📄 Page 对象的创建方式
- 通过PageHelper.startPage()自动创建(最常用)
// 方式1:基础分页
PageHelper.startPage(1, 10); // 页码,页大小
List<User> userList = userMapper.selectAllUsers();
Page<User> page = (Page<User>) userList;//这里可以强转是因为Page是ArrsyList的子类
// 方式2:带排序的分页
PageHelper.startPage(1, 10, "id desc");
List<User> userList = userMapper.selectAllUsers();
Page<User> page = (Page<User>) userList;
// 方式3:更详细的分页参数
PageHelper.startPage(1, 10, true); // 页码,页大小,是否进行count查询
List<User> userList = userMapper.selectAllUsers();
Page<User> page = (Page<User>) userList;
- 手动创建Page对象
// 方式1:空Page对象
Page<User> page = new Page<>();
// 方式2:指定页码和页大小
Page<User> page = new Page<>(1, 10);
// 方式3:指定页码、页大小和是否进行count查询
Page<User> page = new Page<>(1, 10, true);
// 方式4:指定页码、页大小、是否count查询和排序
Page<User> page = new Page<>(1, 10, "id desc", true);
// 方式5:从现有List创建
List<User> existingList = Arrays.asList(user1, user2, user3);
Page<User> page = new Page<>(1, 10);
page.addAll(existingList);
page.setTotal(100L); // 手动设置总数
- 使用PageMethod创建
// 使用PageMethod的静态方法
Page<User> page = PageMethod.startPage(1, 10)
.doSelectPage(() -> userMapper.selectAllUsers());
那么如何创建PageInfo对象?
📋 PageInfo 对象的创建方式
- 从List/Page对象创建(最常用)
// 方式1:从普通List创建
List<User> userList = userMapper.selectAllUsers();
PageInfo<User> pageInfo = new PageInfo<>(userList);
// 方式2:从Page对象创建
PageHelper.startPage(1, 10);
List<User> userList = userMapper.selectAllUsers();
Page<User> page = (Page<User>) userList;
PageInfo<User> pageInfo = new PageInfo<>(page);
// 方式3:指定导航页码数量
PageInfo<User> pageInfo = new PageInfo<>(userList, 5); // 5个导航页码
- 使用Builder模式创建(灵活配置)
// 方式1:基础Builder
PageInfo<User> pageInfo = PageInfo.of(userList)
.setPageNum(1)
.setPageSize(10)
.setTotal(100L)
.setPages(10);
// 方式2:完整配置
PageInfo<User> pageInfo = new PageInfo.Builder<User>()
.list(userList)
.pageNum(1)
.pageSize(10)
.total(100L)
.pages(10)
.navigatePages(8)
.build();
- 手动设置所有属性
// 创建空PageInfo并手动设置所有属性
PageInfo<User> pageInfo = new PageInfo<>();
pageInfo.setList(userList); // 数据列表
pageInfo.setPageNum(1); // 当前页码
pageInfo.setPageSize(10); // 每页大小
pageInfo.setTotal(100L); // 总记录数
pageInfo.setPages(10); // 总页数
pageInfo.setSize(userList.size()); // 当前页记录数
pageInfo.setStartRow(1); // 起始行
pageInfo.setEndRow(10); // 结束行
pageInfo.setPrePage(0); // 上一页
pageInfo.setNextPage(2); // 下一页
pageInfo.setIsFirstPage(true); // 是否第一页
pageInfo.setIsLastPage(false); // 是否最后一页
pageInfo.setHasPreviousPage(false); // 是否有上一页
pageInfo.setHasNextPage(true); // 是否有下一页
pageInfo.setNavigatePages(8); // 导航页码数
pageInfo.setNavigatepageNums(new int[]{1,2,3,4,5,6,7,8}); // 导航页码
pageInfo.setNavigateFirstPage(1); // 导航第一页
pageInfo.setNavigateLastPage(8); // 导航最后一页
- 使用工具方法创建
// 从Map创建(适用于从参数Map转换)
Map<String, Object> params = new HashMap<>();
params.put("list", userList);
params.put("total", 100L);
params.put("pageNum", 1);
PageInfo<User> pageInfo = PageInfoUtils.buildFromMap(params);
// 从JSON创建(适用于反序列化)
String json = "{\"pageNum\":1,\"pageSize\":10,\"total\":100}";
PageInfo<User> pageInfo = JSON.parseObject(json, new TypeReference<PageInfo<User>>(){});
Page和PageInfo如何选择
Page vs PageInfo 分页信息对比
📋 Page类中的分页信息
Page类是PageHelper的内部实现,继承自ArrayList,包含了基础的分页信息:
Page类核心字段和方法:
public class Page<E> extends ArrayList<E> {
// 分页基本信息
private int pageNum; // 当前页码
private int pageSize; // 每页数量
private long total; // 总记录数
private int pages; // 总页数
// 数据库相关
private int startRow; // 起始行号
private int endRow; // 结束行号
// 排序相关
private String orderBy; // 排序字段
// 计算字段
private boolean count = true; // 是否进行count查询
private Boolean reasonable; // 分页合理化
private Boolean pageSizeZero; // pageSize为0时返回所有结果
}
Page类的主要方法:
// 获取分页信息
page.getPageNum(); // 当前页码
page.getPageSize(); // 每页大小
page.getTotal(); // 总记录数
page.getPages(); // 总页数
page.getStartRow(); // 起始行
page.getEndRow(); // 结束行
// 列表操作(继承自ArrayList)
page.size(); // 当前页记录数
page.get(index); // 获取指定位置记录
📊 PageInfo类中的分页信息
PageInfo是一个独立的分页信息包装类,提供了更丰富的分页导航信息:
PageInfo类核心字段和方法:
public class PageInfo<T> implements Serializable {
// 基础分页信息(与Page相同)
private int pageNum; // 当前页码
private int pageSize; // 每页数量
private long total; // 总记录数
private int pages; // 总页数
private List<T> list; // 数据列表
// 扩展的分页信息
private int size; // 当前页记录数
// 行号信息
private int startRow; // 起始行号
private int endRow; // 结束行号
// 页面导航信息
private int prePage; // 上一页页码
private int nextPage; // 下一页页码
// 布尔状态标识
private boolean isFirstPage; // 是否第一页
private boolean isLastPage; // 是否最后一页
private boolean hasPreviousPage; // 是否有上一页
private boolean hasNextPage; // 是否有下一页
// 导航页码相关
private int navigatePages; // 导航页码数
private int[] navigatepageNums; // 所有导航页码
private int navigateFirstPage; // 导航条上的第一页
private int navigateLastPage; // 导航条上的最后一页
}
🔄 Page vs PageInfo 详细对比
| 特性 | Page | PageInfo |
|---|---|---|
| 继承关系 | 继承ArrayList | 独立的包装类 |
| 数据存储 | 直接存储数据列表 | 通过list属性存储数据 |
| 基础分页信息 | ✅ 有 | ✅ 有 |
| 导航页码 | ❌ 无 | ✅ 完整的导航页码数组 |
| 页面状态标识 | ❌ 无 | ✅ 丰富的布尔状态标识 |
| 前后页信息 | ❌ 无 | ✅ 明确的上一页/下一页页码 |
| 使用场景 | 内部实现,简单分页 | 对外返回,完整分页需求 |
| 序列化 | 可能包含过多信息 | 专门为API设计,字段清晰 |
💡 实际使用对比
使用Page:
PageHelper.startPage(pageNum, pageSize);
List<User> userList = userMapper.selectAllUsers();
Page<User> page = (Page<User>) userList;
// 获取基本信息
long total = page.getTotal(); // 总记录数
int totalPages = page.getPages(); // 总页数
int currentSize = page.size(); // 当前页记录数
使用PageInfo:
PageHelper.startPage(pageNum, pageSize);
List<User> userList = userMapper.selectAllUsers();
PageInfo<User> pageInfo = new PageInfo<>(userList);
// 获取基础信息
long total = pageInfo.getTotal(); // 总记录数
int totalPages = pageInfo.getPages(); // 总页数
int currentSize = pageInfo.getSize(); // 当前页记录数
// 获取扩展的导航信息
boolean isFirst = pageInfo.isFirstPage(); // 是否第一页
boolean isLast = pageInfo.isLastPage(); // 是否最后一页
int prePage = pageInfo.getPrePage(); // 上一页页码
int nextPage = pageInfo.getNextPage(); // 下一页页码
int[] navigatePages = pageInfo.getNavigatepageNums(); // 导航页码数组
🎯 核心差异总结
Page的特点:
- 轻量级:只包含最基本的分页信息
- 直接数据容器:本身就是数据列表,可以直接使用
- 内部实现:更适合在Service层内部处理
- 信息有限:缺少导航相关的丰富信息
PageInfo的特点:
- 功能完整:包含完整的分页导航信息
- API友好:专门为前后端交互设计
- 导航丰富:提供页面导航所需的所有信息
- 推荐使用:PageHelper官方推荐对外返回的方式
✅ 选择建议
- 如果需要简单分页:可以使用Page,通过强制转换获得基础分页信息
- 如果需要完整分页(推荐):使用PageInfo,特别是需要给前端提供分页导航时
- API返回:总是使用PageInfo,字段清晰且完整
- 内部处理:可以使用Page进行简单处理,然后转换为PageInfo返回
最终建议:在大多数场景下,直接使用PageInfo是更好的选择,因为它提供了完整且标准化的分页信息,特别适合前后端分离的项目架构。
2.如果使用了springboot
好的,你想在 Spring Boot 中使用 MyBatis 的分页插件 PageHelper,我给你详细说一下 依赖导入 和 分页拦截器配置 的步骤。
1. 导入 Maven 依赖
PageHelper 官方提供了 Spring Boot Starter,可以直接引入,不用手动配置拦截器(推荐)。
<!-- MyBatis 分页插件 PageHelper -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.7</version> <!-- 版本号可以去 Maven Central 查最新 -->
</dependency>
如果你不想用 starter,也可以单独引入
pagehelper核心包:
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.3.3</version>
</dependency>
但是这样需要自己手动配置拦截器。
2. 添加分页拦截器(两种方式)
方式一:使用 pagehelper-spring-boot-starter(自动配置)
如果你用了 starter,一般不需要手动配置拦截器,它会自动注入 PageInterceptor。
你只需要在 application.yml 或 application.properties 里配置数据库方言等参数:
pagehelper:
helper-dialect: mysql
reasonable: true
support-methods-arguments: true
params: count=countSql
方式二:手动配置拦截器(不用 starter)
如果没用 starter,需要自己定义一个 @Configuration 类来注册分页插件:
import com.github.pagehelper.PageInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Properties;
@Configuration
public class MyBatisConfig {
@Bean
public PageInterceptor pageInterceptor() {
PageInterceptor interceptor = new PageInterceptor();
Properties properties = new Properties();
// 指定数据库方言
properties.setProperty("helperDialect", "mysql");
// 合理化分页参数
properties.setProperty("reasonable", "true");
interceptor.setProperties(properties);
return interceptor;
}
}
3. 使用示例
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public Page<User> getUsers(int pageNum, int pageSize) {
// 开始分页
PageHelper.startPage(pageNum, pageSize);
// 后续的第一个 MyBatis 查询会自动分页
List<User> users = userMapper.selectAll();
// 用 Page 接收结果,可以获取分页信息
return (Page<User>) users;
}
}
4. 注意事项
- PageHelper.startPage 方法必须紧挨着需要分页的查询方法,中间不能有其他 MyBatis 方法调用,否则分页会失效。
- 如果是多数据源,需要确保拦截器配置在对应 SqlSessionFactory 里。
- 数据库方言(
helperDialect)要配置正确,比如mysql、postgresql、oracle等。
✅ 如果你用 Spring Boot + MyBatis,我建议直接用 pagehelper-spring-boot-starter,几乎零配置就能用。
Page和PageInfo的构造方法创建方式的对比
Page 和 PageInfo 构造方法参数详解
📄 Page 构造方法参数详解
1. 无参构造方法
Page<E> page = new Page<>();
作用:创建空的Page对象
包含属性:
pageNum= 1(默认页码)pageSize= 0(默认页大小)total= 0(总记录数)pages= 0(总页数)- 空的ArrayList数据容器
2. 页码 + 页大小构造方法
Page<E> page = new Page<>(int pageNum, int pageSize);
参数作用:
pageNum:当前页码(从1开始)pageSize:每页显示的记录数
包含属性:
- 设置指定的页码和页大小
- 其他属性保持默认值
3. 页码 + 页大小 + 是否count构造方法
Page<E> page = new Page<>(int pageNum, int pageSize, boolean count);
参数作用:
pageNum:当前页码pageSize:每页记录数count:是否进行count查询(true=查询总数,false=不查询)
包含属性:
- 设置分页基本参数
- 控制是否进行总数统计
4. 完整参数构造方法
Page<E> page = new Page<>(int pageNum, int pageSize, String orderBy, boolean count);
参数作用:
pageNum:当前页码pageSize:每页记录数orderBy:排序字段(如:"id DESC, name ASC")count:是否进行count查询
包含属性:
- 完整的分页和排序参数
- 包含排序信息
📋 PageInfo 构造方法参数详解
1. 无参构造方法
PageInfo<E> pageInfo = new PageInfo<>();
作用:创建空的PageInfo对象
包含属性:所有属性均为默认值(null、0、false等)
2. List数据构造方法(最常用)
PageInfo<E> pageInfo = new PageInfo<>(List<E> list);
参数作用:
list:当前页的数据列表
包含属性:
list= 传入的数据列表- 自动计算:
size、startRow、endRow等 - 其他分页信息需要后续设置
3. List数据 + 导航页码数构造方法
PageInfo<E> pageInfo = new PageInfo<>(List<E> list, int navigatePages);
参数作用:
list:当前页的数据列表navigatePages:导航页码显示数量(如:5显示5个页码)
包含属性:
- 包含所有基础分页信息
- 设置导航页码数量,影响
navigatepageNums数组
🔄 构造方法对比总结
Page 构造方法特点:
| 构造方法 | 核心参数 | 创建的对象特点 |
|---|---|---|
Page() |
无 | 空Page对象,需要手动设置所有属性 |
Page(pageNum, pageSize) |
页码、页大小 | 基础分页参数设置 |
Page(pageNum, pageSize, count) |
页码、页大小、是否统计 | 控制是否查询总数 |
Page(pageNum, pageSize, orderBy, count) |
完整参数 | 包含排序的完整分页对象 |
PageInfo 构造方法特点:
| 构造方法 | 核心参数 | 创建的对象特点 |
|---|---|---|
PageInfo() |
无 | 空PageInfo,需要手动设置所有属性 |
PageInfo(list) |
数据列表 | 包含数据,自动计算基础分页信息 |
PageInfo(list, navigatePages) |
数据列表、导航页数 | 完整的分页导航对象 |
💡 实际应用建议
创建Page的推荐场景:
// 场景1:手动创建分页对象
Page<User> page = new Page<>(1, 10, "create_time DESC", true);
// 场景2:通过PageHelper自动创建(最常用)
PageHelper.startPage(1, 10);
List<User> list = userMapper.selectAll();
Page<User> page = (Page<User>) list; // 实际使用时转换
创建PageInfo的推荐场景:
// 场景1:从查询结果直接创建(最常用)
PageHelper.startPage(1, 10);
List<User> list = userMapper.selectAll();
PageInfo<User> pageInfo = new PageInfo<>(list, 5); // 5个导航页码
// 场景2:手动创建完整分页信息
PageInfo<User> pageInfo = new PageInfo<>();
pageInfo.setList(userList);
pageInfo.setPageNum(1);
pageInfo.setPageSize(10);
pageInfo.setTotal(100L);
pageInfo.setPages(10);
🎯 核心区别总结
- Page:主要是数据容器 + 基础分页参数
- PageInfo:主要是分页信息包装器 + 完整导航信息
选择建议:
- 内部处理数据时可以使用Page
- 返回给前端的API统一使用PageInfo
- 大多数情况下推荐直接使用
new PageInfo<>(list, navigatePages)




浙公网安备 33010602011771号