若依ruoyi-vue分离版--分页(小白记录)

    /**
     * 获取通知公告列表
     */
    @PreAuthorize("@ss.hasPermi('system:notice:list')")
    @GetMapping("/list")
    public TableDataInfo list(SysNotice notice)
    {
        startPage();// 此方法配合前端完成自动分页
        List<SysNotice> list = noticeService.selectNoticeList(notice);
        return getDataTable(list);
    }

先概要说明下但很重要:

后端采用基于mybatis的轻量级分页插件pageHelper

上图方法的notice参数,我们点进去看,其实并没看到分页相关参数。

那我们进到startPage()里看看,会走到如下:

/**
 * 分页工具类
 * 
 * @author ruoyi
 */
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();
    }
}

看来是在上面取分页参数没错了。再往下:

看来这里是ruoyi vue和前端配合的代码,来获取分页参数。那我们看看前端是怎么传的:

原来是get这里。

额外说明下:

ServletUtils.getParameter 方法获取请求参数,该方法底层调用的是 HttpServletRequest 的 getParameter 方法。getParameter 方法主要用于获取 HTTP 请求中 query string(即 URL 中的查询参数)和 form data(表单数据,通常是 POST 请求且 Content-Type 为 application/x-www-form-urlencoded 或 multipart/form-data)里的参数,并不会获取 body 里以 JSON 等其他格式传递的数据。

上面是ruoyi-vue的分页参数获取方式。然后才调用

PageHelper.startPage(pageNum, pageSize, orderBy).setReasonable(reasonable);

我们自己也可以封装一个,比如把分页参数放在body里,如刚才的notice里头。然后从body里取出来。最后传给PageHelper.startPage方法。

分页原理:

        这个原理一搜都有,不过既然写到这里,就简单说一下省的小白(比如我自己)到处找哈哈。

下面有参考了别人的 ,我觉得很清晰,引用一下,感谢该作者:

------------------------------------------------------------------------------------------------------Mybatis中分页插件PageHelper的底层实现原理_mybatis pagehelper分页原理是什么-优快云博客

PageHelper 的核心原理是:MyBatis 插件机制(拦截器 Interceptor)+ ThreadLocal + SQL 改写

核心步骤有 4 个:
✅ 1. 利用 MyBatis 的插件机制
MyBatis 允许开发者写拦截器拦截 SQL 执行过程,
PageHelper 就写了一个拦截器,拦截的是 Executor.query(…) 方法。

✅ 2. 用 ThreadLocal 暂存分页信息
当你调用:

PageHelper.startPage(1, 10);
1
PageHelper 就会把这个分页参数(页码、每页条数)存到 ThreadLocal 中,方便后面使用。

ThreadLocal 是一个线程本地变量,不会影响其他线程。

✅ 3. 拦截查询语句并修改 SQL
拦截器在查询语句执行前拿到了原始 SQL,然后从 ThreadLocal 里取出分页参数,把 SQL 改成带 LIMIT 的样子:

比如:

SELECT * FROM user
1
变成:

SELECT * FROM user LIMIT 0, 10
1
注意:它不是直接改你写的 SQL,而是改 MyBatis 构造好的 SQL,再交给数据库执行。

✅ 4. 执行分页查询并封装 Page 对象
执行完 SQL 后,PageHelper 还会生成一个 Page<T> 对象,里面包含:

当前页数据
总记录数(通过 count 查询)
总页数
当前页码等信息
方便你在前端展示。
————————————————
原文链接:https://blog.youkuaiyun.com/qq_61033357/article/details/148063691

------------------------------------------------------------------------------------------------------

上面的最后第四点要注意看下了,也就是返回给前端的时候。

这里的list是经过分页后的,应该是Page类型了

上图的PageInfo 是插件框架里的,如果我们自己要存这些信息并返回给前端,可以自定义一个

包含分页信息和数据的类,把PageInfo里头的信息取出来,也可以继承这个PageInfo后做修改。然后把这些东西返回给前端就可以了。

常见坑点:我就搬一下官网的过来。非常重要。

后台手册 | RuoYi

  • 常见坑点1:selectPostById莫名其妙的分页。例如下面这段代码
  • startPage();
    List<User> list;
    if(user != null){
        list = userService.selectUserList(user);
    } else {
        list = new ArrayList<User>();
    }
    Post post = postService.selectPostById(1L);
    return getDataTable(list);

    原因分析:这种情况下由于user存在null的情况,就会导致pageHelper生产了一个分页参数,但是没有被消费,这个参数就会一直保留在这个线程上。 当这个线程再次被使用时,就可能导致不该分页的方法去消费这个分页参数,这就产生了莫名其妙的分页。
    上面这个代码,应该写成下面这个样子才能保证安全。

  • List<User> list;
    if(user != null){
    	startPage();
    	list = userService.selectUserList(user);
    } else {
    	list = new ArrayList<User>();
    }
    Post post = postService.selectPostById(1L);
    return getDataTable(list);

  • 常见坑点2:添加了startPage方法。也没有正常分页。例如下面这段代码
  • startPage();
    Post post = postService.selectPostById(1L);
    List<User> list = userService.selectUserList(user);
    return getDataTable(list);

    原因分析:只对该语句以后的第一个查询(Select)语句得到的数据进行分页。
    上面这个代码,应该写成下面这个样子才能正常分页。

  • Post post = postService.selectPostById(1L);
    startPage();
    List<User> list = userService.selectUserList(user);
    return getDataTable(list);

    提示

    项目分页插件默认是Mysql语法,如果项目改为其他数据库需修改配置application.yml文件中的属性helperDialect: 你的数据库

  • 注意

    只要你可以保证在PageHelper方法调用后紧跟MyBatis查询方法,这就是安全的。因为PageHelperfinally代码段中自动清除了ThreadLocal存储的对象。 如果代码在进入Executor前发生异常,就会导致线程不可用,这属于人为的Bug(例如接口方法和XML中的不匹配,导致找不到MappedStatement时),这种情况由于线程不可用,也不会导致ThreadLocal参数被错误的使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值