原文再续,书接上回。上次我们讲了怎么把用户信息放到model里,然后用jsp+bootstrap做一个简单又不丑陋的界面去展示,但是现在讲究前后端分离,所以我们的接口返回一个json才是如今的王道,这样就不再需要后端人员去写JSP,顺便再用bootstrap做个界面了,而是前端人员用我们返回的json数据结合jquery或者nodejs等等方式去将数据展示给用户(所以这一章涉及到的jquery的东西其实和后端无关,不过jquery这玩意很简单,其实看一看最基本的用法就会了)。好了,话不多说,我们进入正题。
哦,对了,进入正题前先说个令人愉悦的题外话。由于我换了个开发环境,从github上拉下来代码之后发现pom里各种错误,一看基本就知道是包的错误,这种情况下最粗暴的方法就是把项目maven的依赖全删了,再把本地的jar包连带着文件夹一块删了(默认是在C:/用户/admin/.m2/下,我直接全删了)。。。。反正从阿里云上下的够快。update maven project之后果然几十个错误全消失了。然后运行的时候又报错数据源错误,完全找不到原因,最后我怀疑是以前用的driver class和我现在环境里安装的最新版mysql不匹配,我把pom里的mysql依赖的包换成了8.0.11,然后把dbconfig.properties里的连接字符串修改一下发现OK了(即使解决了这个问题我也不确定是不是版本不匹配的原因。。):
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.11</version>
</dependency>
dbconfig.properties如下:
jdbc.jdbcUrl=jdbc:mysql://127.0.0.1:3306/ssm_crud?characterEncoding=utf8&useUnicode=true&useSSL=false&serverTimezone=UTC
jdbc.driverClass=com.mysql.cj.jdbc.Driver
jdbc.user=root
jdbc.password=123456
好了,这下可以正式开始写代码了。。。
首先我们知道,返回json字符串返回的信息里除了有用户信息之外,还应该有个通用的错误码和错误信息,或者成功码或者成功信息,所以我们就写这样的一个类,在com.sunsy.crud.bean下我们创建Msg.java类,代码如下:
package com.sunsy.crud.bean;
import java.util.HashMap;
import java.util.Map;
public class Msg {
private int code;
private String msg;
private Map<String, Object> extend = new HashMap<>();
public Msg() {
}
public static Msg success() {
Msg result = new Msg();
result.setCode(0);
result.setMsg("处理成功");
return result;
}
public static Msg fail() {
Msg result = new Msg();
result.setCode(100);
result.setMsg("处理失败");
return result;
}
//用这个方法可以实现链式添加
public Msg add(String key, Object value) {
this.getExtend().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> getExtend() {
return extend;
}
public void setExtend(Map<String, Object> extend) {
this.extend = extend;
}
}
接下来是我们的Controller类,我们把EmployeeController.java类修改一下,让他返回json字符串,注意,如果想直接返回json一般采用的方式是添加@ResponseBody注解,这样spring会将我们返回的类直接转成json字符串传给请求发送者,但是在spring里如果用@ResponseBody必须要添加jackjson包,所以在pom.xml里添加如下依赖:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.8</version>
</dependency>
EmployeeController.java类修改后如下:
package com.sunsy.crud.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.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.sunsy.crud.bean.Employee;
import com.sunsy.crud.bean.Msg;
import com.sunsy.crud.service.EmployeeService;
@Controller
public class EmployeeController {
@Autowired
EmployeeService employeeService;
/**
* 分页查询所有员工信息,返回json的形式
* 使用responsebody需要加入解析json的包(springboot就不需要了)
*/
@RequestMapping("/emps")
@ResponseBody
public Msg getEmpsWithJson(@RequestParam(value="pageNum", defaultValue="1")Integer pageNum) {
//引入分页插件pagehelper
//在startPage后的第一个查询会变成分页查询
PageHelper.startPage(pageNum, 5);
List<Employee> emps = employeeService.getAll();
//把查询结果放到pageInfo里,这个pagehelper提供的类很好用,封装了各种我们需要的信息,那个5代表连续现实的页数
PageInfo<Employee> page = new PageInfo<Employee>(emps, 5);
return Msg.success().add("pageInfo", page);
}
// /**
// * 分页查询所有员工信息,返回model的形式
// * @return
// */
// @RequestMapping("/emps")
// public String getEmps(@RequestParam(value="pageNum", defaultValue="1")Integer pageNum, Model model) {
//
// //引入分页插件pagehelper
// //在startPage后的第一个查询会变成分页查询
// PageHelper.startPage(pageNum, 5);
// List<Employee> emps = employeeService.getAll();
//
// //把查询结果放到pageInfo里,这个pagehelper提供的类很好用,封装了各种我们需要的信息,那个5代表连续现实的页数
// PageInfo<Employee> page = new PageInfo<Employee>(emps, 5);
//
// //把pageinfo放到model里,这样就会传给界面
// model.addAttribute("pageInfo", page);
// return "list";
// }
}
OK,后端的内容到此就结束了,你可以直接从浏览器里访问127.0.0.1:8080/ssm-crud/emps,会在浏览器里直接显示json字符串。接下来就是前端用jquery封装的ajax去请求这个路径,再用请求到的用户信息+jquery+bootstrap构建前端界面,将数据较为美观的展示给用户。
上一次的list.jsp我们就不再需要了,而是将所有的逻辑都写到index.jsp里即可,不过你会发现虽然index.jsp是个jsp,但是里边其实没有任何用到jsp的地方。。。。老规矩,有一些解释直接写到注释里了,不过建议直接看jquery和bootstrap的官方文档更好点,index.jsp如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>员工列表</title>
<!-- 找到web项目的webapp路径 -->
<%
pageContext.setAttribute("APP_PATH", request.getContextPath());
%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<script type="text/javascript" src="${APP_PATH}/static/js/jquery-1.12.4.min.js"></script>
<link href="${APP_PATH}/static/bootstrap-3.3.7-dist/css/bootstrap.min.css" rel="stylesheet">
<script src="${APP_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">
<h1>SSM-CRUD</h1>
</div>
</div>
<!-- 删除和新增两个按钮 -->
<div class="row">
<div class="col-md-4 col-md-offset-8">
<button class="btn btn-success">新增</button>
<button class="btn btn-danger">删除</button>
</div>
</div>
<!-- 员工数据在表格中显示 -->
<div class="row">
<div class="col-md-12">
<table class="table table-hover" id="emps_table">
<thead>
<tr>
<th>#</th>
<th>empName</th>
<th>gender</th>
<th>email</th>
<th>departName</th>
<th>操作</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
<!-- 显示分页信息 -->
<div class="row">
<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:"${APP_PATH}/emps",
data:"pageNum="+pn,
type:"get",
success:function(result){
build_emps_table(result);
buile_page_info(result);
build_page_nav(result);
}
});
}
//解析员工数据
function build_emps_table(result){
//先清空
$("#emps_table tbody").empty();
var emps = result.extend.pageInfo.list;
$.each(emps, function(index, item){
var empIdTd = $("<td></td>").append(item.empId);
var empNameTd = $("<td></td>").append(item.empName);
var genderTd = $("<td></td>").append(item.getder=='M'?"男":"女");
var emailTd = $("<td></td>").append(item.email);
var deptNameTd = $("<td></td>").append(item.department.deptName);
var editBtn = $("<button></button>").addClass("btn btn-primary 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(empNameTd)
.append(genderTd)
.append(emailTd)
.append(deptNameTd)
.append(btnTd)
.appendTo("#emps_table tbody");
});
}
//解析分页信息
function buile_page_info(result){
$("#page_info_area").empty();
$("#page_info_area").append("当前" + result.extend.pageInfo.pageNum +
"页,总" + result.extend.pageInfo.pages +
"页,总" + result.extend.pageInfo.total + "条记录");
}
//解析分页数据
function build_page_nav(result){
$("#page_nav_area").empty();
var ul = $("<ul></ul>").addClass("pagination");
var firstPageLi = $("<li></li>").append($("<a></a>").append("首页").attr("href", "#"));
var prePageLi = $("<li></li>").append($("<a></a>").append("«"));
if(result.extend.pageInfo.hasPreviousPage==false){
firstPageLi.addClass("disabled");
prePageLi.addClass("disabled");
}else{
firstPageLi.click(function(){
to_page(1);
});
prePageLi.click(function(){
to_page(result.extend.pageInfo.pageNum - 1);
});
}
var nextPageLi = $("<li></li>").append($("<a></a>").append("»"));
var lastPageLi = $("<li></li>").append($("<a></a>").append("末页").attr("href", "#"));
if(result.extend.pageInfo.hasNextPage==false){
nextPageLi.addClass("disabled");
lastPageLi.addClass("disabled");
}else{
lastPageLi.click(function(){
to_page(result.extend.pageInfo.pages);
});
nextPageLi.click(function(){
to_page(result.extend.pageInfo.pageNum + 1);
});
}
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>
OK了,运行我们的项目,然后访问127.0.0.1:8080/ssm-crud就会得到和我们上一次基本一毛一样的效果。。。
至此crud里的r,也就是Retrieve(读取)我们就完成了,下一次我们就继续写我们的增加操作。。啥时候更新就不一定了。。我还是先把github地址加上吧,如下:https://github.com/ssystc/ssm-crud.git
然后是csdn的项目下载路径,我也附上了(球球各位有积分的老爷们用这个下吧,只要1分,1分也是情,1分也是爱啊):