0.开篇引入
数据分页是一个常见的需求,但是优雅的实现是一门学问。
开发要点:
- 使用分页的成本足够低,实现分页的代码要尽可能简单。
- 足够的通用性,新的模块可以快捷使用,在方法内部自由的控制分页
看看若依是怎么实现的吧。
若依的orm框架是mybatis,采用的分页插件是PageHelper
我们从最外层看,层层深入。
1.controller层
Java
@RestController
@RequestMapping("/system/dict/data")
// 继承了BaseController,分页的一些功能是在里面实现,作为controller层的基类
public class SysDictDataController extends BaseController
{
@Autowired
private ISysDictDataService dictDataService;
@PreAuthorize("@ss.hasPermi('system:dict:list')")
@GetMapping("/list")
public TableDataInfo list(SysDictData dictData)
{
// 作为标识,开始分页,通知下一个方法需要分页
// startPage本身的方法是存在BaseController中的可以直接使用
startPage();
List<SysDictData> list = dictDataService.selectDictDataList(dictData);
return getDataTable(list);
}
其中startPage和getDataTable的方法是在BaseController中,说明分页的功能是由BaseController里面实现。
controller层只要继承了这个类,就可以实现分页的这个功能了。
2.BaseController类和PageUtils类和TableSupport类分析
先整体过一遍BaseController的方法,然后具体的看方法里面是怎么实现的。
Java
/**
* web层通用数据处理
*
* @author ruoyi
*/
public class BaseController
{
//日志相关
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
/**
* 设置请求分页数据
*/
protected void startPage()
{
PageUtils.startPage();
}
/**
* 设置请求排序数据
*/
protected void startOrderBy()
{
PageDomain pageDomain = TableSupport.buildPageRequest();
if (StringUtils.isNotEmpty(pageDomain.getOrderBy()))
{
String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
PageHelper.orderBy(orderBy);
}
}
/**
* 清理分页的线程变量
*/
protected void clearPage()
{
PageUtils.clearPage();
}
/**
* 响应请求分页数据
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
protected TableDataInfo getDataTable(List<?> list)
{
TableDataInfo rspData = new TableDataInfo();
rspData.setCode(HttpStatus.SUCCESS);
rspData.setMsg("查询成功");
rspData.setRows(list);
rspData.setTotal(new PageInfo(list).getTotal());
return rspData;
}
好,整体的过了一遍,然后看具体的方法
2.1 分页入口
Java
// BaseController.java
protected void startPage() {
PageUtils.startPage();
}
Java
// PageUtils.java
public static void startPage()
{
// 这里用到了TableSupport这个类去构建初始的PageDomain,本质上就是对http的请求参数获取封装成一个对象
PageDomain pageDomain = TableSupport.buildPageRequest();
Integer pageNum = pageDomain.getPageNum();
Integer pageSize = pageDomain.getPageSize();
// 这里是对orderby参数做的一些校验,方式sql注入,无其他意义。
String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
// 这里的参数是是否设置响应,是个boolean参数默认为true
Boolean reasonable = pageDomain.getReasonable();
// 封装PageHelper对象,把请求参数全部放进去。
PageHelper.startPage(pageNum, pageSize, orderBy).setReasonable(reasonable);
}
Java
// TableSupport.java
/**
* 表格数据处理
*/
public class TableSupport
{
/**
* 当前记录起始索引
*/
public static final String PAGE_NUM = "pageNum";
/**
* 每页显示记录数
*/
public static final String PAGE_SIZE = "pageSize";
/**
* 排序列
*/
public static final String ORDER_BY_COLUMN = "orderByColumn";
/**
* 排序的方向 "desc" 或者 "asc".
*/
public static final String IS_ASC = "isAsc";
/**
* 分页参数合理化
*/
public static final String REASONABLE = "reasonable";
/**
* 封装分页对象
* 本质上就是获取http的请求参数封装成一个对象
*/
public static PageDomain getPageDomain()
{
PageDomain pageDomain = new PageDomain();
// 从http中获取pageNum的参数
pageDomain.setPageNum(Convert.toInt(ServletUtils.getParameter(PAGE_NUM), 1));
// 从http中获取pageSize的参数
pageDomain.setPageSize(Convert.toInt(ServletUtils.getParameter(PAGE_SIZE), 10));
// 从http中获取...
pageDomain.setOrderByColumn(ServletUtils.getParameter(ORDER_BY_COLUMN));
pageDomain.setIsAsc(ServletUtils.getParameter(IS_ASC));
pageDomain.setReasonable(ServletUtils.getParameterToBool(REASONABLE));
return pageDomain;
}
public static PageDomain buildPageRequest()
{
return getPageDomain();
}
}
2.2分页结果返回封装
Java
// SysDictDataController.java
public TableDataInfo list(SysDictData dictData)
{
startPage();
List<SysDictData> list = dictDataService.selectDictDataList(dictData);
// 通过getDataTable封装返回分页的结果
return getDataTable(list);
}
Java
// BaseController.java
protected TableDataInfo getDataTable(List<?> list)
{
// 创建分页返回的对象
TableDataInfo rspData = new TableDataInfo();
rspData.setCode(HttpStatus.SUCCESS);
rspData.setMsg("查询成功");
// 存放结果list
rspData.setRows(list);
//这里会先检测是否能转为page对象,可以转的话就返回总数,要不然就是list的大小
rspData.setTotal(new PageInfo(list).getTotal());
return rspData;
}
// 获取总数的核心逻辑
if (list instanceof Page) {
Page page = (Page)list;
this.pageNum = page.getPageNum();
this.pageSize = page.getPageSize();
this.pages = page.getPages();
this.size = page.size();
if (this.size == 0) {
this.startRow = 0L;
this.endRow = 0L;
} else {
this.startRow = page.getStartRow() + 1L;
this.endRow = this.startRow - 1L + (long)this.size;
}