使用SpringBoot 框架搭建用户管理系统,代码附在文末
快~点这里来试试(●’◡’●)
1、项目解决问题
用户管理系统:用户的信息做统一的管理
2、需求功能分析
1、登录功能(普通管理员登陆、超级管理员的登录)
2、用户列表页面(普通用户的列表、超级管理员的列表页)
3、条件查询(组合条件查询、不定规则查询)
4、分页功能
5、添加功能(普通管理员的添加、超级管理员的添加)
6、单挑删除功能
7、多条删除功能
3、设计数据库
用户管理系统,所以只需要设置一张用户表即可,SQL语句如下:
drop database if exists userdb;
create DATABASE if not exists userdb character set utf8;
use userdb;
drop table if exists userinfo;
create table `userinfo` (
`id` INT PRIMARY KEY auto_increment,
`name` varchar(60), --姓名
`username` varchar(60) default 'root',
`password` varchar(60) default '123456',
`sex` varchar(4), --性别
`age` int, --年龄
`address` varchar(90), --邮箱
`qq` varchar (20), -- QQ
`email` varchar (30), --是否为超管,默认为否
`isadmin` int not null default 0
);
INSERT INTO userinfo VALUES(1,'超级管理员','admin','123','男',18,'成都','1262913815','admin@qq.com',1);
INSERT INTO userinfo VALUES(2,'张飞','zhangfei','123','男',18,'成都','1262913815','126@qq.com',0);
INSERT INTO userinfo VALUES(3,'关羽','guanyu','1234','男',18,'西安','1262913816','1262@qq.com',0);
INSERT INTO userinfo VALUES(4,'张三','zhangsan','1235','女',19,'西安','1262913817','1263@qq.com',0);
INSERT INTO userinfo VALUES(5,'李四','lisi','1236','男',20,'北京','1262913818','1264@qq.com',0);
INSERT INTO userinfo VALUES(6,'王五','wangwu','1237','女',21,'西安','1262913819','1265@qq.com',0);
INSERT INTO userinfo VALUES(7,'孙权','sunquan','1238','男',22,'上海','1262913814','1266@qq.com',0);
INSERT INTO userinfo VALUES(8,'孙悟空','sunwukong','1239','男',23,'西安','1262913813','1267@qq.com',0);
INSERT INTO userinfo VALUES(9,'猪八戒','zhubajie','1239','男',23,'上海','1262913813','1267@qq.com',0);
4、返回原则:所有接口必须有统一的返回格式
为前端返回JSON字符串,包含 {status,data,message}
第一种封装方法:定义一个全局的返回时调用此对象进行返回。
第二种封装方法:Advice 接口实现统一的数据封装
这里采用第二种:定义全区的返回掉用对象来实现统一返回原则,泛用性强
package com.example.usermanager.tools;
import lombok.Data;
@Data
public class ResponseBody<T> {
private int status;
private String message;
private T data;
public ResponseBody(int status, String message, T data) {
this.status = status;
this.message = message;
this.data = data;
}
}
在之后写的后端controller类下各种方法,都将其返回值设置为ResponseBody,根据需求返回值不同,设置data属性为需要的属性。
5、登录
先贴上登录的前端页面:login.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>用户信息管理系统登录页面</title>
<!-- 1. 导入CSS的全局样式 -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- 2. jQuery导入,建议使用1.9以上的版本 -->
<script src="js/jquery-2.1.0.min.js"></script>
<!-- 3. 导入bootstrap的js文件 -->
<!--<script src="js/bootstrap.min.js"></script>-->
<script type="text/javascript"></script>
<style>
html, body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: auto;
}
body {
background: url(images/acg.gy_16.jpg) no-repeat 100% 100%;
background-size: cover;
}
</style>
</head>
<body id="body">
<div class="container" style="width: 400px;margin-top: 110px;background-color: rgba(255,255,255,0.8)">
<h3 style="text-align: center;">后台管理员登录</h3>
<div class="form-group">
<label for="username">用户名:</label>
<input type="text" name="user" class="form-control" id="username" placeholder="请输入用户名"/>
</div>
<div class="form-group">
<label for="password">密码:</label>
<input type="password" name="password" class="form-control" id="password" placeholder="请输入密码"/>
</div>
<div>
测试超管帐号:admin
         测试密码:123
</div>
<hr/>
<div class="form-group" style="text-align: center;"><!--class="form-group"-->
<input style="width: 200px;height: 40px" id="submit"
class="btn btn btn-primary" type="button" value="登录" onclick="mysub()">
</div>
</div>
<script>
function mysub() {
// 获取用户名
var username = jQuery("#username");
// 获取密码
var password = jQuery("#password");
// 非空效验
if (username.val().trim() == "" ||
password.val().trim() == "") {
alert("请先输入用户名和密码才能进行登录!");
return false;
}
// 提交数据到后端进行登录效验
jQuery.getJSON("/user/login", {
"username": username.val(),
"password": password.val()
}, function (result) {
if (result != null && result.status == 0) {
// 登录成功
alert("登录成功");
location.href = "list.html";
} else {
// todo:安全限制(如果一定时间内输入的用户名和密码错误次数过多,就可以先冻结账户一段时间)
alert(result.message);
}
});
}
</script>
</body>
</html>
登录功能需要做的就是两件事,第一件事,拿到前端传来的帐号和密码后,去数据库验证,验证成功则登录,失败则拒绝登录;第二件事,登陆成功后,将当前登录用户的Session信息保存下来
package com.example.usermanager.controller;
import com.example.usermanager.mapper.UserMapper;
import com.example.usermanager.model.UserInfo;
import com.example.usermanager.tools.AppFinal;
import com.example.usermanager.tools.ResponseBody;
import com.example.usermanager.tools.SessionUtil;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.List;
@RestController
@RequestMapping("/user")
public class UserController {
@Resource
private UserMapper userMapper; // 注入UserMapper.class接口类,用于映射与数据库沟通的方法
// 登录方法
@RequestMapping("/login")
public ResponseBody<UserInfo> login(@RequestParam String username,
@RequestParam String password,
HttpServletRequest request) {
UserInfo userInfo = userMapper.login(username, password);
int status = -1;
String message = "用户或密码错误!";
if (userInfo != null && userInfo.getId() > 0) {
// 登录成功
status = 0;
message = "";
// 将用户对象存储到 session 中
HttpSession session = request.getSession();
session.setAttribute(AppFinal.USERINFO_SESSION_KEY, userInfo);
}
return new ResponseBody<>(status, message, userInfo);
}
UserMapper.class
接口类,用于映射UserMapper.xml
配置类中的具体操作数据库的方法
package com.example.usermanager.mapper;
import com.example.usermanager.model.UserInfo;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface UserMapper {
public UserInfo login(String username, String password);
UserMapper.xml
配置文件,用于具体操作数据库的SQL语句书写
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.usermanager.mapper.UserMapper">
<select id="login" resultType="com.example.usermanager.model.UserInfo">
select * from userinfo where username=#{username} and password=#{password}
</select>
</mapper>
6、添加用户页面 —— 拥有两个访问后端的接口
先贴上添加用户的前端页面:add.html
<!DOCTYPE html>
<!-- 网页使用的语言 -->
<html lang="zh-CN">
<head>
<!-- 指定字符集 -->
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>添加用户</title>
<link href="css/bootstrap.min.css" rel="stylesheet">
<script src="js/jquery-2.1.0.min.js"></script>
</head>
<body>
<div class="container" style="width: 400px;">
<h3 style="text-align: center;">添加用户</h3>
<div class="form-group">
<label for="username">登录名:</label>
<input type="text" class="form-control" id="username" name="username" placeholder="请输入登录名"/>
</div>
<div class="form-group">
<label for="name">姓名:</label>
<input type="text" class="form-control" id="name" name="name" placeholder="请输入姓名"/>
</div>
<div class="form-group">
<label for="password">密码:</label>
<input type="password" class="form-control" id="password" name="password" placeholder="请输入密码"/>
</div>
<div class="form-group">
<label for="password2">确认密码:</label>
<input type="password" class="form-control" id="password2" name="password" placeholder="请输入密码"/>
</div>
<div class="form-group">
<label>性别:</label>
<input id="man" type="radio" name="sex" value="男" checked="checked"/>男
<input id="women" type="radio" name="sex" value="女"/>女
</div>
<div class="form-group">
<label for="age">年龄:</label>
<input type="number" class="form-control" id="age" name="age" placeholder="请输入年龄"/>
</div>
<div class="form-group">
<label for="address">籍贯:</label>
<select name="address" id="address" class="form-control">
<option value="北京">北京</option>
<option value="上海">上海</option>
<option value="广州">广州</option>
<option value="深圳">深圳</option>
<option value="成都">成都</option>
<option value="杭州">杭州</option>
<option value="重庆">重庆</option>
<option value="西安">西安</option>
<option value="武汉">武汉</option>
<option value="沧州">沧州</option>
</select>
</div>
<div class="form-group">
<label for="qq">QQ:</label>
<input type="text" id="qq" class="form-control" name="qq" placeholder="请输入QQ号码"/>
</div>
<div class="form-group">
<label for="email">Email:</label>
<input type="text" id="email" class="form-control" name="email" placeholder="请输入邮箱地址"/>
</div>
<div class="form-group" id="adminDiv" style="display: none;">
<label for="email">超级管理员:</label>
<input id="admin_yes" type="radio" name="isadmin" value="1"/>是
<input id="admin_no" type="radio" name="isadmin" value="0" checked="checked"/>否
</div>
<div class="form-group" style="text-align: center">
<input id="btn_sub" class="btn btn-primary" type="button" value="提交" onclick="mysub()"/>
<input id="btn_back" class="btn btn-default" type="button" value="返回" onclick="location.href='list.html'"/>
</div>
</div>
</body>
<script>
jQuery.getJSON("/user/checkadmin",{},function (result) {
if(result!=null && result.data==1){
// 超级管理员
jQuery("#adminDiv").show();
}
});
// 提交方法
function mysub() {
// 1.非空效验
var username = jQuery("#username");
var name = jQuery("#name");
var password = jQuery("#password");
var password2 = jQuery("#password2");
var age = jQuery("#age");
var qq = jQuery("#qq");
var email = jQuery("#email");
if(username.val().trim()==""){
alert("请先输入登录名!");
username.focus();
return false;
}
if(name.val().trim()==""){
alert("请先输入姓名!");
name.focus();
return false;
}
if(password.val().trim()==""){
alert("请先输入密码!");
password.focus();
return false;
}
if(password2.val().trim()==""){
alert("请先输入确认密码!");
password2.focus();
return false;
}
if(password.val()!=password2.val()){
alert("两次输入的密码不一致,请检查!");
password.focus();
return false;
}
if(age.val().trim()==""){
alert("请先输入年龄!");
age.focus();
return false;
}
if(qq.val().trim()==""){
alert("请先输入QQ!");
qq.focus();
return false;
}
if(email.val().trim()==""){
alert("请先输入电子邮箱!");
email.focus();
return false;
}
// 提交数据到后端
jQuery.getJSON("/user/add",{
"username":username.val().trim(),
"name":name.val().trim(),
"password":password.val().trim(),
"sex":jQuery("input[name=sex]:checked").val(),
"age":age.val().trim(),
"address":jQuery("#address").val(),
"qq":qq.val().trim(),
"email":email.val().trim(),
"isadmin":jQuery("input[name=isadmin]:checked").val()
},function (result) {
if(result!=null && result.status==0 && result.data>0){
// 添加成功
alert("恭喜:添加成功!");
// todo:继续添加或返回到列表页
}else{
alert("抱歉:添加失败,"+result.message);
}
});
}
</script>
</html>
(1)获取当前用户登录权限的接口(超级管理员还是普通管理员)
要实现用户信息管理,需要验证当前登录的账号是普通的用户管理员还是超级管理员,这两者的区别是,普通管理员用户只可以看到其他的普通管理员用户信息,添加新的用户时不能添加超管用户,同时也看不到超管用户的信息;但超管用户可以添加普通管理员和超管的新用户,并且可以看见所有用户的信息。
下列所有controller又是对用户进行操作,所以都在UserController类下,所以,每一部分只列出当前部分的方法,就不复制整体类的其他代码了;同样UserMapper.class
接口类同样只写新添加的;UserMapper.xml
配置文件也是。
所以在登录之后,首先要验证当前用户的权限
// 查询当前登录用户的权限
@RequestMapping("/checkadmin")
public ResponseBody<Integer> checkAdmin(HttpServletRequest request) {
int data = 0;
HttpSession session = request.getSession(false); // 拿到Session中的用户信息
UserInfo userInfo = null;
if (session != null &&
(userInfo = (UserInfo) session.getAttribute(AppFinal.USERINFO_SESSION_KEY)) != null) {
data = userInfo.getIsadmin(); // 根据Session中保存的用户信息,拿到 管理员权限 字段,返回这个字段的属性
}
return new ResponseBody<>(0, "", data);
}
(2)添加用户接口
添加用户方法,有两种情况,一种是添加普通用户,一种是添加超管用户,添加超管用户前需要对当前用户的权限进行验证,验证权限的方法与上一段逻辑大体相同,都是拿到Session的用户属性,然后拿到用户属性中的 是否为管理员权限 字段的属性
验证完用户权限后,就需要使用Mybatis进行数据库沟通,添加新用户
在UserController
类下的add
方法内引入UserMapper.class
接口,作为映射UserMapper.xml
中间介质——>data = userMapper.add(userInfo);
在mapper
类下的UserMapper.class
接口中添加 public int add(UserInfo userInfo);
通过在类上添加@Mapper
注释,让UserMapper.class
类映射到resources
资源文件下的mybatis
文件中的UserMapper.xml
配置文件
// 添加用户方法
@RequestMapping("/add")
public ResponseBody<Integer> add(UserInfo userInfo,
HttpServletRequest request) {
int status = 0;
String message = "";
int data = 0;
// 安全效验
UserInfo user = SessionUtil.getUserBySession(request);
if (user == null) {
// 未登录
status = -1;
message = "当前用户未登录,请先登录";
} else if (userInfo.getIsadmin() == 1) { // 要添加超级管理员
if (user.getIsadmin() == 0) {
status = -2;
message = "当前登录用户权限不足,不能操作";
} else if (user.getIsadmin() == 1) {
// 当前登录用户为超级管理员
data = userMapper.add(userInfo);
status = 0;
}
} else if (userInfo.getIsadmin() == 0) { // 添加一个普通管理员
data = userMapper.add(userInfo);
}
return new ResponseBody<>(status, message, data);
}
在UserMapper.class
接口类中添加如下方法:
public int add(UserInfo userInfo);
在UserMapper.xml
配置文件中添加如下SQL语句
<insert id="add">
insert into userinfo(username,name,password,sex,age,address,qq,email
<if test="isadmin!=null">
,isadmin
</if>
)
values(#{username},#{name},#{password},#{sex},#{age},#{address},#{qq},#{email}
<if test="isadmin!=null">
,#{isadmin}
</if>
)
</insert>
7、修改用户页面 —— update.html?uid=xxx
先贴上修改用户的前端页面:update.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>修改用户</title>
<link href="css/bootstrap.min.css" rel="stylesheet">
<script src="js/jquery-2.1.0.min.js"></script>
</head>
<body>
<div class="container" style="width: 400px;">
<h3 style="text-align: center;">修改用户</h3>
<div class="form-group">
<label for="username">登录名:</label>
<input type="text" class="form-control" id="username" name="username" readonly="readonly"/>
</div>
<div class="form-group">
<label for="name">姓名:</label>
<input type="text" class="form-control" id="name" name="name" placeholder="请输入姓名"/>
</div>
<div class="form-group">
<label>性别:</label>
<input id="man" type="radio" name="sex" value="男" checked="checked"/>男
<input id="women" type="radio" name="sex" value="女"/>女
</div>
<div class="form-group">
<label for="age">年龄:</label>
<input type="number" class="form-control" id="age" name="age" placeholder="请输入年龄"/>
</div>
<div class="form-group">
<label for="address">籍贯:</label>
<select name="address" id="address" class="form-control">
<option value="北京">北京</option>
<option value="上海">上海</option>
<option value="广州">广州</option>
<option value="深圳">深圳</option>
<option value="成都">成都</option>
<option value="杭州">杭州</option>
<option value="重庆">重庆</option>
<option value="西安">西安</option>
<option value="武汉">武汉</option>
<option value="沧州">沧州</option>
</select>
</div>
<div class="form-group">
<label for="qq">QQ:</label>
<input type="text" id="qq" class="form-control" name="qq" placeholder="请输入QQ号码"/>
</div>
<div class="form-group">
<label for="email">Email:</label>
<input type="text" id="email" class="form-control" name="email" placeholder="请输入邮箱地址"/>
</div>
<div class="form-group">
<label for="email">超级管理员:</label>
<input id="admin_yes" type="radio" disabled="disabled" name="isadmin" value="1"/>是
<input id="admin_no" type="radio" disabled="disabled" name="isadmin" value="0" checked="checked"/>否
</div>
<div class="form-group" style="text-align: center">
<input id="btn_sub" class="btn btn-primary" type="button" value="提交" onclick="mysub()"/>
<input id="btn_reset" class="btn btn-box" type="button" value="重置" onclick="location.href=location.href"/>
<input id="btn_back" class="btn btn-default" type="button" value="返回" onclick="location.href='list.html'"/>
</div>
</div>
</body>
<script>
// 获取参数
function getParam(key) {
// 得到当前url中的参数 ?uid=xxx
var params = location.search;
params = params.substring(1); // uid=xxx
var paramArr = params.split("&");
for (var i = 0; i < paramArr.length; i++) {
var item = paramArr[i].split("=");
if (item[0] == key) {
return item[1];
}
}
return null;
}
var uid = getParam("uid");
if (uid != null && uid > 0) {
// 查询用户的详情进行展示
jQuery.getJSON("/user/getuser", {"uid": uid}, function (result) {
if (result != null && result.status == 0 && result.data.id > 0) {
// 查询用户信息成功
var userinfo = result.data;
jQuery("#username").val(userinfo.username);
jQuery("#name").val(userinfo.name);
if (userinfo.sex == "男") {
jQuery("#man").attr("checked", "checked");
} else if (userinfo.sex == "女") {
jQuery("#women").attr("checked", "checked");
}
jQuery("#age").val(userinfo.age);
jQuery("#address").val(userinfo.address);
jQuery("#qq").val(userinfo.qq);
jQuery("#email").val(userinfo.email);
if (userinfo.isadmin == 0) {
jQuery("#admin_no").attr("checked", "checked");
} else if (userinfo.isadmin == 1) {
jQuery("#admin_yes").attr("checked", "checked");
}
} else {
alert("查询失败,请重试!");
}
});
} else {
alert("无效参数");
// todo:可以实现后续跳转(如:列表页 || 登录页)
}
function mysub() {
// 1.非空效验
var name = jQuery("#name");
var age = jQuery("#age");
var qq = jQuery("#qq");
var email = jQuery("#email");
if (name.val().trim() == "") {
alert("请先输入姓名!");
name.focus();
return false;
}
if (age.val().trim() == "") {
alert("请先输入年龄!");
age.focus();
return false;
}
if (qq.val().trim() == "") {
alert("请先输入QQ!");
qq.focus();
return false;
}
if (email.val().trim() == "") {
alert("请先输入电子邮箱!");
email.focus();
return false;
}
// 提交数据到后端
jQuery.getJSON("/user/update", {
"id": uid,
"name": name.val().trim(),
"sex": jQuery("input[name=sex]:checked").val(),
"age": age.val().trim(),
"address": jQuery("#address").val(),
"qq": qq.val().trim(),
"email": email.val().trim(),
"isadmin": jQuery("input[name=isadmin]:checked").val()
}, function (result) {
if (result != null && result.status == 0 && result.data > 0) {
// 操作成功
alert("恭喜:修改成功!");
// todo:返回到列表页
} else {
alert("抱歉:修改失败," + result.message);
}
});
}
</script>
</html>
(1)从url中获取uid
因为要对展示的列表中的某个用户进行信息的修改,所以要向后端传输时,传输当前要修改用户的uid,所以要拿到当前用户的uid
这部分在前端代码中完成,通过如下代码拿到URL地址中用户的uid
// 获取参数
function getParam(key) {
// 得到当前url中的参数 ?uid=xxx
var params = location.search;
params = params.substring(1); // uid=xxx
var paramArr = params.split("&");
for (var i = 0; i < paramArr.length; i++) {
var item = paramArr[i].split("=");
if (item[0] == key) {
return item[1];
}
}
return null;
}
(2)展示信息(用户登录状态判断-权限判断)
在UserController
类下新增查询用户详细信息的方法
此处可以进行权限验证,当用户登录的情况下(Session)中有信息,才会展示用户信息
@RequestMapping("/getuser")
public ResponseBody<UserInfo> getUser(@RequestParam int uid) {
int status = -1;
String message = "未知错误";
UserInfo userInfo = userMapper.getUser(uid);
if (userInfo != null) {
// todo:权限效验
status = 0;
}
return new ResponseBody<>(status, message, userInfo);
}
在UserMapper.class
接口类中添加如下方法:
public UserInfo getUser(int uid);
在UserMapper.xml
配置文件中添加如下SQL语句
<select id="getUser" resultType="com.example.usermanager.model.UserInfo">
select * from userinfo where id=#{uid}
</select>
(3)编辑/提交信息(用户登录状态判断、权限判断)
这里的权限效验,主要是要验证当前用户是否是超级管理员,如果不是超级管理员,就不能添加超级管理员的账户
@RequestMapping("/update")
public ResponseBody<Integer> update(UserInfo userInfo) {
int data = 0;
// todo:权限效验
data = userMapper.update(userInfo);
return new ResponseBody<>(0, "", data);
}
在UserMapper.class
接口类中添加如下方法:
public int update(UserInfo userInfo);
在UserMapper.xml
配置文件中添加如下SQL语句
<update id="update">
update userinfo set
name=#{name},
sex=#{sex},
age=#{age},
address=#{address},
qq=#{qq},
email=#{email},
isadmin=#{isadmin}
where id=#{id}
</update>
8、用户列表显示
先将用户列表显示的前端页面贴在这里:list.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<!-- 指定字符集 -->
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>用户信息管理系统</title>
<!-- 1. 导入CSS的全局样式 -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- 2. jQuery导入,建议使用1.9以上的版本 -->
<script src="js/jquery-2.1.0.min.js"></script>
<!-- 3. 导入bootstrap的js文件 -->
<!-- <script src="js/bootstrap.min.js"></script>-->
<style type="text/css">
td, th {
text-align: center;
}
</style>
</head>
<body>
<div class="container">
<h3 style="text-align: center;margin-bottom: 50px;">用户信息列表</h3>
<div style="float: left;">
<form class="form-inline">
<div class="form-group">
<label for="ipt_name">姓名</label>
<input name="name" type="text" class="form-control" id="ipt_name">
</div>
<div class="form-group">
<label for="ipt_address">籍贯</label>
<input name="address" type="text" class="form-control" id="ipt_address">
</div>
<div class="form-group">
<label for="ipt_email">邮箱</label>
<input name="email" type="email" class="form-control" id="ipt_email">
</div>
<button id="submit1" type="button" class="btn btn-default" onclick="oncli()">查询</button>
</form>
</div>
<div style="float: right;margin-bottom: 15px">
<a class="btn btn-primary" href="add.html">添加用户</a>
<a id="delete" class="btn btn-primary" href="javascript:delSelect()">删除选中</a>
</div>
<table border="1" class="table table-bordered table-hover">
<tr class="success">
<th>选择</th>
<th>编号</th>
<th>姓名</th>
<th>性别</th>
<th>年龄</th>
<th>籍贯</th>
<th>QQ</th>
<th>邮箱</th>
<th>超管</th>
<th>操作</th>
</tr>
<tbody id="info">
<!-- 用户列表部分,通过使用此处的id=“info”动态添加数据 <tr>-->
</tbody>
</table>
<div>
<nav aria-label="Page navigation">
<ul id="all" class="pagination">
<!-- 序号与换页符部分,动态添加 </span>-->
</ul>
</nav>
</div>
</div>
</body>
<script>
var name = "";
var address = "";
var email = "";
var cpage = 1;
var psize = 5
function oncli(){
name = jQuery("#ipt_name").val().trim();
address = jQuery("#ipt_address").val().trim();
email = jQuery("#ipt_email").val().trim();
getData(); // 查询后端接口,展示信息
}
// 点击分页按钮
function cliPage(cp) {
cpage = cp;
getData();
}
function getData(){
jQuery.getJSON("/user/list",{
"name":name,
"address":address,
"email":email,
"cpage":cpage,
"psize":psize
},function (result) {
if(result != null && result.data.list != null &&
result.data.list.length > 0) {
// 1、绑定列表数据
var listHtml = "";
for (var i = 0; i < result.data.list.length; i++) {
var userinfo = result.data.list[i];
listHtml += '<tr>\n' +
' <th>\n' +
' <input id="' + userinfo.id + '" type="checkbox">\n' +
' </th>\n' +
' <th>' + userinfo.id + '</th>\n' +
' <th>' + userinfo.name + '</th>\n' +
' <th>' + userinfo.sex + '</th>\n' +
' <th>' + userinfo.age + '</th>\n' +
' <th>' + userinfo.address + '</th>\n' +
' <th>' + userinfo.qq + '</th>\n' +
' <th>' + userinfo.email + '</th>\n' +
' <th>' + (userinfo.isadmin == 0 ? "否" : "是") + '</th>\n' +
' <th>\n' +
' <a class="btn btn-default btn-sm" href="update.html?uid=' + userinfo.id + '">修改</a>\n' +
' <a class="btn btn-default btn-sm" href="javascript:del(' + userinfo.id + ');">删除</a>\n' +
' </th>\n' +
' </tr>';
}
jQuery("#info").html(listHtml);
// 2.绑定分页信息
var tpage = result.data.tpage; //总页数
var pageHtml = "";
if (tpage > 1) {
if(cpage != 1){
pageHtml += '<li><a href="javascript:cliPage(' + (cpage - 1) + ');" aria-label="Previous">\n' +
' <span aria-hidden="true">«</span></a>\n'
}
for(var j = 1; j <= tpage; j++){
// 拼接当前页
if(cpage == j) { // 高亮当前页面序号
pageHtml += '<li class="active"><a href="javascript:cliPage(' + j + ');">' + j + '</a></li>\n';
}else{
pageHtml += '<li><a href="javascript:cliPage(' + j + ');">' + j + '</a></li>\n';
}
}
// 下一页的按钮 与 动态显示:共 ? 条记录,共?页
if(cpage != tpage) {
pageHtml += '<li><a href="javascript:cliPage(' + (cpage + 1) + ');" aria-label="Next">\n' +
' <span aria-hidden="true">»</span></a>\n' +
' </li>\n' +
' <span style="font-size: 20px;margin-left: 10px;"> 共' + result.data.tcount + '条记录,共' + tpage + '页\n' +
' </span>\n'
}
}
jQuery("#all").html(pageHtml);
}
});
}
getData();
// 单条删除
function del(id) {
if (confirm("是否进行删除?")) {
jQuery.getJSON("/user/del", {"id": id}, function (result) {
if (result != null && result.data > 0) {
alert("恭喜:删除成功!");
// 刷新当前页面
location.href = location.href;
} else {
alert("抱歉:删除失败 "+result.message);
}
});
}
}
// 多条删除
// 思路1、for循环多条id,每次循环调用单条循环删除方法的接口;缺点:需要与后端进行N次交互,浪费带宽
// 思路2、将所有id集合一次发送给后端,后端对前端传递的id集合做统一的删除(使用这条思路)
// (a) 点击选中按钮后,拿到选中的用户id集合
// (b) 后端拿到id集合之后,使用<for>循环的标签,实现多条信息的删除
function delSelect() {
// 1、获取需要删除的用户id集合
var ids = "";
jQuery("#info").find("tr").each(function (i) {
//jQuery(this) == 当前行tr
if(jQuery(this).find("th:first").find("input").prop("checked")==true){ // 判断 当前行tr的第一列的input控件中的 chekbox属性 是否为选中状态 prop("checked")判断当前控件是否为选中状态
ids += ((jQuery(this).find("th:first").find("input").attr("id")) + ',')
};
});
if(ids != ""){
confirm("确认删除?")
// 2、访问后端接口进行操作
jQuery.getJSON("/user/dels",{"ids":ids},function (result) {
if(result != null && result.status == 0 && result.data > 0){
alert("删除成功");
location.href = location.href;
}else {
alert("删除失败");
}
})
}else {
alert("请先选中要删除的数据")
}
}
</script>
</html>
根据前端页面所写,当用户登录进入到list.html
这个页面,静态页面加载完成后,首先会执行getData()
这个<script>
中的内容,这部分就是以列表的形式,返回所有用户的信息,而且因为我们需要分页查询,所以需要将cpage (当前页码)、psize(每页显示条数)传递给后端;并且要实现使用用户姓名
、籍贯
或者邮箱
查询用户,所以同时也需要将name,adress、email传递,所以传递给后端的jQuery.getJSON
中,传递的参数格式应该写成{"name":name,"address":address, "email":email,"cpage":cpage,"psize":psize }
;如果后端查询用户信息成功后使用jQuery("#info").html(listHtml);
将循环赋值的listHtml
对象展示到给前端页面上
(1)展示用户信息,以及分页
UserController
类下新增list
方法,该方法用于查询用户的信息,同时也需要验证一下当前用户是否为超管,普通管理员用户,是不能查询到超管用户的信息的
@RequestMapping("/list")
public ResponseBody<HashMap<String, Object>> getList(String name,
String address,
String email,
int cpage,
int psize,
HttpServletRequest request
) {
// 1.权限效验
UserInfo userInfo = SessionUtil.getUserBySession(request);
if (userInfo == null) {
// 未登录
return new ResponseBody<>(-1, "当前用户未登录", null);
}
// 2.判断权限
Integer isadmin = null;
if (userInfo.getIsadmin() == 0) { // 如果是普通管理员用户,这里将isadmin置为0
isadmin = 0; // 后续在查询的时候,他只能查询到isadmin为0,即只能查询到非超管用户
} // 如果是超管,isadmin则为null,查询时,就不考虑这项属性
// 处理前端的查询参数
name = name.equals("") ? null : name;
address = address.equals("") ? null : address;
email = email.equals("") ? null : email;
// 3.构建分页查询字段 limit xx,psize 查询当前页面的列表信息
// 跳过查询的条数
int skipCount = (cpage - 1) * psize;
// 查询一页的列表信息
List<UserInfo> list = userMapper.getListByPage(name, address, email,
skipCount, psize, isadmin);
// 4.查询满足条件的数据总条数
int tcount = userMapper.getCount(name, address, email, isadmin);
// 总页数
int tpage = (int) Math.ceil(tcount / (psize * 1.0));
// 封装统一返回对象
HashMap<String, Object> data = new HashMap<>();
data.put("list", list);
data.put("tcount", tcount); // 总条数
data.put("tpage", tpage); // 总条数
return new ResponseBody<>(0, "", data);
}
在UserMapper.class
接口类中添加如下方法:
// 查询一页信息
public List<UserInfo> getListByPage(String name, String address, String email,
int skipCount, int psize,
Integer isadmin);
// 查询满足条件的信息条数
public int getCount(String name, String address, String email,
Integer isadmin);
在UserMapper.xml
配置文件中添加如下SQL语句,getListByPage为查询一页信息,getCount为查询满足条件的信息条数
<select id="getListByPage" resultType="com.example.usermanager.model.UserInfo">
select * from userinfo
<where>
<if test="name!=null">
and name like concat('%',#{name},'%')
</if>
<if test="address!=null">
and address=#{address}
</if>
<if test="email!=null">
and email=#{email}
</if>
<if test="isadmin!=null">
and isadmin=#{isadmin}
</if>
</where>
order by id desc
limit #{skipCount},#{psize}
</select>
<select id="getCount" resultType="java.lang.Integer">
select count(*) from userinfo
<where>
<if test="name!=null">
and name like concat('%',#{name},'%')
</if>
<if test="address!=null">
and address=#{address}
</if>
<if test="email!=null">
and email=#{email}
</if>
<if test="isadmin!=null">
and isadmin=#{isadmin}
</if>
</where>
</select>
(2)单挑删除,以及多条删除
@RequestMapping("/del")
public ResponseBody<Integer> del(@RequestParam int id, HttpServletRequest request) {
// 权限效验
UserInfo userInfo = SessionUtil.getUserBySession(request);
if (userInfo == null) {
// 未登录
return new ResponseBody<>(-1, "未登录", 0);
}
// 判断删除的是否是自己
if (id == userInfo.getId()) {
// 删除的是自己
return new ResponseBody<>(-2, "不能删除自己", 0);
}
// 权限效验
Integer isadmin = null;
if (userInfo.getIsadmin() == 0) {
isadmin = 0;
}
int result = userMapper.del(id, isadmin);
return new ResponseBody<>(0, "", result);
}
// 多条数据删除
@RequestMapping("dels")
public ResponseBody<Integer> dels(String ids) {
int result = 0;
result = userMapper.dels(ids.split(","));
System.out.println("ids:" + ids);
return new ResponseBody<>(0, "", result);
}
在UserMapper.class
接口类中添加如下方法:
// 单挑删除
public int del(int id, Integer isadmin);
// 多条删除
public int dels(String[] ids);
在UserMapper.xml
配置文件中添加如下SQL语句
<delete id="del">
delete from userinfo
where id=#{id}
<if test="isadmin!=null">
and isadmin=#{isadmin}
</if>
</delete>
<delete id="dels">
delete from userinfo where id in
<foreach collection="ids" item="item" open="(" close=")" separator=",">
#{item}
</foreach>
</delete>
项目工程的完整文件可以点这里
链接:https://pan.baidu.com/s/1iw82k7R_ohRcSMwm7RfMag
提取码:jrdc