尚筹网02管理员维护

任务清单

  • 分页显示Admin数据
    •   不带关键词分页
    •   带关键词分页
  • 新增Admin
  • 更新Admin
  • 单挑删除Admin

分页

目标

以分页的形式把管理员信息显示到页面上.

特殊需求:兼顾关键词查询,让后端代码不管有没有查询条件都能够以分页形式显示数据.

思路 

尚筹网02管理员维护

 

  • 点击用户维护
    •   跳转到admin-page.jsp,在页面初始化的时候把分页数据也加载出来
  • 在page页面查询关键词的时候,提交给后台,然后在页面初始化的时候把分页数据加载出来
  • 点击上一页下一页,把页面pageNum(和keyword)提交给后台,然后在页面初始化的时候把分页数据加载出来

技术点

  • 让SQL语句针对keyword时有时无的情况进行适配
    •   使用SQL中做字符串连接的函数:CONCAT(“%”,#{keyword},”%”)
    •   keyword有值:“like %tom%“
    •   Key 无值:”like %%“
  • pageHelper使用
    •   引入依赖
    •   在SqlSessionFactoryBean中配置PageHelper
    •   在Java代码中使用
      •     PageHelper.startPage(PageNum,PageSize)
      •     PageInfo<Admin> pageInfo = new PageInfo(adminList);
  • 显示页码
    •   使用JQuery插件:Pagination 

后端代码

查询Admin数据的SQL语句

尚筹网02管理员维护

<select id= "selectAdminByKeyword" resultMap="BaseResultMap">
    select
    <include refid="Base_Column_List"/>
    from t_admin
    where login_acct like CONCAT("%",#{keyword},"%")
    or
    user_name like CONCAT("%",#{keyword},"%")
    or
    email like CONCAT("%",#{keyword},"%")
</select>

准备PageHelper环境

1、导入坐标

尚筹网02管理员维护

<!--mybatis 分页插件-->
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>5.1.11</version>
</dependency>

 2、配置SqlSessionFactoryBean

尚筹网02管理员维护

<!-- 配置 MyBatis 的插件 -->
        <property name="plugins">
            <array>
                <!-- 配置 PageHelper -->
                <bean class="com.github.pagehelper.PageInterceptor">
                    <property name="properties">
                        <value>
                             <!-- 分页插件会自动检测当前的数据库链接,自动选择合适的分页方式。 
                            你可以配置helperDialect属性来指定分页插件使用哪种方言。配置时,可以使用下面的缩写值:
                                oracle,mysql,mariadb,sqlite,hsqldb,postgresql,db2,sqlserver,informix,h2,sqlserver2012,derby
                                特别注意:使用 SqlServer2012 数据库时,需要手动指定为 sqlserver2012,否则会使用 SqlServer2005 的方式进行分页。 -->
                            helperDialect=mysql
                            <!-- 默认false禁用 启用合理化时,如果pageNum<1会查询第一页,
                            如果pageNum>pages会查询最后一页 禁用合理化时,如果pageNum<1或pageNum>pages会返回空数据 -->
                            reasonable=true
                             <!-- 支持通过 Mapper 接口参数来传递分页参数,默认值false,分页插件会从查询方法的参数值中,自动根据上面 params
                                配置的字段中取值,查找到合适的值时就会自动分页。 使用方法可以参考测试代码中的 
                                com.github.pagehelper.test.basic
                                包下的 ArgumentsMapTest 和 ArgumentsObjTest。 -->
                            supportMethodsArguments=true
                            <!-- 为了支持startPage(Object params)方法,增加了该参数来配置参数映射,
                            用于从对象中根据属性名取值, 可以配置
                                pageNum,pageSize,count,pageSizeZero,reasonable,不配置映射的用默认值,
                                 默认值为pageNum=pageNum;pageSize=pageSize;count=countSql;
                                 reasonable=reasonable;pageSizeZero=pageSizeZero。 -->
                            params=count=countSql
                            <!-- 默认值为 false。设置为 true 时,允许在运行时根据多数据源自动识别对应方言的分页 
                            (不支持自动选择sqlserver2012,只能使用sqlserver)。 -->
                            autoRuntimeDialect=true
                        </value>
                    </property>
                </bean>
            </array>
        </property>

3、AdminService方法

尚筹网02管理员维护

@Override
public PageInfo<Admin> selectAdminByKeyWord(String keyWord, Integer pageNum, Integer pageSize) {
    // 1. 开启pageHelper的静态方法,开启分页功能
    PageHelper.startPage(pageNum,pageSize);

    // 2. 执行查询
    List<Admin> admins = adminMapper.selectAdminByKeyWord(keyWord);

    // 3. 封装到pageInfo对象中
    PageInfo<Admin> pageInfo = PageInfo.of(admins);

    return pageInfo;
}

4、AdminController

@RequestMapping("/admin/get/page.html")
public String getPageInfo(
        //注意:页面上有可能不提供关键词,要进行匹配
        //@RequestParam注解中设置defaultValue属性为空字符串表示不提供关键词
        @RequestParam(value = "keyword", defaultValue = "") String keyword,
        //默认从第一页开始
        @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
        @RequestParam(value = "pageSize", defaultValue = "2") Integer pageSize,
        ModelMap modelMap) {

    // 1. 获取pageInfo
    PageInfo<Admin> adminPageInfo = adminService.selectAdminByKeyWord(keyword, pageNum, pageSize);
    // 2. 将pageInfo存入Model
    modelMap.addAttribute(ConstantUtil.ATTR_NAME_PAGEINFO, adminPageInfo);

    return "/admin-page";
}

5、前端代码

尚筹网02管理员维护

根据返回的pageInfo数据,拼接成表进行显示

<tbody>
<c:if test="${empty requestScope.pageInfo.list}">
    <tr>
        <td colspan="6" align="center"> 抱歉!没有查询到你要的数据</td>
    </tr>
</c:if>
<c:if test="${!empty requestScope.pageInfo.list}">
    <c:forEach items="${requestScope.pageInfo.list}" var="admin" varStatus="myStatus">
        <tr>
            <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>--%>
                <a href="assign/to/assign/role/page.html?adminId=${admin.id}&pageNum=${requestScope.pageInfo.pageNum}&keyword=${param.keyword}"
                   class="btn btn-success btn-xs"><i class=" glyphicon glyphicon-check"></i></a>
                    <%--<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>--%>
                <a href="admin/to/edit/page.html?adminId=${admin.id}&pageNum=${requestScope.pageInfo.pageNum}&keyword=${param.keyword}"
                   class="btn btn-primary btn-xs"><i
                        class=" glyphicon glyphicon-pencil"></i></a>
                <a href="admin/remove/${admin.id}/${requestScope.pageInfo.pageNum}/${param.keyword}.html"
                   class="btn btn-danger btn-xs"><i class=" glyphicon glyphicon-remove"></i></a>
            </td>
        </tr>
    </c:forEach>
</c:if>
</tbody>

6、加入Pagination插件环境

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html lang="zh_CN">
<%@include file="/WEB-INF/pages/admincommon/include-head.jsp" %>
<link rel="stylesheet" href="static/css/pagination.css"/>
<script type="text/javascript" src="static/jquery/jquery.pagination.js"></script>
<script type="text/javascript">

7、编写pagination代码

<script type="text/javascript">   
$(function () { initPagination(); }); //生成分页导航条函数 function initPagination() { //获取总记录数 var totalRecord = ${requestScope.pageInfo.total}; var properties = { num_edge_entries: 3, //边缘页数 num_display_entries: 5, //主体页数 callback: pageselectCallback, items_per_page:${requestScope.pageInfo.pageSize}, //每页显示1项 current_page: ${requestScope.pageInfo.pageNum - 1},//Pagination内部使用pageIndex来管理页面 prev_text: "上一页", next_text: "下一页" } // 生成页码导航条 $("#Pagination").pagination(totalRecord, properties); } //pageIndex 0- function pageselectCallback(pageIndex, jQuery) { //根据pageIndex计算pageNum var pageNum = pageIndex + 1; //跳转页面 window.location.href = "admin/get/page.html?pageNum=" + pageNum + "&keyword=${param.keyword}"; //由于每个按钮都是超链接,所以这里取消超链接的默认行为
    //由于会回调函数,且我们这里时跳转页面,因此会不断重复
    //解决方法是return false取消默认回调的行为
return false } </script>

 

关键词查询

页面调整待提交的表单

尚筹网02管理员维护

<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 name="keyword" class="form-control has-success" type="text"
                   placeholder="请输入查询条件">
        </div>
    </div>
    <button type="submit" class="btn btn-warning"><i class="glyphicon glyphicon-search"></i> 查询
    </button>
</form>

翻页时保持keyword值

//pageIndex 0-
function pageselectCallback(pageIndex, jQuery) {
    //根据pageIndex计算pageNum
    var pageNum = pageIndex + 1;
    //跳转页面
    //EL表达式中的param也是一个隐含对象,可以用来获取请求参数
    window.location.href = "admin/get/page.html?pageNum=" + pageNum + "&keyword=${param.keyword}";
    //由于每个按钮都是超链接,所以这里取消超链接的默认行为
    return false;
}

注意:EL表达式中的param是一个隐含的对象,可以用来获取请求参数.

 

新增管理员信息

目标

创建新的管理员信息,通过表单

思路

尚筹网02管理员维护

代码

设置唯一约束

Alter table ‘表名’ add unique index(‘字段名’) 

业务层逻辑 

尚筹网02管理员维护

@Override
public void saveAdmin(Admin admin) {
   //生成系统当前时间
    Date date = new Date();
    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    String createTime = format.format(date);
    admin.setCreateTime(createTime);

    //针对登陆密码进行加密
    String source = admin.getUserPswd();
    String encoded = MD5Util.md5(source);
    admin.setUserPswd(encoded);
    //执行保存,如果账号被占用会抛出异常
    try{
        adminMapper.insert(admin);
    }catch(Exception e){
        e.printStackTrace();
        //检测当前捕获的异常对象,如果是DuplicateKeyException类型说明账号重复导致
        if (e instanceof DuplicateKeyException){
            //抛出自定义的LoginAcctAlreadyExist
            throw new LoginAccountAlreadlyInUse(ConstantUtil.MESSAGE_SYSTEM_ERROR_LOGIN_NOT_UNIQUE);
        }
        //如果不是则继续往上抛
        throw e;
    }
}

异常映射处理器类

尚筹网02管理员维护

当抛出对应异常时,会被异常拦截器捕捉

@ExceptionHandler(LoginAccountAlreadlyInUse.class)
public ModelAndView resolverLoginAccountAlreadlyInUseException(LoginAccountAlreadlyInUse e, HttpServletRequest request, HttpServletResponse response) throws IOException {
    String viewName = "admin-add";
    ModelAndView modelAndView = common(viewName, e, request, response);
    return modelAndView;
}
/**
 * 提取可复用部分
 * @return
 */
public ModelAndView common(String viewName, Exception e, HttpServletRequest request, HttpServletResponse response) throws IOException {
    boolean requestType = CrowdUtil.isAjaxRequest(request);
    if (requestType) {
        ResultEntity<Object> failed = ResultEntity.failed(e.getMessage());
        String json = new Gson().toJson(failed);
        response.getWriter().write(json);
        return null;
    } else {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("exception", e);
        modelAndView.setViewName(viewName);
        return modelAndView;
    }
}

自定义异常

尚筹网02管理员维护

控制层

 

@RequestMapping("/save/admin.html")
public String saveAdmin(Admin admin) {
    //执行保存
    adminService.saveAdmin(admin);
    // 为了让用户第一眼就看到新增加的用户,直接跳转到最后一页
    return "redirect:/admin/page.html?pageNum=" + Integer.MAX_VALUE;
}

保存之后重定向

"redirect:/admin/page.html?pageNum=" + Integer.MAX_VALUE;

表单页面

尚筹网02管理员维护

配置跳转
<mvc:view-controller path="/admin/to/add/page.html" view-name="admin-add"/>

 

更新删除管理员信息

目标

通过提交页面上的表单修改某个Admin的数据

思路

尚筹网02管理员维护

  • 在admin-page.jsp页面点击修改,带着id到后台,查询出对应的admin
  • 把admin保存在request域
  • 重定向到edit页面并填充
  • 当点击修改时到后台执行更新
  • 重定向到page页面
    •   为了保持所在页和关键词还需要pageNum和keyword

 

  • 重定向到main-page.jsp点击删除(携带id)
  • 提交到后台处理完,重定向到page页面
    •   什么时候使用重定向,不需要再返回操作,不需要request的数据

 

代码

尚筹网02管理员维护

<a href="admin/to/edit/page.html?adminId=${admin.id}&pageNum=${requestScope.pageInfo.pageNum}&keyword=${param.keyword}"
   class="btn btn-primary btn-xs"><i
        class=" glyphicon glyphicon-pencil"></i></a>
<a href="admin/remove/${admin.id}/${requestScope.pageInfo.pageNum}/${param.keyword}.html"
   class="btn btn-danger btn-xs"><i class=" glyphicon glyphicon-remove"></i></a>

controller

@RequestMapping("/admin/to/edit/page.html")
    public String toAdminEdit(@RequestParam("adminId") Integer adminId, ModelMap map) {
        // 1.根据 id(主键)查询待更新的 Admin 对象
        Admin admin = adminService.selectAdminById(adminId);
        // 2.将 Admin 对象存入模型
        map.addAttribute("admin", admin);
        return "admin-edit";
    }
//
    @RequestMapping("/admin/update.html")
    public String editAdmin(Admin admin,
                            @RequestParam("pageNum") Integer pageNum,
                            @RequestParam("keyword") String keyword,
                            ModelMap map) {

        adminService.updateAdmin(admin);
        return "redirect:/admin/get/page.html?pageNum=" + pageNum + "&keyword=" + keyword;
    }
@RequestMapping("/admin/remove/{id}/{pageNum}/{keyword}")
public String deleteAdmin(@PathVariable("id") Integer id,
                          @PathVariable("pageNum") Integer pageNum,
                          @PathVariable(value = "keyword") String keyword) {
    adminService.deleteAdminByPrimaryKey(id);

    return "redirect:/admin/get/page.html?pageNum=" + pageNum + "&keyword=" + keyword;
}

service

@Override
public void deleteAdminByPrimaryKey(Integer id) {
    adminMapper.deleteByPrimaryKey(id);
}

@Override
public Admin selectAdminById(Integer adminId) {
    Admin admin = adminMapper.selectByPrimaryKey(adminId);
    return admin;
}

@Override
public void updateAdmin(Admin admin) {

    try {
        adminMapper.updateByPrimaryKeySelective(admin);
    } catch (Exception e) {
        if (e instanceof DuplicateKeyException) {
            throw new LoginAccountAlreadlyInUseForUpdate("不允许重复的账户");
        }
    }
}

 

尚筹网02管理员维护

 

上一篇:解决高并发-springboot-redis-mysql医院预约系统项目超详细讲解--半个小时教你如何使用sp--第二章ringboot完成预约项目---:页面显示所有医生加分类查询功能


下一篇:django之分页过滤