RuoYi分页插件:PageHelper集成与自定义扩展
引言
在企业级应用开发中,分页查询是必不可少的功能。RuoYi作为一款优秀的权限管理系统,深度集成了MyBatis分页插件PageHelper,并在此基础上进行了精心的封装和扩展。本文将深入解析RuoYi中PageHelper的集成原理、使用方式以及自定义扩展技巧,帮助开发者更好地理解和运用这一强大的分页解决方案。
PageHelper核心集成原理
1. 基础配置
RuoYi在application.yml中配置了PageHelper的基本参数:
# PageHelper分页插件
pagehelper:
helperDialect: mysql
reasonable: true
supportMethodsArguments: true
params: count=countSql
2. 核心工具类设计
RuoYi通过PageUtils类对PageHelper进行了二次封装:
public class PageUtils extends PageHelper
{
public static void startPage()
{
PageDomain pageDomain = TableSupport.buildPageRequest();
Integer pageNum = pageDomain.getPageNum();
Integer pageSize = pageDomain.getPageSize();
String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
Boolean reasonable = pageDomain.getReasonable();
PageHelper.startPage(pageNum, pageSize, orderBy).setReasonable(reasonable);
}
public static void clearPage()
{
PageHelper.clearPage();
}
}
3. 分页数据模型
RuoYi定义了统一的分页响应模型TableDataInfo:
public class TableDataInfo implements Serializable
{
private long total; // 总记录数
private List<?> rows; // 列表数据
private int code; // 状态码
private String msg; // 消息内容
}
分页使用流程详解
1. 请求参数解析
2. 控制器层使用示例
@GetMapping("/list")
public TableDataInfo list(SysUser user)
{
PageUtils.startPage();
List<SysUser> list = userService.selectUserList(user);
return getDataTable(list);
}
protected TableDataInfo getDataTable(List<?> list)
{
TableDataInfo rspData = new TableDataInfo();
rspData.setCode(0);
rspData.setRows(list);
rspData.setTotal(new PageInfo(list).getTotal());
return rspData;
}
自定义扩展功能
1. 排序功能增强
RuoYi支持动态排序,通过orderByColumn和isAsc参数实现:
// 前端传参示例
// orderByColumn=createTime&isAsc=desc
// 后端处理
String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
PageHelper.startPage(pageNum, pageSize, orderBy);
2. 分页参数合理化
// 防止不合理的分页参数
Boolean reasonable = pageDomain.getReasonable();
PageHelper.startPage(pageNum, pageSize).setReasonable(reasonable);
3. SQL注入防护
public static String escapeOrderBySql(String value)
{
if (StringUtils.isNotEmpty(value) && !isValidOrderBySql(value))
{
throw new ServiceException("排序参数不合法");
}
return value;
}
高级使用技巧
1. 多表关联分页
public TableDataInfo selectUserWithDeptList(SysUser user)
{
PageUtils.startPage();
List<SysUser> list = userMapper.selectUserWithDeptList(user);
return getDataTable(list);
}
// Mapper XML
<select id="selectUserWithDeptList" resultMap="SysUserResult">
SELECT u.*, d.dept_name
FROM sys_user u
LEFT JOIN sys_dept d ON u.dept_id = d.dept_id
WHERE u.del_flag = '0'
</select>
2. 复杂条件分页
public TableDataInfo searchUsers(UserSearchVO searchVO)
{
PageUtils.startPage();
// 构建复杂查询条件
Example example = new Example(SysUser.class);
Example.Criteria criteria = example.createCriteria();
if (StringUtils.isNotEmpty(searchVO.getKeyword())) {
criteria.orLike("userName", "%" + searchVO.getKeyword() + "%")
.orLike("loginName", "%" + searchVO.getKeyword() + "%");
}
if (searchVO.getDeptId() != null) {
criteria.andEqualTo("deptId", searchVO.getDeptId());
}
List<SysUser> list = userMapper.selectByExample(example);
return getDataTable(list);
}
性能优化建议
1. 分页参数调优
| 参数 | 默认值 | 建议值 | 说明 |
|---|---|---|---|
| pageSize | 10 | 20-50 | 根据业务需求调整 |
| reasonable | true | true | 防止不合理分页 |
| count | true | false | 大数据量时禁用count |
2. 索引优化
-- 为分页字段创建索引
CREATE INDEX idx_create_time ON sys_user(create_time);
CREATE INDEX idx_dept_id ON sys_user(dept_id);
3. 分页查询优化
// 使用覆盖索引优化count查询
@Select("SELECT COUNT(*) FROM (SELECT id FROM table WHERE condition) tmp")
Long optimizedCount(Map<String, Object> params);
常见问题解决方案
1. 分页失效问题
// 确保在Service方法调用前设置分页
public List<SysUser> getUserList() {
PageUtils.startPage(); // 必须放在第一行
return userMapper.selectList();
}
2. 排序异常处理
try {
PageUtils.startPage();
// 业务逻辑
} catch (ServiceException e) {
// 处理排序参数异常
log.error("分页参数错误: {}", e.getMessage());
throw new BusinessException("分页参数不合法");
} finally {
PageUtils.clearPage();
}
3. 大数据量分页优化
// 使用游标分页代替传统分页
public TableDataInfo largeDataPage(PageParam param) {
// 使用last_id方式分页
List<SysUser> list = userMapper.selectByCursor(
param.getLastId(), param.getPageSize());
TableDataInfo result = new TableDataInfo();
result.setRows(list);
result.setTotal(-1); // 大数据量不返回总条数
return result;
}
总结
RuoYi通过深度集成PageHelper并提供丰富的扩展功能,为开发者提供了一套完整、安全、高效的分页解决方案。其核心优势在于:
- 统一封装:通过
PageUtils和TableDataInfo统一分页逻辑 - 安全防护:内置SQL注入检测和参数校验
- 灵活扩展:支持动态排序、复杂查询等场景
- 性能优化:提供多种性能优化方案
掌握RuoYi的分页机制,不仅能够提升开发效率,还能确保系统的稳定性和安全性。在实际项目中,建议根据具体业务需求选择合适的优化策略,充分发挥PageHelper的强大功能。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



