分页功能是我们开发过程中常见的一个小功能,如何快速高效的实现一个分页功能呢。本文将带领大家快速搭建一个分页功能。
com.github.pagehelper
pagehelper
5.1.2
需要分页的实体继承该实体,用以接收分页的参数
public class BasePageReqListMsg {
protected final static int SIZE = 20;
protected final static int NO = 1;
protected int pageNum=NO;
protected int pageSize = SIZE;
public static int getInitSize() {
return SIZE;
}
public int getPageNum() {
return pageNum;
}
public int getPageSize() {
return pageSize;
}
public int getStartIndex() {
return (getPageNum() - 1) * this.pageSize;
}
public int getEndIndex() {
return getPageNum() * this.pageSize;
}
}
该实体将分页数据封装,返给前端
@Data
public class PageResult {
private Integer pageNum;
private Integer pageSize;
private Long total;
private List list;
public PageResult() {
}
public PageResult(Integer pageNum, Integer pageSize, Long total, List list) {
this.pageNum = pageNum;
this.pageSize = pageSize;
this.total = total;
this.list = list;
}
public static PageResult getResult(int pageNum, int pageSize, long total, List result) {
return new PageResult(pageNum, pageSize, total, result);
}
public static PageResult getResult(int pageNum, int pageSize) {
return new PageResult(pageNum, pageSize, 0L, new ArrayList());
}
}
public PageResult queryByParamPageList(QueryDTO queryDTO) {
PageHelper.startPage(queryDTO.getPageNum(), queryDTO.getPageSize());
List users= userMapper.selectByParam(queryDTO);
PageInfo pageInfo = new PageInfo<>(users);
return new PageResult<>(pageInfo.getPageNum(), pageInfo.getPageSize(), pageInfo.getTotal(), users);
}
分页是从这个方法开始的
/**
* 开始分页
*
* @param pageNum 页码
* @param pageSize 每页显示数量
* @param count 是否进行count查询
* @param reasonable 分页合理化,null时用默认配置
* @param pageSizeZero true且pageSize=0时返回全部结果,false时分页,null时用默认配置
*/
public static Page startPage(int pageNum, int pageSize, boolean count, Boolean reasonable, Boolean pageSizeZero) {
Page page = new Page(pageNum, pageSize, count);
page.setReasonable(reasonable);
page.setPageSizeZero(pageSizeZero);
//当已经执行过orderBy的时候
Page oldPage = getLocalPage();
if (oldPage != null && oldPage.isOrderByOnly()) {
page.setOrderBy(oldPage.getOrderBy());
}
setLocalPage(page);
return page;
}
跟进setLocalPage(page),是讲分页参数放到了ThreadLocal里了。ThreadLocal的讲解参见:
https://blog.csdn.net/zhangzijiejiayou/article/details/103425789
protected static final ThreadLocal LOCAL_PAGE = new ThreadLocal();
protected static boolean DEFAULT_COUNT = true;
/**
* 设置 Page 参数
*
* @param page
*/
protected static void setLocalPage(Page page) {
LOCAL_PAGE.set(page);
}
/**
* 获取 Page 参数
*
* @return
*/
public static Page getLocalPage() {
return LOCAL_PAGE.get();
}
PageInterceptor是分页的核心实现了mybatis的拦截器Interceptor,进行分页拦截和频接核心方法如下
public class PageInterceptor implements Interceptor {
//缓存count查询的ms
protected Cache msCountMap = null;
private Dialect dialect;
private String default_dialect_class = "com.github.pagehelper.PageHelper";
private Field additionalParametersField;
private String countSuffix = "_COUNT";
@Override
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];
}
List resultList;
//调用方法判断是否需要进行分页,如果不需要,直接返回结果
if (!dialect.skip(ms, parameter, rowBounds)) {
//反射获取动态参数
String msId = ms.getId();
Configuration configuration = ms.getConfiguration();
Map additionalParameters = (Map) additionalParametersField.get(boundSql);
//判断是否需要进行 count 查询
if (dialect.beforeCount(ms, parameter, rowBounds)) {
String countMsId = msId + countSuffix;
Long count;
//先判断是否存在手写的 count 查询
MappedStatement countMs = getExistedMappedStatement(configuration, countMsId);
if(countMs != null){
count = executeManualCount(executor, countMs, parameter, boundSql, resultHandler);
} else {
countMs = msCountMap.get(countMsId);
//自动创建
if (countMs == null) {
//根据当前的 ms 创建一个返回值为 Long 类型的 ms
countMs = MSUtils.newCountMappedStatement(ms, countMsId);
msCountMap.put(countMsId, countMs);
}
count = executeAutoCount(executor, countMs, parameter, boundSql, rowBounds, resultHandler);
}
//处理查询总数
//返回 true 时继续分页查询,false 时直接返回
if (!dialect.afterCount(count, parameter, rowBounds)) {
//当查询总数为 0 时,直接返回空的结果
return dialect.afterPage(new ArrayList(), parameter, rowBounds);
}
}
//判断是否需要进行分页查询
if (dialect.beforePage(ms, parameter, rowBounds)) {
//生成分页的缓存 key
CacheKey pageKey = cacheKey;
//处理参数对象
parameter = dialect.processParameterObject(ms, parameter, boundSql, pageKey);
//调用方言获取分页 sql
String pageSql = dialect.getPageSql(ms, boundSql, parameter, rowBounds, pageKey);
BoundSql pageBoundSql = new BoundSql(configuration, pageSql, boundSql.getParameterMappings(), parameter);
//设置动态参数
for (String key : additionalParameters.keySet()) {
pageBoundSql.setAdditionalParameter(key, additionalParameters.get(key));
}
//执行分页查询
resultList = executor.query(ms, parameter, RowBounds.DEFAULT, resultHandler, pageKey, pageBoundSql);
} else {
//不执行分页的情况下,也不执行内存分页
resultList = executor.query(ms, parameter, RowBounds.DEFAULT, resultHandler, cacheKey, boundSql);
}
} else {
//rowBounds用参数值,不使用分页插件处理时,仍然支持默认的内存分页
resultList = executor.query(ms, parameter, rowBounds, resultHandler, cacheKey, boundSql);
}
return dialect.afterPage(resultList, parameter, rowBounds);
} finally {
dialect.afterAll();
}
}
http://www.dengb.com/Javabc/1381088.html