项目完整实现代码下载地址:https://download.csdn.net/download/bingbeichen/10578683。
该部分主要实现员工信息的查询与显示,主要实现步骤包括:
- 访问index.jsp页面,该页面发送查询员工列表的请求(URI为/emps);
- 处理器EmployeeHandler来接收请求,查询出员工数据;
- 返回到/WEB-INF/views/emp-list.jsp页面进行员工信息的显示;
- 使用PageHelper分页插件完成分页查询功能。
###1. 分页查询后台代码实现
第一步,访问index.jsp页面,在该页面发送查询员工列表数据的请求,如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<jsp:forward page="/emps"></jsp:forward>
第二步,创建控制器EmployeeHandler来接收请求,查询出员工信息,如下:
// EmployeeHandler.java
@Controller
public class EmployeeHandler {
@Autowired
private EmployeeService employeeService;
@RequestMapping("/emps")
public String handleGetEmps() {
// 查询所有员工信息(需要创建业务逻辑组件EmployeeService)
List<Employee> emps = employeeService.getAll();
// 返回到emp-list.jsp页面进行显示
return "emp-list";
}
}
// EmployeeService.java
@Service
public class EmployeeService {
@Autowired
private EmployeeMapper employeeMapper;
public List<Employee> getAll() {
List<Employee> emps = employeeMapper.selectByExampleWithDept(null);
return emps;
}
}
第三步, 使用PageHelper分页插件完成分页查询功能,该部分主要包括:
(1). 引入分页插件,即在pom.xml文件中添加如下依赖
<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.4</version>
</dependency>
(2). 在MyBatis的全局配置文件mybatis-config.xml中,配置拦截器插件
<plugins>
<!-- com.github.pagehelper为PageHelper类所在包名 -->
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!-- 分页合理化参数,默认值为false。
当为true时,pageNum<=0 时查询第一页, pageNum>pages时查询最后一页。
-->
<property name="reasonable" value="true"/>
</plugin>
</plugins>
(3). 在控制器EmployeeHandler中进行分页查询,并将查询结果封装在Map中
@Controller
public class EmployeeHandler {
@Autowired
private EmployeeService employeeService;
@RequestMapping("/emps")
public String handleGetEmps(@RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum, Model model) {
// 使用PageHelper组件获取第pageNum页,共6条内容
PageHelper.startPage(pageNum, 6);
// 紧跟的查询操作即为分页查询
List<Employee> emps = employeeService.getAll();
// 使用PageInfo对分页查询结果进行封装,以获取分页查询的详细信息,并传入可连续显示的页数
PageInfo<Employee> pageInfo = new PageInfo<Employee>(emps, 6);
// 将pageInfo对象传递到结果页面
model.addAttribute("pageInfo", pageInfo);
return "emp-list";
}
}
第四步,使用Spring单元测试测试分页请求及其返回结果的正确性
package com.qiaobc.crud.test;
/**
* Spring4测试时需要servlet3.0支持
*/
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration({ "classpath:applicationContext.xml",
"file:src/main/webapp/WEB-INF/dispatcherServlet-servlet.xml" })
public class CRUDTest {
@Autowired
private WebApplicationContext context;
// 虚拟MVC请求,获取请求结果
private MockMvc mockMvc;
@Before
public void initMockMvc() {
mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
}
@Test
public void testGetAll() throws Exception {
// 模拟请求并获取请求结果
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.get("/emps").param("pageNum", "1")).andReturn();
MockHttpServletRequest request = result.getRequest();
PageInfo pageInfo = (PageInfo) request.getAttribute("pageInfo");
System.out.println("当前页码:" + pageInfo.getPageNum());
System.out.println("总页码数:" + pageInfo.getPages());
System.out.println("总记录数:" + pageInfo.getTotal());
System.out.print("连续页面:");
int[] nums = pageInfo.getNavigatepageNums();
for (int i : nums) {
System.out.print(i + " ");
}
System.out.println();
// 获取所有员工信息
List<Employee> emps = pageInfo.getList();
for (Employee emp : emps) {
System.out.println(emp.getLastName());
}
}
}
至此为止,分页查询的后台代码和测试均已完成。
###2. 分页查询页面搭建与数据显示
基于Bootstrap前端框架搭建分页页面,并对分页数据进行整理显示,实现效果图如下:
查询结果显示页面emp-list.jsp的具体实现代码:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>员工信息显示</title>
<%
pageContext.setAttribute("WEB_PATH", request.getContextPath());
%>
<script type="text/javascript"
src="${WEB_PATH }/static/javascript/jquery-3.3.1.min.js"></script>
<link
href="${WEB_PATH }/static/bootstrap-3.3.7-dist/css/bootstrap.min.css"
rel="stylesheet">
<script
src="${WEB_PATH }/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
</head>
<body>
<!-- 搭建显示界面 -->
<div class="container">
<!-- 标题行 -->
<div class="raw">
<div class="col-md-12">
<h1>SSM_CRUD</h1>
</div>
</div>
<!-- 按钮行 -->
<div class="raw">
<div class="col-md-4 col-md-offset-8">
<button class="btn btn-primary">新增</button>
<button class="btn btn-danger">删除</button>
</div>
</div>
<!-- 显示表格数据 -->
<div class="raw">
<div class="col-md-12">
<table class="table table-striped">
<tr>
<th>工号</th>
<th>姓名</th>
<th>邮箱</th>
<th>性别</th>
<th>部门</th>
<th>操作</th>
</tr>
<c:forEach items="${pageInfo.list }" var="emp">
<tr>
<td>${emp.id }</td>
<td>${emp.lastName }</td>
<td>${emp.email }</td>
<td>${emp.gender == "F" ? "女" : "男" }</td>
<td>${emp.dept.deptName }</td>
<td>
<button class="btn btn-info btn-sm">
<span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>
编辑
</button>
<button class="btn btn-danger btn-sm">
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span>
删除
</button>
</td>
</tr>
</c:forEach>
</table>
</div>
</div>
<!-- 显示分页信息 -->
<div class="raw">
<!-- 分页文字信息 -->
<div class="col-md-6">当前第${pageInfo.pageNum }页,共有${pageInfo.pages }页,总计${pageInfo.total }条记录
</div>
<!-- 分页条信息 -->
<div class="col-md-6">
<nav aria-label="Page navigation">
<ul class="pagination">
<li><a href="${WEB_PATH }/emps?pageNum=1">首页</a></li>
<c:if test="${pageInfo.hasPreviousPage }">
<li><a
href="${WEB_PATH }/emps?pageNum=${pageInfo.pageNum - 1}"
aria-label="Previous"> <span aria-hidden="true">«</span>
</a></li>
</c:if>
<c:forEach items="${pageInfo.navigatepageNums }" var="pn">
<c:if test="${pn == pageInfo.pageNum}">
<li class="active"><span>${pn } <span
class="sr-only">(current)</span></span></li>
</c:if>
<c:if test="${pn != pageInfo.pageNum}">
<li><a href="${WEB_PATH }/emps?pageNum=${pn }">${pn }</a></li>
</c:if>
</c:forEach>
<c:if test="${pageInfo.hasNextPage }">
<li><a
href="${WEB_PATH }/emps?pageNum=${pageInfo.pageNum + 1}"
aria-label="Next"> <span aria-hidden="true">»</span>
</a></li>
</c:if>
<li><a href="${WEB_PATH }/emps?pageNum=${pageInfo.pages }">尾页</a></li>
</ul>
</nav>
</div>
</div>
</div>
</body>
</html>
至此,员工信息的分页查询及显示功能已实现完毕,但该实现仅适用于浏览器-服务器结构,若实现移动端与服务器的交互则需要重新修改后台代码,在此可直接返回分页结果的JSON数据以使服务器适配不同的客户端。
###3. 返回分页结果的JSON数据
通过JSON的形式返回分页结果以实现员工信息的查询与显示,主要步骤包括:
- index.jsp页面直接发送Ajax请求进行员工分页数据的查询;
- 服务器将查出的数据,以JSON字符串的形式返回给客户端;
- 客户端可以使用javascript对JSON字符串进行解析,并通过dom增删改来显示页面;
- 返回JSON字符串串,可以实现客户端的无关性。
首先,在pom.xml文件中添加jackson包的依赖信息
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.6</version>
</dependency>
然后,修改控制器的目标方法,使其返回封装有分页信息的JSON字符串
@Controller
public class EmployeeHandler {
@Autowired
private EmployeeService employeeService;
@RequestMapping("/emps")
@ResponseBody
public Message handleGetEmpsRtnJson(@RequestParam(value = "pageNum", defaultValue="1") Integer pageNum, Model model) {
PageHelper.startPage(pageNum, 6);
List<Employee> list = employeeService.getAll();
PageInfo pageInfo = new PageInfo(list, 6);
// 返回带状态码的JSON数据
return Message.success().add("pageInfo", pageInfo);
}
}
package com.qiaobc.crud.bean;
public class Message {
// 状态码 100-成功 200-失败
private Integer code;
// 提示信息
private String msg;
// 待返回数据
Map<String, Object> extend = new HashMap<String, Object>();
// 成功
public static Message success() {
Message result = new Message();
result.setCode(100);
result.setMsg("操作成功");
return result;
}
// 失败
public static Message fail() {
Message result = new Message();
result.setCode(200);
result.setMsg("操作失败");
return result;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Map<String, Object> getExtend() {
return extend;
}
public void setExtend(Map<String, Object> extend) {
this.extend = extend;
}
public Message add(String key, Object value) {
this.getExtend().put(key, value);
return this;
}
}
最后,修改index.jsp显示页面,以解析返回的JSON字符串,并显示在页面上
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>员工信息显示</title>
<%
pageContext.setAttribute("WEB_PATH", request.getContextPath());
%>
<script type="text/javascript"
src="${WEB_PATH }/static/javascript/jquery-3.3.1.min.js"></script>
<link
href="${WEB_PATH }/static/bootstrap-3.3.7-dist/css/bootstrap.min.css"
rel="stylesheet">
<script
src="${WEB_PATH }/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
</head>
<body>
<!-- 搭建显示界面 -->
<div class="container">
<!-- 标题行 -->
<div class="raw">
<div class="col-md-12">
<h1>SSM_CRUD</h1>
</div>
</div>
<!-- 按钮行 -->
<div class="raw">
<div class="col-md-4 col-md-offset-8">
<button class="btn btn-primary">新增</button>
<button class="btn btn-danger">删除</button>
</div>
</div>
<!-- 显示表格数据 -->
<div class="raw">
<div class="col-md-12">
<table class="table table-striped" id="emps_table">
<thead>
<tr>
<th>工号</th>
<th>姓名</th>
<th>邮箱</th>
<th>性别</th>
<th>部门</th>
<th>操作</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
<!-- 显示分页信息 -->
<div class="raw">
<!-- 分页文字信息 -->
<div class="col-md-6" id="page_info_area"></div>
<!-- 分页条信息 -->
<div class="col-md-6" id="page_nav_area"></div>
</div>
</div>
<script type="text/javascript">
// 页面加载完成后,发送Ajax请求,获取分页数据
$(function() {
to_page(1);
});
function to_page(pn) {
$.ajax({
url : "${WEB_PATH}/emps",
data : "pageNum=" + pn,
type : "GET",
success : function(result) {
// console.log(result);
//1.解析并显示员工数据
build_emps_table(result);
//2.解析并显示分页信息
build_page_info(result);
//3.解析显示分页条数据
build_page_nav(result);
}
});
};
//解析并显示员工数据
function build_emps_table(result) {
$("#emps_table tbody").empty();
var emps = result.extend.pageInfo.list;
$.each(emps, function(index, item) {
//alert(item.lastName);
var idTd = $("<td></td>").append(item.id);
var lastNameTd = $("<td></td>").append(item.lastName);
var emailTd = $("<td></td>").append(item.email);
var genderTd = $("<td></td>").append(
item.gender == "M" ? "男" : "女");
var deptNameTd = $("<td></td>").append(item.dept.deptName);
/*
<button class="btn btn-info btn-sm">
<span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>
编辑
</button>
*/
var editBtn = $("<button></button>").addClass(
"btn btn-info btn-sm").append(
$("<span></span>").addClass(
"glyphicon glyphicon-pencil")).append("编辑");
var deleteBtn = $("<button></button>").addClass(
"btn btn-danger btn-sm").append(
$("<span></span>")
.addClass("glyphicon glyphicon-trash")).append(
"删除");
var buttonsTd = $("<td></td>").append(editBtn).append(" ")
.append(deleteBtn);
$("<tr></tr>").append(idTd).append(lastNameTd).append(emailTd)
.append(genderTd).append(deptNameTd).append(buttonsTd)
.appendTo("#emps_table tbody");
});
}
//解析并显示分页信息数据
function build_page_info(result) {
$("#page_info_area").empty();
var pageInfo = result.extend.pageInfo;
var pageNum = pageInfo.pageNum;
var pages = pageInfo.pages;
var total = pageInfo.total;
// 当前第?页,共有?页,总计?条记录
$("#page_info_area").append(
"当前第" + pageNum + "页,共有" + pages + "页,总计" + total + "条记录");
}
//解析并显示分页条数据
function build_page_nav(result) {
$("#page_nav_area").empty();
var pageInfo = result.extend.pageInfo;
var ul = $("<ul></ul>").addClass("pagination");
var firstPageLi = $("<li></li>").append(
$("<a></a>").append("首页").attr("href", "#"));
var lastPageLi = $("<li></li>").append(
$("<a></a>").append("尾页").attr("href", "#"));
var prePageLi = $("<li></li>").append(
$("<a></a>").append("«"));
var nextPageLi = $("<li></li>").append(
$("<a></a>").append("»"));
if (result.extend.pageInfo.hasPreviousPage == false) {
prePageLi.addClass("disabled");
firstPageLi.addClass("disabled");
} else {
prePageLi.click(function() {
to_page(result.extend.pageInfo.pageNum - 1);
});
firstPageLi.click(function() {
to_page(1);
});
}
if (result.extend.pageInfo.hasNextPage == false) {
nextPageLi.addClass("disabled");
lastPageLi.addClass("disabled");
} else {
nextPageLi.click(function() {
to_page(result.extend.pageInfo.pageNum + 1);
});
lastPageLi.click(function() {
to_page(result.extend.pageInfo.pages);
});
}
ul.append(firstPageLi).append(prePageLi);
$.each(result.extend.pageInfo.navigatepageNums, function(index,
item) {
var numLi = $("<li></li>").append($("<a></a>").append(item));
if (result.extend.pageInfo.pageNum == item) {
numLi.addClass("active");
}
numLi.click(function() {
to_page(item);
});
ul.append(numLi);
});
ul.append(nextPageLi).append(lastPageLi);
var navEle = $("<nav></nav>").append(ul);
navEle.appendTo("#page_nav_area");
}
</script>
</body>
</html>