前言:
最近在工作中有个后台功能是对导入的excel文件中的数据进行读取后分页展示,读取excel数据保存到List集合中都比较容易,但在分页这里堵住了。因为公司Java服务采用的是SSM框架,而分页是统一采用的配合Mybatis的分页插件Pagehelper。所以问题来了,Pagehelper原理是在同一线程中对通过mybatis拦截器拦截查询数据库的sql语句并添加分页参数,之后实现分页查询,查询结束后在 finally 语句中清除ThreadLocal中的查询参数。因此现在这个业务场景使用pagehelper是无效的,需要寻求新的分页方案。
对List进行分页
主流的两种解决方案:
- 后端一次性返回所有list数据,前端使用JS对数据进行‘假分页’;
- 后端预先对数据进行分页处理再返回前端,前端通过传相应参数进行分页展示数据;
在跟前端同事协商,最后采用第二种方案,以下我将介绍这种对list数据物理分页的方法:
1、首先是一个分页工具类(其实和Pagehelper的PageInfo类很相似)
/**
* 对list数据进行分页工具类
*/
public class PageModel {
private int page = 1; // 当前页
public int totalPages = 0; // 总页数
private int pageRecorders;// 每页5条数据
private int totalRows = 0; // 总数据数
private int pageStartRow = 0;// 每页的起始数
private int pageEndRow = 0; // 每页显示数据的终止数
private boolean hasNextPage = false; // 是否有下一页
private boolean hasPreviousPage = false; // 是否有前一页
private List list;
// private Iterator it;
public PageModel(List list, int pageRecorders) {
init(list, pageRecorders);// 通过对象集,记录总数划分
}
/** */
/**
* 初始化list,并告之该list每页的记录数
* @param list
* @param pageRecorders
*/
public void init(List list, int pageRecorders) {
this.pageRecorders = pageRecorders;
this.list = list;
totalRows = list.size();
// it = list.iterator();
hasPreviousPage = false;
if ((totalRows % pageRecorders) == 0) {
totalPages = totalRows / pageRecorders;
} else {
totalPages = totalRows / pageRecorders + 1;
}
if (page >= totalPages) {
hasNextPage = false;
} else {
hasNextPage = true;
}
if (totalRows < pageRecorders) {
this.pageStartRow = 0;
this.pageEndRow = totalRows;
} else {
this.pageStartRow = 0;
this.pageEndRow = pageRecorders;
}
}
// 判断要不要分页
public boolean isNext() {
return list.size() > 5;
}
public void setHasPreviousPage(boolean hasPreviousPage) {
this.hasPreviousPage = hasPreviousPage;
}
public String toString(int temp) {
String str = Integer.toString(temp);
return str;
}
public void description() {
String description = "共有数据数:" + this.getTotalRows()
+ "共有页数: " + this.getTotalPages()
+ "当前页数为:" + this.getPage()
+ " 是否有前一页: " + this.isHasPreviousPage()
+ " 是否有下一页:" + this.isHasNextPage()
+ " 开始行数:" + this.getPageStartRow()
+ " 终止行数:" + this.getPageEndRow();
System.out.println(description);
}
public List getNextPage() {
page = page + 1;
disposePage();
System.out.println("用户凋用的是第" + page + "页");
this.description();
return getObjects(page);
}
/** */
/**
* 处理分页
*/
private void disposePage() {
if (page == 0) {
page = 1;
}
if ((page - 1) > 0) {
hasPreviousPage = true;
} else {
hasPreviousPage = false;
}
if (page >= totalPages) {
hasNextPage = false;
} else {
hasNextPage = true;
}
}
public List getPreviousPage() {
page = page - 1;
if ((page - 1) > 0) {
hasPreviousPage = true;
} else {
hasPreviousPage = false;
}
if (page >= totalPages) {
hasNextPage = false;
} else {
hasNextPage = true;
}
this.description();
return getObjects(page);
}
/** */
/**
* 获取第几页的内容
*
* @param page
* @return
*/
public List getObjects(int page) {
if (page == 0) {
this.setPage(1);
} else {
this.setPage(page);
}
this.disposePage();
if (page * pageRecorders < totalRows) {// 判断是否为最后一页
pageEndRow = page * pageRecorders;
pageStartRow = pageEndRow - pageRecorders;
} else {
pageEndRow = totalRows;
pageStartRow = pageRecorders * (totalPages - 1);
}
List objects = null;
if (!list.isEmpty()) {
objects = list.subList(pageStartRow, pageEndRow);
}
//this.description();
return objects;
}
public List getFistPage() {
if (this.isNext()) {
return list.subList(0, pageRecorders);
} else {
return list;
}
}
public boolean isHasNextPage() {
return hasNextPage;
}
public void setHasNextPage(boolean hasNextPage) {
this.hasNextPage = hasNextPage;
}
public List getList() {
return list;
}
public void setList(List list) {
this.list = list;
}
public int getPage() {
return page;
}
public void setPage(int page) {
this.page = page;
}
public int getPageEndRow() {
return pageEndRow;
}
public void setPageEndRow(int pageEndRow) {
this.pageEndRow = pageEndRow;
}
public int getPageRecorders() {
return pageRecorders;
}
public void setPageRecorders(int pageRecorders) {
this.pageRecorders = pageRecorders;
}
public int getPageStartRow() {
return pageStartRow;
}
public void setPageStartRow(int pageStartRow) {
this.pageStartRow = pageStartRow;
}
public int getTotalPages() {
return totalPages;
}
public void setTotalPages(int totalPages) {
this.totalPages = totalPages;
}
public int getTotalRows() {
return totalRows;
}
public void setTotalRows(int totalRows) {
this.totalRows = totalRows;
}
public boolean isHasPreviousPage() {
return hasPreviousPage;
}
}
2、具体实现类
/**
* 分页查询用户信息Excel文件
* @param pageQuery
* @return
*/
@Override
public PageInfo<PushUserVO> queryUserInfoExcel(PageQuery pageQuery, InputStream inputStream, String fileName) throws Exception{
List<PushUserVO> userList = getUserInfoListByExcel(inputStream, fileName);
//利用工具类进行数据拆分
PageModel pm = new PageModel(userList, pageQuery.getPageSize());
List list = pm.getObjects(pageQuery.getPageNo());
//将分页数据转到pageInfo
PageInfo<PushUserVO> pageInfo = new PageInfo<>(list);
//当前页码数
pageInfo.setPageNum(pm.getPage());
//每页数据条数
pageInfo.setPageSize(pm.getPageRecorders());
//数据总条数
pageInfo.setTotal(pm.getTotalRows());
//是否有下一页
pageInfo.setHasNextPage(pm.isHasNextPage());
if (CollectionUtils.isEmpty(list)) {
return new PageInfo<PushUserVO>(list);
}
inputStream.close();
return pageInfo;
}
3、最后是controller层
@ApiOperation("上传用户信息excel")
@PostMapping("/uploadUserInfoExcel")
public Result<PageInfo<PushUserVO>> uploadUserInfoExcel(@RequestParam("file") MultipartFile file, PageQuery pageQuery) {
if (file.isEmpty()) {
throw new BusinessException(ErrorCode.USEREXCEL_EMPTY_ERROR.getCode(),ErrorCode.USEREXCEL_EMPTY_ERROR.getDefaultMessage());
}
String fileName = file.getOriginalFilename();
InputStream in = null;
try {
in = file.getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
PageInfo<PushUserVO> pageInfo = new PageInfo<>();
try {
pageInfo = userInfoService.queryUserInfoExcel(pageQuery, in, fileName);
} catch (Exception e) {
e.printStackTrace();
}
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
return Result.successData(pageInfo);
}