众筹网_管理员信息维护_分页

一、目标

以分页的形式把管理员信息显示到页面上。
特殊需求:兼顾关键词查询,让后端代码不管有没有查询条件都能够以分页形式显示数据。

二、思路

  • 流程图

 

三、代码

  • 引入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插件的原理:
  1. MyBatis提供了拦截器,写这个拦截器可以使SQL语句发送到数据库执行之前拦截住它,做一些修改,再让它执行
  2. 通过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
  1. int的默认值为0,而Integer的默认值为null,即Integer可以区分出未赋值和值为0的区别,int则无法表达出未赋值的情况,故int不适合作为web层的表单数据的类型;
  2. Integer提供了多个与整数相关的操作方法,例如,将一个字符串转换成整数,Integer中还定义了表示整数的最大值和最小值的常量;
  3. 泛型支持Integer,并不支持int。如:ArrayList list = new ArrayList();不能在泛型中写int;
  4. Integer是int的包装类,int则是java的一种基本数据类型;
  5. 声明为Integer的变量需要实例化,而声明为int的变量不需要实例化;
  6. 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>
  1. action=admin/get/page.html method="post"
  2. name="keyword"
  3. type="submit"
  4. 关键:翻页时也要带上关键词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"),一般是从服务器传递结果到页面,在页面中取出服务器端保存的值!

posted on 2021-07-25 18:29  魔法师多尼se  阅读(69)  评论(0)    收藏  举报