bootstrap
的轻量级表格插件bootstrap-table(opens new window)mybatis
的轻量级分页插件pageHelper(opens new window)提示:
前后端分页实现流程
// 全局组件挂载
Vue.component('Pagination', Pagination)
// 分页组件
import Pagination from "@/components/Pagination";
// 一般在查询参数中定义分页变量
queryParams: {
pageNum: 1,
pageSize: 10
},
// 页面添加分页组件,传入分页变量
// 声明分页参数和查询参数
export default {
data() {
return {
// 查询参数
queryParams: {
pageNum: 1, // 第1页
pageSize: 10, // 每页10条
roleId: undefined, // 查询条件1:roleId,角色id
userName: undefined, // 查询条件2:用户名称
phonenumber: undefined // 查询条件3:电话号码
}
};
}
}
// 调用后台方法,传入参数 获取结果
// queryParams是分页参数和查询参数
listUser(this.queryParams).then(response => {
this.userList = response.rows;
this.total = response.total;
}
);
public class TableDataInfo implements Serializable
{
private static final long serialVersionUID = 1L;
/** 总记录数 */
private long total;
/** 列表数据 */
private List> rows;
/** 消息状态码 */
private int code;
/** 消息内容 */
private String msg;
}
/**
* 分页工具类
*
* @author ruoyi
*/
public class PageUtils extends PageHelper
{
/**
* 设置请求分页数据:
* 就是从request中把前端传过来的几个参数拿过来。
* 然后设置到pageDomain里面。
*/
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);
}
}
/**
* 获取岗位列表
*/
@RequiresPermissions("system:post:list")
@GetMapping("/list")
public TableDataInfo list(SysPost post)
{
// 分页
startPage();
// 当前页数据
List list = postService.selectPostList(post);
// 返回给前端
return getDataTable(list);
}
// 当前请求
protected static final ThreadLocal LOCAL_PAGE = new ThreadLocal();
// 即在当前请求下面,去给我们进行一个分页
// 会自动在sql语句中拼接pageNum、pageSize、orderBy这3个参数的limit分页语句
// 简化代码:不用在SysPostMapper.xml中修改sql语句
public static Page startPage(int pageNum, int pageSize, String orderBy) {
Page page = startPage(pageNum, pageSize);
page.setOrderBy(orderBy);
return page;
}
selectPostById
莫名其妙的分页。例如下面这段代码startPage();
List list;
if(user != null){
list = userService.selectUserList(user);
} else {
list = new ArrayList();
}
// 当user == null时,分页会消费在此查询上。
// 本来是查询单个的,但结果却莫名其妙给你分了个页
Post post = postService.selectPostById(1L);
return getDataTable(list);
原因分析:这种情况下由于user
存在null
的情况,就会导致pageHelper
生产了一个分页参数,但是没有被消费,这个参数就会一直保留在这个线程上。 当这个线程再次被使用时,就可能导致不该分页的方法去消费这个分页参数,这就产生了莫名其妙的分页。
上面这个代码,应该写成下面这个样子才能保证安全。
就是说你使用了这个startPage,你又不去分页啊,这个地方又没有分页。那么的话,你下一次查询就是下一个查询,它就会带上这个分页,所以的话呢就会莫名其妙。这个你本来不需要分页的,反而被分页了,所以的话就需要注意一下。
List list;
if(user != null){
startPage();
list = userService.selectUserList(user);
} else {
list = new ArrayList();
}
Post post = postService.selectPostById(1L);
return getDataTable(list);
startPage
方法。也没有正常分页。例如下面这段代码startPage();
// 错:分页错误地加上这里
Post post = postService.selectPostById(1L);
List list = userService.selectUserList(user);
return getDataTable(list);
原因分析:只对该语句以后的第一个查询(Select)
语句得到的数据进行分页。
上面这个代码,应该写成下面这个样子才能正常分页。
因为的话,你下面的话必须是你分页的那个sql语句的一个查询方法(XxxMapper.xml)。
Post post = postService.selectPostById(1L);
startPage();
List list = userService.selectUserList(user);
return getDataTable(list);
项目分页插件默认是Mysql
语法,如果项目改为其他数据库需修改配置application.yml
文件中的属性helperDialect: 你的数据库
只要你可以保证在
PageHelper
方法调用后紧跟MyBatis
查询方法,这就是安全的。因为PageHelper
在finally
代码段中自动清除了ThreadLocal
存储的对象。 如果代码在进入Executor
前发生异常,就会导致线程不可用,这属于人为的Bug
(例如接口方法和XML
中的不匹配,导致找不到MappedStatement
时),这种情况由于线程不可用,也不会导致ThreadLocal
参数被错误的使用。