众筹网_管理员信息维护_分页
一、目标
以分页的形式把管理员信息显示到页面上。
特殊需求:兼顾关键词查询,让后端代码不管有没有查询条件都能够以分页形式显示数据。
二、思路
- 流程图

三、代码
- 引入PageHelper插件依赖(MyBatis插件)
<!-- MyBatis 分页插件 --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> </dependency>
- 在SqlSessionFactoryBean中配置PageHelper插件
<!-- 配置 SqlSessionFactoryBean --> <bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 装配数据源 --> <property name="dataSource" ref="dataSource" /> <!-- 指定 MyBatis 全局配置文件位置 --> <property name="configLocation" value="classpath:mybatis-config.xml" /> <!-- 指定 Mapper 配置文件位置 --> <property name="mapperLocations" value="classpath:mapper/*Mapper.xml" /> <!-- 配置插件 --> <property name="plugins"> <array> <!-- 配置PageHelper插件 --> <!-- 内部bean可以不写id --> <bean class="com.github.pagehelper.PageHelper"> <!-- 配置相关属性 --> <property name="properties"> <props> <!-- 配置数据库方言,告诉 PageHelper 当前使用的具体数据库, --> <!-- 让 PageHelper 可以根据当前数据库生成对应的分页SQL语 句 --> <prop key="dialect">mysql</prop> <!-- 配置页码的合理化修正,自动把浏览器传来的 PageNum 修正到 0~总页数范围 --> <prop key="reasonable">true</prop> </props> </property> </bean> </array> </property> </bean>
- 注:PageHelper插件的原理:
- MyBatis提供了拦截器,写这个拦截器可以使SQL语句发送到数据库执行之前拦截住它,做一些修改,再让它执行
- 通过PageHelper.startPage(pageNum, pageSize)开启分页,增加limit语句部分
- AdminMapper.xml中编写SQL语句,并在AdminMapper中补上该接口,形成映射
<!-- 该部分<sql>是逆向工程自动生成的 -->
<sql id="Base_Column_List"> id, login_acct, user_pswd, user_name, email, create_time </sql>
<!-- 有关limit的语句已经由PageHelper写好了,我们只需要写select语句 -->
<!-- 这个BaseResultMap是逆向工程里自带的 --> <select id="selectAdminListByKeyword" resultMap="BaseResultMap"> select <include refid="Base_Column_List" /> from t_admin where
<!-- CONCAT是sql里拼字符串的函数 -->
<!-- 这样可以做到兼容有关键字查询和无关键字查询 --> login_acct like CONCAT("%",#{keyword},"%") or user_name like CONCAT("%",#{keyword},"%") or email like CONCAT("%",#{keyword},"%") </select
List<Admin> selectAdminListByKeyword(String keyword);
- AdminServiceImpl.java
// PageInfo内部封装了List类型的属性来放Admin
@Override public PageInfo<Admin> getPageInfo(String keyword, Integer pageSize, Integer pageNum) { // 1.调用PageHelper的静态方法开启分页功能 // 这里体现了PageHelper的"非侵入式"设计:原本的查询代码不必有任何修改,要分页就加上这句话,不分页去掉就行了 PageHelper.startPage(pageNum, pageSize); // 2.执行查询 // 老师说这个AdminListByKeyword是Page类型的,Page继承了ArrayList,所以可以直接赋值给List,这是多态 List<Admin> AdminListByKeyword = adminMapper.selectAdminListByKeyword(keyword); //Page<Admin> AdminListByKeyword = adminMapper.selectAdminListByKeyword(keyword); // 3.封装到PagInfo对象中 return new PageInfo<Admin>(AdminListByKeyword); }
- 注:int与Integer
- int的默认值为0,而Integer的默认值为null,即Integer可以区分出未赋值和值为0的区别,int则无法表达出未赋值的情况,故int不适合作为web层的表单数据的类型;
- Integer提供了多个与整数相关的操作方法,例如,将一个字符串转换成整数,Integer中还定义了表示整数的最大值和最小值的常量;
- 泛型支持Integer,并不支持int。如:ArrayList list = new ArrayList();不能在泛型中写int;
- Integer是int的包装类,int则是java的一种基本数据类型;
- 声明为Integer的变量需要实例化,而声明为int的变量不需要实例化;
- Integer实际是对象的引用,当new一个Integer时,实际上是生成一个指针指向此对象;而int则是直接存储数据值.
- AdminHandler.java
@RequestMapping("admin/get/page/html")
public String getPageInfo(
// 页面上有可能没提供关键词,要进行适配
@RequestParam(value="keyword",defaultValue="")String keyword,
// 浏览器未提供 pageSize 时,默认每页显示5条记录
@RequestParam(value="pageSize",defaultValue="6")Integer pageSize,
// 浏览器未提供 pageNum 时,默认前往第1页
@RequestParam(value="pageNum", defaultValue="1") Integer pageNum,
ModelMap modelMap
) {
// 查询得到分页的管理员数据pageInfo(pageInfo中封装有AdminListByKeyword,不封装的话,无法用EL表达式取得List<Admin>)
PageInfo<Admin> pageInfo = adminService.getPageInfo(keyword, pageSize, pageNum);
// 将分页数据存入模型
modelMap.addAttribute(CrowdConstant.ATTR_NAME_PAGE_INFO, pageInfo);
return "admin-page";
}
- 抽取页面公共部分新建JSP模板
1.打开preferences

2.注:选New JSP

- 在现成的html文件中复制整块前端代码的步骤(我要复制的是main这块的代码):
1.右键->检查

2.鼠标选中main这部分->右键->编辑HTML

3.替换这部分main代码

- admin-page.jsp 页面显示主体数据
1. 引入JSTL(打完引号就按ALT+1) (记得引入JSTL依赖,此处不赘述)
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
2.管理员列表
<thead> <tr> <th width="30">#</th> <th width="30"><input type="checkbox"></th> <th>账号</th> <th>名称</th> <th>邮箱地址</th> <th width="100">操作</th> </tr> </thead> <tbody> <!-- ${empty requestScope.pageInfo.list }判断是否为空 --> <c:if test="${empty requestScope.pageInfo.list }"> <tr> <!-- colspan="2"表示合并单元格 --> <td colspan="2">抱歉!没有查询到相关的数据!</td> </tr> </c:if> <c:if test="${!empty requestScope.pageInfo.list }"> <!-- varStatus="myStatus"用于循环计数 --> <c:forEach items="${requestScope.pageInfo.list }" var="admin" varStatus="myStatus"> <tr> <!-- ${myStatus.count }是单纯的循环计数器,这样是用来代替主键 --> <td>${myStatus.count }</td> <td><input type="checkbox"></td> <td>${admin.loginAcct }</td> <td>${admin.userName }</td> <td>${admin.email }</td> <td> <button type="button" class="btn btn-success btn-xs"> <i class=" glyphicon glyphicon-check"></i> </button> <button type="button" class="btn btn-primary btn-xs"> <i class=" glyphicon glyphicon-pencil"></i> </button> <button type="button" class="btn btn-danger btn-xs"> <i class=" glyphicon glyphicon-remove"></i> </button> </td> </tr> </c:forEach> </c:if> </tbody> <tfoot>
- admin-page.jsp 使用Pagination工具实现分页导航栏前端显示
- 引入环境
<%@include file="/WEB-INF/include-head.jsp"%> <link rel="stylesheet" href="css/pagination.css"> <script type="text/javascript" src="jquery/jquery.pagination.js"></script>
- 编写 Pagination 代码
<script type="text/javascript"> $(function(){ // 调用专门的函数初始化分页导航条 initPagination(); }); // 声明一个函数用于初始化Pagination function initPagination() { // 获取分页数据中的总记录数 var totalRecord = ${requestScope.pageInfo.total}; // 声明 Pagination 设置属性的 JSON 对象 var properties = { num_edge_entries: 3, // 边缘页数 num_display_entries: 5, // 主体页数 callback: pageSelectCallback, // 用户点击“翻页”按钮之后 执行翻页操作的回调函数 current_page: ${requestScope.pageInfo.pageNum-1}, // 当前页,pageNum 从 1 开始, 必须-1 后才可以赋值 prev_text: "上一页", next_text: "下一页", items_per_page:${requestScope.pageInfo.pageSize} // 每页显示 1 项 }; // 调用分页导航条对应的 jQuery 对象的 pagination()方法生成导航条 $("#Pagination").pagination(totalRecord, properties); } // 翻页过程中执行的回调函数 // 点击“上一页”、“下一页”或“数字页码”都会触发翻页动作,从而导致当前函数被调用 // pageIndex 是用户在页面上点击的页码数值 function pageSelectCallback(pageIndex, jQuery) { // pageIndex 是当前页页码的索引,相对于 pageNum 来说,pageIndex 比 pageNum 小 1 var pageNum = pageIndex + 1; // 执行页面跳转也就是实现“翻页” window.location.href = "admin/get/page.html?pageNum="+pageNum+"&keyword=${param.keyword}"; // 取消当前超链接的默认行为 return false; } </script>
- 显示分页导航栏
<tr> <td colspan="6" align="center"> <div id="Pagination" class="pagination"> <!-- 这里显示分页 --> </div> </td> </tr>
- 问题:
- 解决:不让 Pagination 在页码导航条初始化完成时就调用回调函数!(jquery.pagination.js)
else { return false; } } // 所有初始化完成,绘制链接 drawLinks(); // 回调函数 //opts.callback(current_page, this);
- admin-page.jsp 提交查询的表单,实现关键词查询
<form action=admin/get/page.html method="post" class="form-inline" role="form" style="float: left;"> <div class="form-group has-feedback"> <div class="input-group"> <div class="input-group-addon">查询条件</div> <input class="form-control has-success" name="keyword" type="text" placeholder="请输入查询条件"> </div> </div> <button type="submit" class="btn btn-warning"> <i class="glyphicon glyphicon-search"></i> 查询 </button> </form>
-
action=admin/get/page.html method="post" -
name="keyword" -
type="submit" - 关键:翻页时也要带上关键词keyword
// 执行页面跳转也就是实现“翻页” window.location.href = "admin/get/page.html?pageNum="+pageNum+"&keyword=${param.keyword}";
因为是同一个请求,所以可以用param获取请求参数.EL 表达式中的 param 也是一个隐含对象,可以用来获取请求参数!
- 注:关于EL表达式中的param和requestScope?
1. getParameter:
可以获取URL中传递过来的String参数,如:http://www.baidu.com?username=abc 中的abc;
对于POST/GET提交的表单,在服务器端我们都可以通过request.getParameter获取表单中的值。
2. getAttribute:
获取的是一个对象(Object);
请求转发的时候,可以使用request.setAttribute传递参数。
3. 结论
${param.name} 等价于 request.getParamter("name"),一般用于服务器从页面或者客户端获取的内容,这些内容都是String的。
${requestScope.name} 等价于 request.getAttribute("name"),一般是从服务器传递结果到页面,在页面中取出服务器端保存的值!
浙公网安备 33010602011771号