RuoYi分页插件:PageHelper集成与自定义扩展

RuoYi分页插件:PageHelper集成与自定义扩展

【免费下载链接】RuoYi 🎉 基于SpringBoot的权限管理系统 易读易懂、界面简洁美观。 核心技术采用Spring、MyBatis、Shiro没有任何其它重度依赖。直接运行即可用 【免费下载链接】RuoYi 项目地址: https://gitcode.com/yangzongzhuan/RuoYi

引言

在企业级应用开发中,分页查询是必不可少的功能。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. 请求参数解析

mermaid

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支持动态排序,通过orderByColumnisAsc参数实现:

// 前端传参示例
// 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. 分页参数调优

参数默认值建议值说明
pageSize1020-50根据业务需求调整
reasonabletruetrue防止不合理分页
counttruefalse大数据量时禁用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并提供丰富的扩展功能,为开发者提供了一套完整、安全、高效的分页解决方案。其核心优势在于:

  1. 统一封装:通过PageUtilsTableDataInfo统一分页逻辑
  2. 安全防护:内置SQL注入检测和参数校验
  3. 灵活扩展:支持动态排序、复杂查询等场景
  4. 性能优化:提供多种性能优化方案

掌握RuoYi的分页机制,不仅能够提升开发效率,还能确保系统的稳定性和安全性。在实际项目中,建议根据具体业务需求选择合适的优化策略,充分发挥PageHelper的强大功能。

【免费下载链接】RuoYi 🎉 基于SpringBoot的权限管理系统 易读易懂、界面简洁美观。 核心技术采用Spring、MyBatis、Shiro没有任何其它重度依赖。直接运行即可用 【免费下载链接】RuoYi 项目地址: https://gitcode.com/yangzongzhuan/RuoYi

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值