任务清单
-
分页显示数据功能的实现
1.不带关键词分页
2.带关键词分页
-
单条删除Admin数据
-
新增Admin数据
-
更新Admin数据
一、分页显示数据
1.1目标
将数据库中的Admin数据在前端分页显示,在后端带“关键词”的和“不带关键词”的用同一套代码进行分页显示
1.2思路
1.3代码
1.1 引入pageHelper插件
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
</dependency>
1.2 在SqlSessionFactoryBean配置pageHelper
<!-- 配置插件-->
<property name="plugins">
<array>
<!-- 配置pageHelper插件-->
<bean class="com.github.pagehelper.PageHelper">
<property name="properties">
<props>
<!-- 配置数据库方言,告诉PageHelper目前使用的数据库-->
<prop key="dialect">mysql</prop>
<!-- 配置页码的合理化修正,在1~总页数之间修正-->
<prop key="reasonable"></prop>
</props>
</property>
</bean>
</array>
</property>
1.3 写sql语句
<select id="selectAdminKeyWord" resultMap="BaseResultMap">
select id, login_acct, user_pswd, user_name, email, create_time
from t_admin
where login_acct like concat("%",#{keyword},"%") or
user_name like concat("%",#{keyword},"%") or
email like concat("%",#{keyword},"%")
</select>
1.4 service层
AdminService
/**
* keyword:搜索的关键词信息
* pageNum:总页数
* pageSize每页显示的条数
* */
PageInfo<Admin> getPageInfo(String keyword,Integer pageNum,Integer pageSize);
AdminServiceImpl
/**
* 分页显示
* */
@Override
public PageInfo<Admin> getPageInfo(String keyword, Integer pageNum, Integer pageSize) {
// 1.调用pageHelper的静态方法,开启分页
PageHelper.startPage(pageNum,pageSize);
// 2.执行查询
List<Admin> list = mapper.selectAdminKeyWord(keyword);
// 3.将查询的结果封装到pageInfo对象中
PageInfo pageInfo = new PageInfo(list);
//System.out.println("总页数:"+pageInfo.getPageNum());
return pageInfo;
}
1.5 Controller层
/**
* 分页显示方法
* */
@RequestMapping("/admin/get/page.html")
public String getPageInfo(
// 使用@RequestParam的defaultValue属性,指定默认值,
// 在请求中没有携带对应参数时使用默认值
// keyword默认使用空字符串和sql语句两种情况适配
@RequestParam(value = "keyword",defaultValue = "") String keyword,
@RequestParam(value = "pageNum",defaultValue = "1") Integer pageNum,
@RequestParam(value = "pageSize",defaultValue = "5") Integer pageSize,
ModelMap modelMap){
System.out.println("keyword="+keyword);
// 1.调用Service获取getInfo对象
PageInfo<Admin> pageInfo = adminService.getPageInfo(keyword, pageNum, pageSize);
// 2.将pageInfo对象存入模型
modelMap.addAttribute(CrowdConstant.ATTR_NAME_PAGE_INFO,pageInfo);
return "admin-page";
}
1.6 页面显示主体数据
1.6.1 引入Pagination插件用来显示导航条
1.6.2 在需要的页面引入
1.6.3 页面代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html>
<html lang="zh-CN">
<%@include file="/WEB-INF/jsp/include-head.jsp" %>
<link rel="stylesheet" href="css/pagination.css" />
<script type="text/javascript" src="jquery/jquery.pagination.js"></script>
<script type="text/javascript">
$(function (){
// 调用后面声明的函数对页码导航条进行初始化操作
initPageination();
})
// 1.生成页码导航条函数
function initPageination(){
// 获取总记录条数
var totalRecord =${requestScope.pageInfo.total};
// 声明一个JSON对象存储Pagination要设置的属性
var properties={
num_edge_entries: 3, //边缘页数
num_display_entries: 5, //主体页数
callback: pageSelectCallback, //指定用户点击翻页按
//钮时跳转页面的函数
items_per_page: ${requestScope.pageInfo.pageSize}, //每页显示的条数
current_page: ${requestScope.pageInfo.pageNum-1},
//pageNum是从1开始的,而pagination内部使用pageIndex来管理的,里面是从0开始的
prev_text: "上一页", //上一页按钮上显示的文本
next_text: "下一页" //下一页按钮上显示的文本
};
//生成页码导航条
$("#Pagination").pagination(totalRecord,properties);
}
// 2.用户点击“1”,“2”,“3”,,,这样的按钮时调用这个函数实现跳转
function pageSelectCallback(page_index,jQuery){
// 根据page_index来获取pageNum
var pageNum = page_index+1;
//跳转页面
window.location.href="admin/get/page.html?pageNum="+pageNum+"&keyword=${param.keyword}";
// 由于每一个页面都是超链接,所以在这个函数最后取消超链接的默认行为
return false;
}
</script>
<body>
<%@include file="/WEB-INF/jsp/include-nav.jsp" %>
<div class="container-fluid">
<div class="row">
<%@include file="/WEB-INF/jsp/include-sidebar.jsp" %>
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><i class="glyphicon glyphicon-th"></i> 数据列表</h3>
</div>
<div class="panel-body">
<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>
<button type="button" class="btn btn-danger" style="float:right;margin-left:10px;"><i class=" glyphicon glyphicon-remove"></i> 删除</button>
<%--旧代码--%>
<%--<button type="button" class="btn btn-primary" style="float:right;" onclick="window.location.href='add.html'"><i class="glyphicon glyphicon-plus"></i> 新增</button>--%>
<%--新代码--%>
<a style="float:right;" href="admin/toAdd.html" class="btn btn-primary"><i class="glyphicon glyphicon-plus"></i>新增</a>
<br>
<hr style="clear:both;">
<div class="table-responsive">
<table class="table table-bordered">
<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>
<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>
<%--myStatus.count:循环计数 1,2,3,4,5,,,,--%>
<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>
<%--ton type="button" class="btn btn-primary btn-xs"><i class=" glyphicon glyphicon-pencil"></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>
<%--<button id="btn1" type="button" class="btn btn-danger btn-xs"><i class=" glyphicon glyphicon-remove"></i></button>--%>
<a href="admin/get/delete/${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>
<tfoot>
<tr>
<td colspan="6" align="center">
<div id="Pagination" class="pagination"><!-- 这里显示分页 --></div>
<%--<ul class="pagination">
<li class="disabled"><a href="#">上一页</a></li>
<li class="active"><a href="#">1 <span class="sr-only">(current)</span></a></li>
<li><a href="#">2</a></li>
<li><a href="#">3</a></li>
<li><a href="#">4</a></li>
<li><a href="#">5</a></li>
<li><a href="#">下一页</a></li>
</ul>--%>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
二、单条删除admin数据
1. 目标
点击删除按钮删除,删除后回到删除的页数
2.思路
3.代码
3.1 前端删除按钮
3.2 Controller层
/*-----------------------删除数据-----------------------*/
/**
* 单击删除方法
* */
@RequestMapping("/admin/get/delete/{adminId}/{pageNum}/{keyword}.html")
public String adminDelete(@PathVariable("adminId") Integer adminId,
@PathVariable("pageNum") Integer pageNum,
@PathVariable("keyword") String keyword,
HttpSession session
){
Admin admin = (Admin) session.getAttribute(CrowdConstant.ATTR_NAME_LOGIN_ADMIN);
String userName = admin.getUserName();
System.out.println("当前登录用户:"+userName);
System.out.println("adminid="+adminId);
Integer id = admin.getId();
if (adminId==id){
throw new RuntimeException(CrowdConstant.DELETE_FAILED);
}
// 执行删除
int remove = adminService.remove(adminId);
// 页面跳转:回到分页页面
// 1.尝试方案一:直接发送到admin-page.jsp会无法显示分页数据
// return "admin-page"
// 2.尝试方案二:转发到/admin/get/page.html 一刷新页面会重复执行删除浪费性能
// 3.尝试方案三:转发到/admin/get/page.html 一刷新页面会重复执行删除浪费性能
// 为了保持原本所在页面和查询关键词再附加两个参数pageNum,keyword
return "redirect:/admin/get/page.html?pageNum="+pageNum+"&keyword="+keyword;
}
3.3 Service层
AdminService
int remove(Integer adminId);
AdminServiceImpl
/**
* 删除方法
* */
@Override
public int remove(Integer adminId) {
int i = mapper.deleteByPrimaryKey(adminId);
return i;
}
三、新增Admin数据
1.目标
将表单提交的Admin数据保存到数据库中
- 要求1.loginAcct不能重复
- 要求2.密码加密
2.思路
3.代码
3.1 前端新增按钮
3.2 Controller层
/*-----------------------新增数据-----------------------*/
/**
* 跳转页面--->新增页面
* */
@RequestMapping("/admin/toAdd.html")
public String toAdd(){
return "admin-add";
}
/**
* 保存页面
* */
@RequestMapping("/admin/save.html")
public String adminAdd(Admin admin){
// 将输入进来的密码加密
String userPswd = admin.getUserPswd();
String md5 = CrowdUtil.md5(userPswd);
// 将加密的密码保存
admin.setUserPswd(md5);
//生成时间
Date date = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
String format = dateFormat.format(date);
admin.setCreateTime(format);
//插入数据
try {
adminService.saveAdmin(admin);
} catch (Exception e) {
//e.printStackTrace();
if (e instanceof DuplicateKeyException){
throw new LoginAcctAlreadyUseException(CrowdConstant.MESSAGE_ACCT_ALREADY_IN_USE);
}
}
System.out.println("admin="+admin);
//为了新增之后可以直接跳转到新增的那一页数据
List<Admin> all = adminService.getAll();
int size = all.size();
int YeShu = size/5;
if (size%5!=0){
YeShu+=1;
}
return "redirect:/admin/get/page.html?pageNum="+YeShu;
}
3.3 Service层 AdminService
public interface AdminService {
void saveAdmin(Admin admin);
AdminServiceImpl
@Override
public void saveAdmin(Admin admin) {
mapper.insert(admin);
}
3.4 异常处理
四、更新Admin数据
1.目标
修改现有的Admin数据
- 要求1.不能修改时间和密码
- 要求2.不能修改成已有的loginAcct
2.思路
修改成已有用户时,抛出异常到system.error页面,返回上一步,数据还在,这样可以避免回显数据代码
3.代码
3.1 前端更新按钮
<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>
3.2 Controller层
/*----------------------更新数据-----------------------*/
/**
* 跳转到更新页面
*/
@RequestMapping("admin/to/edit/page.html")
public String toAdminEdite(@RequestParam("adminId") Integer adminId,ModelMap modelMap){
System.out.println("adminId="+adminId);
// 1.根据adminId查询admin对象
Admin admin = adminService.getAdminByAdminId(adminId);
// 2.将admin对象存入模型
modelMap.addAttribute("admin",admin);
return "admin-edit";
}
/**
* 保存更新
* */
@RequestMapping("admin/update.html")
public String updateAdmin(Admin admin,
@RequestParam("pageNum") Integer pageNum,
@RequestParam("keyword") String keyword){
try {
adminService.update(admin);
} catch (Exception e) {
//e.printStackTrace();
throw new UpdateAcctAlreadyUseException(CrowdConstant.MESSAGE_ACCT_ALREADY_IN_USE);
}
return "redirect:/admin/get/page.html?pageNum="+pageNum+"&keyword="+keyword;
}
3.3 service层 AdminService
void update(Admin admin);
AdminServiceImpl
/**
* 更新方法
* */
@Override
public void update(Admin admin) {
//Selective表示由选择的更新,对null字段不更新
mapper.updateByPrimaryKeySelective(admin);
}
3.4 异常处理
/**
* 新增时已存在该用户异常
* */
public class UpdateAcctAlreadyUseException extends RuntimeException{
private static final long serialVersionUID = 5L;
public UpdateAcctAlreadyUseException() {
super();
}
public UpdateAcctAlreadyUseException(String message) {
super(message);
}
public UpdateAcctAlreadyUseException(String message, Throwable cause) {
super(message, cause);
}
public UpdateAcctAlreadyUseException(Throwable cause) {
super(cause);
}
protected UpdateAcctAlreadyUseException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
/**
* 更新时该更新的用户已被使用异常
* */
@ExceptionHandler(value = UpdateAcctAlreadyUseException.class)
public ModelAndView updateFailedException(
UpdateAcctAlreadyUseException exception,
HttpServletRequest request,
HttpServletResponse response
) throws IOException {
// 只是指定当前异常对应的页面即可
String viewName = "system-error";
System.out.println("已完成");
return commonResolveException(viewName, exception, request, response);
}