本文针对那种想要快速实现功能,而不是研究原理的,那你就直接复制我的东西,运行就好。如果想深入学习的同学请另行百度。
第一种 Spring Boot + Thymeleaf 使用PageHelper实现分页
这种实际上就是单独使用分页插件来实现分页功能。好处是,分页条你可以自行排版,不受页面约束。(前端使用的是thymeleaf)
我使用的是spring boot 2.1.11.RELEASE,如果按照以下步骤不能实现分页,那可能是pagehelper的版本问题,更换版本试一下。
1.1 pom.xml
首先在项目pom.xml中加入pagehelper插件的依赖
<!--pagehelper分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.5</version>
</dependency>
1.2 application.properties
然后在springboot的application.properties配置文件中:
(本人试了一下,这些属性可以不加,依然可以实现分页功能。最后还是写上吧。万一哪天炸了呢?)
配置pageHelper分页插件的内容:
pagehelper.helper-dialect=mysql
pagehelper.reasonable=true
pagehelper.support-methods-arguments=true
pagehelper.params=count=countSql
1.3 UserController
想要实现功能,而不是研究怎么搞的,你就直接复制我的东西(不建议)
/**
*
* @param model 携带数据返回
* @param pageSize 一页显示多少条-非必传值
* @param pageNum 显示当前页--必传值
* @return 前端页面
* @Author: Zoutao
* @Date: 2018/12/6
*/
//分页查询数据
@GetMapping("/usermanage")
public String usermanage(Model model,
@RequestParam(required = false,defaultValue="1",value="pageNum")Integer pageNum,
@RequestParam(defaultValue="5",value="pageSize")Integer pageSize){
//为了程序的严谨性,判断非空:
if(pageNum == null){
pageNum = 1; //设置默认当前页
}
if(pageNum <= 0){
pageNum = 1;
}
if(pageSize == null){
pageSize = 5; //设置默认每页显示的数据数
}
System.out.println("当前页是:"+pageNum+"显示条数是:"+pageSize);
//1.引入分页插件,pageNum是第几页,pageSize是每页显示多少条,默认查询总数count
PageHelper.startPage(pageNum,pageSize);
//2.紧跟的查询就是一个分页查询-必须紧跟.后面的其他查询不会被分页,除非再次调用PageHelper.startPage
try {
List<User> userList = userService.getAll();
System.out.println("分页数据:"+userList);
//3.使用PageInfo包装查询后的结果,5是连续显示的条数,结果list类型是Page<E>
PageInfo<User> pageInfo = new PageInfo<User>(userList,pageSize);
//4.使用model/map/modelandview等带回前端
model.addAttribute("pageInfo",pageInfo);
}finally {
PageHelper.clearPage(); //清理 ThreadLocal 存储的分页参数,保证线程安全
}
//5.设置返回的jsp/html等前端页面
// thymeleaf默认就会拼串classpath:/templates/xxxx.html
return "admin/user/list";
}
重要提示:
- 只有紧跟在PageHelper.startPage()方法后的第一个Mybatis的查询(Select)方法会被分页。
- 请不要在系统中配置多个分页插件(使用Spring时,mybatis-config.xml和Spring配置方式,请选择其中一种,不要同时配置多个分页插件)!
- 对于带有for update的sql,会抛出运行时异常,对于这样的sql建议手动分页,毕竟这样的sql需要重视。
- 由于嵌套结果方式会导致结果集被折叠,因此分页查询的结果在折叠后总数会减少,所以无法保证分页结果数量正确。
还有就分页插件支持以下几种调用方式(你任选),复制粘贴就好:
//第一种,RowBounds方式的调用
List<Country> list = sqlSession.selectList("x.y.selectIf", null, new RowBounds(0, 10));
//第二种,Mapper接口方式的调用,推荐这种使用方式。
PageHelper.startPage(1, 10);
List<Country> list = countryMapper.selectIf(1);
//第三种,Mapper接口方式的调用,推荐这种使用方式。
PageHelper.offsetPage(1, 10);
List<Country> list = countryMapper.selectIf(1);
//第四种,参数方法调用
//存在以下 Mapper 接口方法,你不需要在 xml 处理后两个参数
public interface CountryMapper {
List<Country> selectByPageNumSize(
@Param("user") User user,
@Param("pageNum") int pageNum,
@Param("pageSize") int pageSize);
}
//配置supportMethodsArguments=true
//在代码中直接调用:
List<Country> list = countryMapper.selectByPageNumSize(user, 1, 10);
//第五种,参数对象
//如果 pageNum 和 pageSize 存在于 User 对象中,只要参数有值,也会被分页
//有如下 User 对象
public class User {
//其他fields
//下面两个参数名和 params 配置的名字一致
private Integer pageNum;
private Integer pageSize;
}
//存在以下 Mapper 接口方法,你不需要在 xml 处理后两个参数
public interface CountryMapper {
List<Country> selectByPageNumSize(User user);
}
//当 user 中的 pageNum!= null && pageSize!= null 时,会自动分页
List<Country> list = countryMapper.selectByPageNumSize(user);
//第六种,ISelect 接口方式
//jdk6,7用法,创建接口
Page<Country> page = PageHelper.startPage(1, 10).doSelectPage(new ISelect() {
@Override
public void doSelect() {
countryMapper.selectGroupBy();
}
});
//jdk8 lambda用法
Page<Country> page = PageHelper.startPage(1, 10).doSelectPage(()-> countryMapper.selectGroupBy());
//也可以直接返回PageInfo,注意doSelectPageInfo方法和doSelectPage
pageInfo = PageHelper.startPage(1, 10).doSelectPageInfo(new ISelect() {
@Override
public void doSelect() {
countryMapper.selectGroupBy();
}
});
//对应的lambda用法
pageInfo = PageHelper.startPage(1, 10).doSelectPageInfo(() -> countryMapper.selectGroupBy());
//count查询,返回一个查询语句的count数
long total = PageHelper.count(new ISelect() {
@Override
public void doSelect() {
countryMapper.selectLike(country);
}
});
//lambda
total = PageHelper.count(()->countryMapper.selectLike(country));
下面对最常用的方式进行详细介绍:
使用这种调用方式时,你可以使用RowBounds参数进行分页,这种方式侵入性最小,我们可以看到,通过RowBounds方式调用只是使用了这个参数,并没有增加其他任何内容。
分页插件检测到使用了RowBounds参数时,就会对该查询进行物理分页。
关于这种方式的调用,有两个特殊的参数是针对 RowBounds 的,你可以参看上面还有PageHelper.startPage 静态方法调用+PageInfo的用法:代码中的1-3步,可以放到impl层写。反正就是在Dao层调用之前写就可以了。
说一点:
有人说PageHelper 是不安全的分页?
实际上PageHelper 方法使用了静态的 ThreadLocal 参数,分页参数和线程是绑定的。
只要你可以保证在 PageHelper 方法调用后紧跟 MyBatis 查询方法,这就是安全的。因为 PageHelper 在 finally 代码段中自动清除了 ThreadLocal 存储的对象。
1.4 Service
/**
* 查询所有用户
* @return
*/
public List<User> getAll();
1.5 Serviceimpl
/**
* 查询所有用户
* @return
*/
@Override
public List<User> getAll() {
return userMapper.getAll();
}
1.6 Dao层/mapper
//查询所有用户
@Select("SELECT * FROM tb_user")
@ResultMap(value = "userMap")
public List<User> getAll();
就是一个查询所有数据的方法,然后接下来是前端页面,我使用的thymeleaf。实际上jsp也是可以的,只不过写的时候注意一些使用EL表达式。
1.7 前端thymeleaf页面:
就是用来显示分页信息的,展示一下pageInfo的属性,用的是BootStrap,记得引入js和css还有Bootstrap图标或字体核心文件
<!--显示分页信息-->
<div class="modal-footer no-margin-top">
<div class="col-md-6">
当前第 [[${pageInfo.pageNum}]]页,共 [[${pageInfo.pages}]] 页.一共 [[${pageInfo.total}]] 条记录
</div>
<ul class="pagination pull-right no-margin">
<li th:if="${pageInfo.hasPreviousPage}">
<a th:href="'/usermanage?pageNum=1'">首页</a>
</li>
<li class="prev" th:if="${pageInfo.hasPreviousPage}">
<a th:href="'/usermanage?pageNum='+${pageInfo.prePage}">
<i class="ace-icon fa fa-angle-double-left"></i>
</a>
</li>
<!--遍历条数-->
<li th:each="nav:${pageInfo.navigatepageNums}">
<a th:href="'/usermanage?pageNum='+${nav}" th:text="${nav}" th:if="${nav != pageInfo.pageNum}"></a>
<span style="font-weight: bold;background: #6faed9;" th:if="${nav == pageInfo.pageNum}" th:text="${nav}" ></span>
</li>
<li class="next" th:if="${pageInfo.hasNextPage}">
<a th:href="'/usermanage?pageNum='+${pageInfo.nextPage}">
<i class="ace-icon fa fa-angle-double-right"></i>
</a>
</li>
<li>
<a th:href="'/usermanage?pageNum='+${pageInfo.pages}">尾页</a>
</li>
</ul>
</div>
<div>当前页号:<span th:text="${pageInfo.pageNum}"></span></div>
<div>每页条数:<span th:text="${pageInfo.pageSize}"></span></div>
<div>起始行号:<span th:text="${pageInfo.startRow}"></span></div>
<div>终止行号:<span th:text="${pageInfo.endRow}"></span></div>
<div>总结果数:<span th:text="${pageInfo.total}"></span></div>
<div>总页数:<span th:text="${pageInfo.pages}"></span></div>
<hr />
<div>是否为第一页:<span th:text="${pageInfo.isFirstPage}"></span></div>
<div>是否为最后一页:<span th:text="${pageInfo.isLastPage}"></span></div>
<div>是否有前一页:<span th:text="${pageInfo.hasPreviousPage}"></span></div>
<div>是否有下一页:<span th:text="${pageInfo.hasNextPage}"></span></div>
我把相关方法也写出来了,自己选择使用就好。
运行项目看效果:
这是使用的thymeleaf语法来集成PageHelper实现的分页,很多从JSP转thymeleaf的同学可以直接使用这个代码就好了。
说明一点哈,这些都是需要引入CSS,js,jquery之类的,基本上版本通用的,PageHelper官网就有,不要不引入就来跟我说没有效果。
PageHelper官网:https://pagehelper.github.io/docs/howtouse/
第二种 页神器DataTables(通用版)
下面介绍这个是DataTables表格组件,也是可以用来做分页的。前端分页也常用。也是需要快速实现功能的小伙伴直接复制粘贴就是。
1.后台查询数据
首先后台查询到数据,封装到map,传到jsp/html等页面。
如图:
2.前端页面Jsp遍历数据:
记得使用EL表达式。
可能在说的太快了,这里分解一下。
3.在html/jsp页面的详细使用步骤:
在你的项目中使用 DataTables,只需要引入三个文件即可,jQuery库,一个DT的核心js文件和一个DT的css文件,
源码:
<!-- 分页查看 -->
<link rel="stylesheet" type="text/css" href="resources/js/dataTable/jquery.dataTables.min.css">
<script type="text/javascript" src="resources/js/dataTable/jquery.js"></script>
<script type="text/javascript" src="resources/js/dataTable/jquery.dataTables.min.js"></script>
3.2.在表格的地方添加class和id属性。(必须写thead,tbody)
固定的class=“tablelist” id=“example”
源码:
<table cellspacing="0px" cellpadding="0px" border="1px" width="100%" class="tablelist" id="example">
<thead>
<tr>
<th>课程ID</th>
<th>课程名</th>
<th>方向</th>
<th>描述</th>
<th>时长(小时)</th>
<th>操作人</th>
</tr>
</thead>
<tbody>
<c:forEach items="${cList }" var="course">
<tr>
<td>${course.courseId }</td>
<td>${course.courseName }</td>
<td>${course.courseType }</td>
<td>${course.description }</td>
<td>${course.courseTime }</td>
<td>${course.operator }</td>
</tr>
</c:forEach>
</tbody>
</table>
3.3.添加分页的script即可。
<script type="text/javascript">
$(document).ready(function(){
$("#example").dataTable({
"bProcessing" : true, //DataTables载入数据时,是否显示‘进度’提示
"aLengthMenu" : [5, 10, 15], //更改显示记录数选项
"sPaginationType" : "full_numbers", //详细分页组,可以支持直接跳转到某页
"bAutoWidth" : true, //是否自适应宽度
//"bJQueryUI" : true,
"oLanguage": { //国际化配置
"sProcessing" : "正在获取数据,请稍后...",
"sLengthMenu" : "显示 _MENU_ 条",
"sZeroRecords" : "没有您要搜索的内容",
"sInfo" : "从 _START_ 到 _END_ 条记录 总记录数为 _TOTAL_ 条",
"sInfoEmpty" : "记录数为0",
"sInfoFiltered" : "(全部记录数 _MAX_ 条)",
"sInfoPostFix" : "",
"sSearch" : "搜索",
"sUrl" : "",
"oPaginate": {
"sFirst" : "第一页",
"sPrevious" : "上一页",
"sNext" : "下一页",
"sLast" : "最后一页"
}
},
});
});
</script>
其他可以参考官网:http://www.datatables.club/example/diy.html
一些属性参数说明:
默认情况下 Datatables 的分页就是上一页、下一页和6个页数按钮,这适合大部分情况。
不过也有用户不喜欢这样,Datatables提供了四个模式供用户选择,通过设置pagingType选项来配置。
- numbers - 只有只有数字按钮
- simple - 只有上一页、下一页两个按钮
- simple_numbers - 除了上一页、下一页两个按钮还有页数按钮,Datatables默认是这个
- full - 有四个按钮首页、上一页、下一页、末页
- full_numbers - 除首页、上一页、下一页、末页四个按钮还有页数按钮
- first_last_numbers - 除首页、末页两个按钮还有页数按钮
还有一些常用操作:
1.开启水平滚动条,设置scrollX选项 加入css样式 th, td { white-space: nowrap; } ,使文字内容在一行里,实现动态高度。
2.通常你可能会想要你的表格跟着页面大小的变化而变化。下面的例子展示了,表格设置了width为100%,表格随着页面的大小变化自动适应。 Tips:试着改变浏览器窗口的大小看看效果
3.可以使用language选项来国际化Datatables的相关信息
3.4.点击行获取数据:
(多写的取值例子,为了方便小伙伴们)
$(document).ready(function() {
var table = $('#example').DataTable();
$('#example tbody').on('click', 'tr', function () {
var data = table.row( this ).data();
alert( 'You clicked on '+data[0]+'\'s row' );
} );
} );
直接复制粘贴过去即可实现分页效果,而且还带有查询等功能。
DataTables 默认情况已启用一些功能,搜索、 排序、 分页等功能已经开启。
最后效果如下:
上面就说完了这一种使用DataTables的分页方式。需要快速实现功能的,你就复制粘贴吧。
也需要引入对应css、js的。
需要的可以官网下载或者留下邮箱我发给你。
第三种 使用Bootstrap Table表格分页
JavaScript 表格控件可以操作大数据集的 HTML表格,提供各种功能,如分页、排序、过滤以及行编辑。
比如最常用的3款:
- datatables:http://www.datatables.club/
- Bootstra Table:http://bootstrap-table.wenzhixin.net.cn/zh-cn/home/
- EasyU DataGrid: http://www.jeasyui.net/plugins/183.html
使用步骤:
1.Html中声明table
<table id="table"></table>
2.Jquery中初始化bootstrap table:
源码如下:
<script>
var $table = $('#table');
// bootstrap table初始化
// http://bootstrap-table.wenzhixin.net.cn/zh-cn/documentation/
$table.bootstrapTable({
url: '/listUser',
height: getHeight(),
striped: true, //设置为 true 会有隔行变色效果
undefinedText: "数据为空",//当数据为 undefined 时显示的字符
search: true,
searchOnEnterKey: true,
showRefresh: true,
showToggle: true,//是否显示切换试图(table/card)按钮
showColumns: true,//是否显示 内容列下拉框
// showPaginationSwitch:true,//是否显示 数据条数选择框
minimumCountColumns: 2,
showPaginationSwitch: true,
clickToSelect: true,
detailView: true,
detailFormatter: 'detailFormatter',
pagination: true,//分页
pageSize: 8, //如果设置了分页,页面数据条数
pageList: [5, 10, 20, 40], //如果设置了分页,设置可供选择的页面数据条数。设置为All 则显示所有记录。
paginationLoop: false,//设置为 true 启用分页条无限循环的功能
// singleSelect: false,//设置True 将禁止多选
data_local: "zh-US",//表格汉
search: true, //显示搜索框
classes: 'table table-hover table-no-bordered',
//sidePagination: 'server',
//silentSort: false,
smartDisplay: false,
idField: 'id', //指定主键列
sortName: 'id',
sortOrder: 'desc',
escape: true,
searchOnEnterKey: true,
idField: 'systemId',
maintainSelected: true,
toolbar: '#toolbar',
columns: [
{field: 'state', checkbox: true},
{field: 'realname', title: '真实姓名', sortable: true, halign: 'center'},
{field: 'username', title: '账号', sortable: true, halign: 'center'},
{field: 'password', title: '密码', sortable: true, halign: 'center'},
{field: 'address', title: '地址', sortable: true, halign: 'center'},
{field: 'createtime', title: '创建时间', sortable: true, halign: 'center'},
{field: 'action', title: '操作', halign: 'center', align: 'center', formatter: 'actionFormatter', events: 'actionEvents', clickToSelect: false}
]
}).on('all.bs.table', function (e, name, args) {
$('[data-toggle="tooltip"]').tooltip();
$('[data-toggle="popover"]').popover();
});
});
3.后台:查询数据,返回json字符串
必须返回json字符串或json对象
@ResponseBody
@RequestMapping(value = "listUser", method = RequestMethod.GET)
public String listUser(HttpServletRequest request, HttpServletResponse response) {
List<User> userList = userService.getAll();
System.out.println("分页数据:" + userList);
return JSON.toJSONString(userList);
}
效果图如下
自带pagination分页:
模糊查询:
都是需要引入js、css等的,但是这些都是可以在官网上下载的,我就不贴出来了。主要是代码,你可以在复制过去直接使用,免得以后做项目还得重新写分页,麻烦。
**多种不同的分页方式就写完了,实际上,thymeleaf适用的,jsp、 html页面都可以适用。照着文章复制去用即可。**
原文链接:https://blog.csdn.net/ITBigGod/article/details/85224897