上一节中,查询功能已实现,浏览器的请求功能完好。但是如果是安卓、IOS等移动客户端,服务器发送一个页面给移动设备解析的话,是比较吃力的,交互体验也不是很好。
为了解决该问题,我们需要对查询进行改造:前台发送ajax请求,后台返回json数据。
分析:首页index.jsp直接发送ajax请求进行员工分页信息的查询;服务器将查询的数据以JSON格式返回;
前台使用js完成JSON的解析,通过DOM操作完成增删改查的操作。
第1步、springMVC与json交互,需要jackson的包,那么首先需要在pom.xml中引入jackson包
<!-- 返回json字符串的支持 -->
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.5</version>
</dependency>
第2步、新建一个工具类MsgUtil,用于将分页信息进行包装,方便我们返回JSON的操作
package com.cn.util;
import java.util.HashMap;
import java.util.Map;
/**
* 通用的返回信息的类
* */
public class MsgUtil {
//状态码,自定义一些状态码对应的状态
private int code;
//提示信息
private String msg;
//用户给浏览器的数据,比如说返回的pageInfo信息
private Map<String,Object> map=new HashMap<String,Object>();
/**
* 操作成功的静态方法
* */
public static MsgUtil success(){
MsgUtil result=new MsgUtil();
//100表示成功
result.setCode(100);
result.setMsg("操作成功");
return result;
}
/**
* 操作失败的静态方法
* */
public static MsgUtil fail(){
MsgUtil result=new MsgUtil();
//200表示成功
result.setCode(200);
result.setMsg("操作失败");
return result;
}
/**
* 快捷添加信息的方法
* */
public MsgUtil add(String key,Object value){
this.getMap().put(key, value);
return this;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Map<String, Object> getMap() {
return map;
}
public void setMap(Map<String, Object> map) {
this.map = map;
}
}
第3步、改造EmpController代码如下:
package com.cn.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.cn.bean.Employee;
import com.cn.service.EmpService;
import com.cn.util.MsgUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
/**
* 处理员工CRUD请求的控制层
* */
@Controller
public class EmpController {
@Autowired
private EmpService empService;
/**
* 跳转员工页面
* */
@RequestMapping("/empList2")
public String toEmpList(){
return "empList2";
}
/**
* 查询员工数据(分页查询)
* */
@SuppressWarnings({ "rawtypes", "unchecked" })
//@RequestMapping("/emps")
public String getEmps(@RequestParam(value="pn",defaultValue="1")Integer pn,Model model){
/**
* 引入PageHelper分页插件
* 在查询之前只需要调用,传入页面以及每页的大小
* */
PageHelper.startPage(pn,5);
//startPage后面紧跟的这个查询就是一个分页查询
List<Employee> emps=empService.getAll();
//用pageInfo对结果进行包装,只需要将pageInfo交给页面,封装了详细的分页信息
PageInfo page=new PageInfo(emps,5);
model.addAttribute("pageInfo",page);
return "empList";
}
/**
* 基于ajax的查询员工数据(分页查询)
* @ResponseBody可以将返回的对象转换为JSON字符串,此注解需要引入jackson包以及注解驱动配置
* 将返回的信息封装在MsgUtil里面
* */
@SuppressWarnings({ "rawtypes", "unchecked" })
@ResponseBody
@RequestMapping("/emps")
public MsgUtil getEmpsByPage(@RequestParam(value="pn",defaultValue="1")Integer pn,Model model){
/**
* 引入PageHelper分页插件
* 在查询之前只需要调用,传入页面起始页以及每页的记录数
* */
PageHelper.startPage(pn,5);
//startPage后面紧跟的这个查询就是一个分页查询
List<Employee> emps=empService.getAll();
//用pageInfo对结果进行包装,只需要将pageInfo交给页面,封装了详细的分页信息
PageInfo page=new PageInfo(emps,5); //5为需要连续显示的记录数
//将pageInfo放在msgUtil里面进行返回,链式操作返回对象本身
return MsgUtil.success().add("pageInfo", page);
}
}
第4步、新建jsp页面empList2.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<%
pageContext.setAttribute("path",request.getContextPath());
%>
<title>员工列表</title>
<!-- 推荐以/开始的相对路径(以服务器的根路径为相对路径) -->
<link href="${path}/static/bootstrap-3.3.7-dist/css/bootstrap.min.css" rel="stylesheet" />
<!-- 先引入Jquery,再引入js -->
<script type="text/javascript" src="${path}/static/bootstrap-3.3.7-dist/js/jquery.min.js"></script>
<script src="${path}/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<!-- 分为四行 -->
<!-- 标题行 -->
<div class="row">
<div class="col-md-12">
<font size="20">SSM-CRUD</font>
</div>
</div>
<!-- 2、按钮行 -->
<div class="row">
<!-- 偏移4列 -->
<div class="col-md-4 col-md-offset-8">
<button type="button" class="btn btn-primary">新增</button>
<button type="button" class="btn btn-danger">删除</button>
</div>
</div>
<!-- 3、表格数据行 -->
<div class="row">
<div class="col-md-12">
<table class="table table-hover" id="emps_table">
<thead>
<tr>
<th>序号</th>
<th>员工名称</th>
<th>性别</th>
<th>邮箱</th>
<th>所在部门</th>
<th>操作</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
<!-- 4、分页信息行 -->
<div class="row">
<!-- 分页文字信息 -->
<div class="col-md-6" id="page_info">
</div>
<!-- 分页条 -->
<div class="col-md-6" id="page_nav">
</div>
</div>
</div>
<!-- 加载js -->
<script type="text/javascript" src="${path}/static/js/emp.js"></script>
</body>
</html>
逻辑:我们打开浏览器输入http://localhost:8080/SSM-CRUD跳转到index.jsp页面,点击index.jsp页面的员工查询按钮,到EmpController中查找empList2映射并返回empList2.jsp页面,empList2页面会加载emp.js
第4步、emp.js代码如下:
/**
* 页面加载完成后,直接发送一个ajax请求,要到分页数据
* */
$(function(){
//跳转到首页
to_page(1);
});
//页面加载完成后直接发送ajax请求,取得分页数据
function to_page(pn){
$.ajax({
//请求方式
type: "GET",
//请求url
url: "emps",
//请求要带的数据
data: "pn="+pn,
//请求成功的回调函数
success:function(result){
debugger;
//解析JSON返回员工数据
build_emps_table(result);
//解析生成分页信息(分页条与分页导航)
build_pages_info(result);
build_pages_nav(result);
}
});
}
//解析员工数据
function build_emps_table(result){
debugger;
//清空表格数据
$("#emps_table tbody").empty();
//员工数据
var emps=result.map.pageInfo.list;
//使用jQuery遍历数组,遍历是取出来的json数组,可以通过开发工具查看JSON结构
$.each(emps,function(idx,item){
//使用jQuery生成各列
var empIdTd=$("<td></td>").append(item.empId);
var empNameTd=$("<td></td>").append(item.empName);
var genderTd=$("<td></td>").append(item.gender=="M"?"男":"女");
var emailTd=$("<td></td>").append(item.email);
var deptNameTd=$("<td></td>").append(item.department.deptName);
var editBtn=$("<button></button>").addClass("btn btn-info btn-sm").append($("<span></span>").addClass("glyphicon glyphicon-pencil")).append("编辑");
var delBtn= $("<button></button>").addClass("btn btn-danger btn-sm").append($("<span></span>").addClass("glyphicon glyphicon-trash")).append("删除");
var btnTd=$("<td></td>").append(editBtn).append(" ").append(delBtn);
//链式操作完成列的添加
$("<tr></tr>").append(empIdTd).append(genderTd).append(emailTd).append(deptNameTd).append(btnTd).appendTo("#emps_table tbody");
});
}
//解析分页条数据
function build_pages_info(result){
//清空分页条数据
$("#page_info").empty();
//当前页
var currentPage=result.map.pageInfo.pageNum;
//总页数
var totalPage=result.map.pageInfo.pages;
//总记录数
var totalCount=result.map.pageInfo.total;
//填充
$("#page_info").append("当前第"+currentPage+"页,总共"+totalPage+"页,总共"+totalCount+"条记录");
}
//解析分页导航数据
function build_pages_nav(result){
//清空分页导航数据
$("#page_nav").empty();
//导航条外层的UL
var navUl=$("<ul></ul>").addClass("pagination");
//首页
var firstPageLi=$("<li></li>").append(
$("<a></a>").append("首页").attr("href","#")
);
//上一页
var prePageLi=$("<li></li>").append(
$("<a></a>").append("上一页")
);
//判断是否有首页
if(result.map.pageInfo.hasPreviousPage==false){
//如果没有首页,就禁用首页和上一页按钮
firstPageLi.addClass("disabled");
prePageLi.addClass("disabled");
}else{
//如果有首页,则赋予点击事件
//首页点击事件
firstPageLi.click(function(){
to_page(1);
});
//上一页事件
prePageLi.click(function(){
to_page(result.map.pageInfo.pageNum-1);
});
}
//下一页
var nextPageLi=$("<li></li>").append(
$("<a></a>").append("下一页")
);
//末页
var lastPageLi=$("<li></li>").append(
$("<a></a>").append("末页").attr("href","#")
);
//判断是否有末页
if(result.map.pageInfo.hasNextPage==false){
lastPageLi.addClass("disabled");
nextPageLi.addClass("disabled");
}else{
//下一页事件
nextPageLi.click(function(){
to_page(result.map.pageInfo.pageNum+1);
});
//末页点击事件
lastPageLi.click(function(){
to_page(result.map.pageInfo.pages);
});
}
//添加到ul
navUl.append(firstPageLi).append(prePageLi);
//遍历页码数
$.each(result.map.pageInfo.navigatepageNums,function(idx,item){
var numLi=$("<li></li>").append(
$("<a></a>").append(item)
);
//如果为当前页,则高亮显示
if(result.map.pageInfo.pageNum==item){
numLi.addClass("active");
}
//给每个页面添加单击绑定事件
numLi.click(function(){
to_page(item);
});
navUl.append(numLi);
});
navUl.append(nextPageLi).append(lastPageLi);
var navEle=$("<nav></nav>").append(navUl);
$("#page_nav").append(navEle);
}