mybatis插件开发之 分页插件pagehelper调用原理

/**
 * Mybatis - 通用分页拦截器<br/>
 * 项目地址 : http://git.oschina.net/free/Mybatis_PageHelper
 *
 * @author liuzh/abel533/isea533
 * @version 5.0.0
 */
//springboot集成pagehelper项目中的简单分页查询如下:
@Override
public PageInfo<SysUser> pageUsers(Integer pageNum, Integer pageSize) {

   PageHelper.startPage(pageNum,pageSize);
   List<SysUser> list = userMapper.selectAll();
   PageInfo pageInfo = new PageInfo(list);
   return pageInfo;

}

一、 PageHelper.startPage(pageNum,pageSize);

    这一步是为了提前设置分页参数  ,调用PageHelper的父类PageMethod.startPage ()->PageMethod.setLocalPage()设置Page参数 到

protected static final ThreadLocal<Page> LOCAL_PAGE = new ThreadLocal<Page>();

变量中

二、 List<SysUser> list = userMapper.selectAll();

这步会触发分页拦截器PageInterceptor   ,执行

public Object intercept(Invocation invocation) throws Throwable {
try {
    Object[] args = invocation.getArgs();
    MappedStatement ms = (MappedStatement) args[0];
    Object parameter = args[1];
    RowBounds rowBounds = (RowBounds) args[2];
    ResultHandler resultHandler = (ResultHandler) args[3];
    Executor executor = (Executor) invocation.getTarget();
    CacheKey cacheKey;
    BoundSql boundSql;
    //由于逻辑关系,只会进入一次
    if (args.length == 4) {
        //4 个参数时
        boundSql = ms.getBoundSql(parameter);
        cacheKey = executor.createCacheKey(ms, parameter, rowBounds, boundSql);
    } else {
        //6 个参数时
        cacheKey = (CacheKey) args[4];
        boundSql = (BoundSql) args[5];
    }
    checkDialectExists();

    List resultList;
    //调用方法判断是否需要进行分页,如果不需要,直接返回结果
    if (!dialect.skip(ms, parameter, rowBounds)) {
        //判断是否需要进行 count 查询
        if (dialect.beforeCount(ms, parameter, rowBounds)) {
            //查询总数
            Long count = count(executor, ms, parameter, rowBounds, resultHandler, boundSql);
            //处理查询总数,返回 true 时继续分页查询,false 时直接返回
            if (!dialect.afterCount(count, parameter, rowBounds)) {
                //当查询总数为 0 时,直接返回空的结果
                return dialect.afterPage(new ArrayList(), parameter, rowBounds);
            }
        }
        resultList = ExecutorUtil.pageQuery(dialect, executor,
                ms, parameter, rowBounds, resultHandler, boundSql, cacheKey);
    } else {
        //rowBounds用参数值,不使用分页插件处理时,仍然支持默认的内存分页
        resultList = executor.query(ms, parameter, rowBounds, resultHandler, cacheKey, boundSql);
    }
    return dialect.afterPage(resultList, parameter, rowBounds);
} finally {
    if(dialect != null){
        dialect.afterAll();
    }
}

}方法,返回的其实是一个Page类

定义如下:继承了ArrayList

 

public class Page<E> extends ArrayList<E> implements Closeable {
    private static final long serialVersionUID = 1L;

    /**
     * 页码,从1开始
     */
    private int pageNum;
    /**
     * 页面大小
     */
    private int pageSize;
    /**
     * 起始行
     */
    private int startRow;
    /**
     * 末行
     */
    private int endRow;
    /**
     * 总数
     */
    private long total;
    /**
     * 总页数
     */
    private int pages;
    /**
     * 包含count查询
     */
    private boolean count = true;
    /**
     * 分页合理化
     */
    private Boolean reasonable;
    /**
     * 当设置为true的时候,如果pagesize设置为0(或RowBounds的limit=0),就不执行分页,返回全部结果
     */
    private Boolean pageSizeZero;
    /**
     * 进行count查询的列名
     */
    private String countColumn;
    /**
     * 排序
     */
    private String orderBy;
    /**
     * 只增加排序
     */
    private boolean orderByOnly;

3、 PageInfo pageInfo = new PageInfo(list);

判断是否是Page,设置总数total
/**
 * 包装Page对象
 *
 * @param list
 */
public PageInfo(List<T> list) {
    this(list, 8);
}

/**
 * 包装Page对象
 *
 * @param list          page结果
 * @param navigatePages 页码数量
 */
public PageInfo(List<T> list, int navigatePages) {
    super(list);
    if (list instanceof Page) {
        Page page = (Page) list;
        this.pageNum = page.getPageNum();
        this.pageSize = page.getPageSize();

        this.pages = page.getPages();
        this.size = page.size();
        //由于结果是>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 = this.pageSize > 0 ? 1 : 0;
        this.size = list.size();
        this.startRow = 0;
        this.endRow = list.size() > 0 ? list.size() - 1 : 0;
    }
    if (list instanceof Collection) {
        this.navigatePages = navigatePages;
        //计算导航页
        calcNavigatepageNums();
        //计算前后页,第一页,最后一页
        calcPage();
        //判断页面边界
        judgePageBoudary();
    }
}