文章目录
一、技术栈
语言:Java
Web:html + css + js +bootstrap
数据库:MySQL8.2
服务器:Tomcat
开发环境:JDK–12、Servlet–3.0 、ntelliJ IDEA20、Navicat-11
所需知识:javase、servlet、http、request、response、cookie、session、jsp+el+jstl、filter、listener
详细总结链接:
【学Java不迷茫,真香警告】JavaSE+JavaEE详细分析总结,从入门到实战,哪里不会点哪里!
02-JavaWeb开发【Tomcat服务器&Servlet接口&HTTP协议&HttpServletRequest&BeanUtils工具包封装请求数据&HttpServletResponse】
03-JavaWeb开发【最详细的Cookie&Session分析】
04-JavaWeb开发【JSP&EL&JSTL&MVC&Bootstrap前端框架】
05-JavaWeb的三大组件:小程序Servlet+过滤器Filter+监听器Listener
也可以使用maven项目来完成哦。
开发过程中可能会出现的5中报错异常的解决方案:
关于mysql驱动版本报错解决,Cause: com.mysql.jdbc.exceptions.jdbc4、Unknown system variable ‘query_cache_size
二、业务功能流程分析图
查询所有用户
新增用户
修改用户信息
逻辑删除用户
分页显示查询结果【这个好喝呀】
首先观察下百度分页
编写流程
三、案例实现效果图
首页
登陆
显示所有用户信息
新增用户
修改用户信息
删除用户
分页所有用户信息
四、案例实现代码
注意事项
可先看这些处理概念。后面开发时需要注意的细节。
JAVA反射机制-EL表达式获取对象属性的原理
EL表达式获取对象属性的原理是这样的:
在EL中,对一个Bean的某字段进行引用,只需 ${bean.field},当然,这个bean是已经被set到容器中的。
我们从容器中取出以bean为名字的Object,通过Java反射机制知道它的真实类型,然后通过field以javabean规范拼出方法名(首字母大写并加上get前缀),进行调用,一旦找到与之匹配的方法,El表达式就会认为这就是要访问的属性,并返回属性的值。所以,想要通过EL表达式获取对象属性的值,那么这个属性就必须有与之对应的get方法。
如果这个表达式是多级的,如${bean.field.field},其中第一个field本身就是一个bean对象,同样需要递归的进行解析。
所以这中间不关私有属性的事,调用的是私有属性的get/set方法。
如果你不写get/set方法,那EL表达式就拿不到值了。set方法是给你后台设置值用的。
这样取值的${bean.getFiled}.是死活都取不到的,改成了${user.field}就取到了。
[友友遇到的报错] Bean类少了 一个参数的get方法 EL表达式解析不到值
1、数据库设计
admin
create table admin(
id int primary key auto_increment,
username varchar(50) not null unique,
password varchar(50) not null unique
);
insert into user values(null,'admin','1234');
t_user
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`sex` varchar(50) NOT NULL,
`age` int(11) NOT NULL,
`address` varchar(50) NOT NULL,
`qq` varchar(50) NOT NULL,
`email` varchar(50) NOT NULL UNIQUE,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of t_user
-- ----------------------------
INSERT INTO `t_user` VALUES ('1', '霍建华', '男', '280', '广西', '766335435', 'zs@qq.com');
INSERT INTO `t_user` VALUES ('2', '李四', '男', '22', '广东', '243424242', 'ls@qq.com');
INSERT INTO `t_user` VALUES ('3', '王五', '女', '230', '广东', '474574574', 'ww@qq.com');
INSERT INTO `t_user` VALUES ('4', '赵六', '女', '28', '广东', '77777777', 'zl@qq.com');
INSERT INTO `t_user` VALUES ('5', '钱七', '女', '25', '湖南', '412132145', 'qq@qq.com');
INSERT INTO `t_user` VALUES ('7', '锁哥', '男', '18', '黑龙江', '361', '520@qq.com');
INSERT INTO `t_user` VALUES ('8', '关晓彤', '女', '22', '广东', '361', '361@qq.con');
INSERT INTO `t_user` VALUES ('9', '刘亦菲', '女', '28', '湖南', '362', '362@qq.com');
INSERT INTO `t_user` VALUES ('10', '柳岩', '女', '38', '广西', '363', '363@qq.com');
INSERT INTO `t_user` VALUES ('11', '鹿晗', '女', '300', '广西', '2250', '2250@qq.com');
INSERT INTO `t_user` VALUES ('12', '赵丽颖', '女', '28', '广西', '28', '28@qq.com');
INSERT INTO `t_user` VALUES ('13', '刘德华', '男', '53', '广东', '361', '53@qq.com');
INSERT INTO `t_user` VALUES ('14', '刘亦菲', '女', '28', '广东', '1122', '1122@qq.com');
INSERT INTO `t_user` VALUES ('15', '锁哥', '男', '18', '黑龙江', '111', '111@qq.com');
2、项目结构
1)src
2)web
3)工具包
4)配置文件
jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/user_managerment\
?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false
jdbc.username=root
jdbc.password=1234
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--加载外部的配置文件-->
<properties resource="jdbc.properties"/>
<!--别名-->
<typeAliases>
<package name="com.test.sh.pojo"/>
</typeAliases>
<!--mybatis环境的配置
一个核心配置文件,可以配置多个运行环境,default默认使用哪个运行环境
-->
<environments default="development">
<!--通常我们只需要配置一个就可以了, id是环境的名字 -->
<environment id="development">
<!--事务管理器:由JDBC来管理-->
<!--
事务管理器type的取值:
1. JDBC:由JDBC进行事务的管理
2. MANAGED:事务由容器来管理,后期学习Spring框架的时候,所有的事务由容器管理
-->
<transactionManager type="JDBC"/>
<!--数据源的配置:mybatis自带的连接池-->
<!--
数据源:
1. POOLED:使用mybatis创建的连接池
2. UNPOOLED:不使用连接池,每次自己创建连接
3. JNDI:由服务器提供连接池的资源,我们通过JNDI指定的名字去访问服务器中资源。
-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!--映射器-->
<mappers>
<!--加载其它的映射文件 注:注解开发是点号-->
<!--<package name="com.test.sh.dao"></package>-->
<!--
加载其它的映射文件 xml形式
包扫描方式加载mapper映射文件,说明:
1. 要求mapper映射文件,与mapper接口要放在同一个目录
2. 要求mapper映射文件的名称,与mapper接口的名称要一致
-->
<package name="com.test.sh.dao"/>
</mappers>
</configuration>
log4j.properties
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c]-[%p] %m%n
### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=D:/IdeaProjects/mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c]-[%p] %m%n
### set log levels - for more verbose logging change 'info' to 'debug' ###
log4j.rootLogger=debug, stdout,file
5)web页面
index.html
<!--<%--
Created by IntelliJ IDEA.
User: cfl
Date: 2021/05/03
Time: 8:24
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>-->
<html>
<head>
<!-- 指定字符集 -->
<meta charset="utf-8">
<!--使用微软最新的浏览器Edge的内核来解析当前的HTML文件,最新的浏览器都支持 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!--
响应式布局参数:
viewport: 视口的参数
width=device-width:默认的网页宽度是设备的宽度
initial-scale=1: 初始的缩放比1:1
-->
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<!-- 1. 导入bootstrap的全局css样式 -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<title>用户管理系统</title>
</head>
<body>
<h3 font-siz:200px align="center" style="color: darkturquoise">用户后台管理系统</h3>
<br><br>
<div class="container">
<!-- 默认是白色,navbar-inverse 表示黑色-->
<nav class="navbar navbar-inverse">
<!-- container-fluid 表示占容器nav的100%-->
<div class="container-fluid">
<!-- navbar-header表示指定商标和开关的样式,让它在手机上更好的显示-->
<div class="navbar-header">
<!--开关按钮-->
<!--data-toggle="collapse" 表示点击按钮时可以折叠
data-target 点击开关按钮时,可以找到id是bs-example-navbar-collapse-1下拉菜单
而我们发现下面的下拉菜单的id正好是 bs-example-navbar-collapse-1
-->
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
data-target="#bs-example-navbar-collapse-1">
<!--开关按钮中的白线-->
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<!--navbar-brand 表示商标 类似于苹果网站的苹果标志,无论设备窗口怎么变化,商标都会存在-->
<a class="navbar-brand" href="#">Manager</a>
</div>
<!-- 下拉菜单,表单等 navbar-collapse 表示可以折叠的所有的项-->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li class="active">
<span class="sr-only">(current)</span></a>
<a href="/register.jsp" class="dropdown-toggle" data-toggle="dropdown"
role="button" aria-haspopup="true" aria-expanded="false">注册
<!--向下箭头-->
</a>
</li>
<li class="dropdown">
<a href="/login.jsp" class="dropdown-toggle" data-toggle="dropdown"
role="button" aria-haspopup="true" aria-expanded="false">登陆
<!--向下箭头-->
</a>
</li>
<li class="dropdown">
<a href="/images.jsp" class="dropdown-toggle" data-toggle="dropdown"
role="button" aria-haspopup="true" aria-expanded="false">查询
</a>
</li>
<li class="dropdown">
<a href="/books.jsp" class="dropdown-toggle" data-toggle="dropdown"
role="button" aria-haspopup="true" aria-expanded="false">分页
</a>
</li>
</ul>
<!--navbar-right表示form表单位于右侧-->
<form class="navbar-form navbar-right">
<div class="form-group">
<input type="search" class="form-control" placeholder="关键字">
</div>
<button type="submit" class="btn btn-default">搜索</button>
</form>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
</div>
<br><br><br>
<div align="center" style="font-size: 17px">
<figure>
<div>
<a href="/login.jsp" class="btn btn-primary" style="text-decoration:none;font-size:20px" >登陆用户管理系统</a>
</div>
</figure>
<br>
<figure>
<div>
<a href="/queryUserInfoServlet"
class="btn btn-info" style="text-decoration:none;font-size:20px" >查询所有用户信息</a>
</div>
</figure>
<br>
<figure>
<div>
<a href="/pageBeanServlet?curPage=1"
class="btn btn-success" style="text-decoration:none;font-size:20px">分页显示用户信息</a>
</div>
</figure>
<br>
</div>
<br><br>
<br><br>
<br><br>
<br><br>
<br><br>
<br><br>
<div class="footer" align="center" style="font-size: 16px">
<div class="foot_link">
<a href="#">关于作者</a>
<span>|</span>
<a href="#">联系作者</a>
<span>|</span>
<a href="#">招聘合作</a>
<span>|</span>
<a href="#">友情链接</a>
</div>
<p>CopyRight © 2021 上海菜鸟程序员研学中心 All Rights Reserved</p>
<p>电话:010-5211314 沪ICP备666888号</p>
</div>
<!-- 2. 导入 jQuery 框架 -->
<script src="js/jquery-3.2.1.min.js"></script>
<!-- 3. 导入bootstrap框架 -->
<script src="js/bootstrap.min.js"></script>
</body>
</html>
login.jsp
<%--
Created by IntelliJ IDEA.
User: cfl
Date: 2021/04/27
Time: 23:24
To change this template use File | Settings | File Templates.
--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<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">
<link href="css/login.css" rel="stylesheet">
<script src="js/jquery.js"></script>
<script src="js/bootstrap.js"></script>
<style type="text/css">
#cookie {
font-size: 2px;
}
</style>
</head>
<body>
<div align="left">
<a href="/index.html" class="btn btn-success">首页</a>
</div>
<div class="container text-center">
<form class="form-signin" action="${pageContext.request.contextPath}/loginUserServlet" method="post">
<h3 class="form-signin-heading">登录</h3>
<input type="text" name="name" value="${cookie.name.value}"
class="form-control" placeholder="用户名" aria-describedby="sizing-addon1"
required autofocus>
<br>
<input type="password" name="password" value="${cookie.password.value}" class="form-control" placeholder="密码"
required>
<div align="left">
<table>
<tr>
<td>
<span id="cookie"><b>记住用户名密码:</b></span>
</td>
<td>
<input type="checkbox" name="checkbox">
</td>
</tr>
</table>
</div>
<br>
<button class="btn btn-lg btn-primary btn-block" type="submit">登录</button>
</form>
<font color="#d3d3d3" size="2px">${requestScope.msgErr}</font>
</div>
<script type="text/javascript">
function changeCheckCode(obj) {
obj.src = "/checkCodeServlet?" + new Date().getTime();
}
</script>
</body>
</html>
userList.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--
Created by IntelliJ IDEA.
User: cfl
Date: 2021/05/03
Time: 10:02
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<!--使用微软最新的浏览器Edge的内核来解析当前的HTML文件,最新的浏览器都支持 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!--
响应式布局参数:
viewport: 视口的参数
width=device-width:默认的网页宽度是设备的宽度
initial-scale=1: 初始的缩放比1:1
-->
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<!-- 1. 导入bootstrap的全局css样式 -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<title>用户信管理系统</title>
<style type="text/css">
td, th {
text-align: center;
}
</style>
</head>
<body>
<table class="table table-striped text-left">
<tr>
<td>
<a href="${pageContext.request.contextPath}/index.html" class="btn btn-primary">主页</a>
</td>
<td>
<a href="${pageContext.request.contextPath}/pageBeanServlet?curPage=1" class="btn btn-info">分页显示</a>
</td>
<td>
<a class="btn btn-success" href="addUser.jsp">添加用户</a>
</td>
<td>
<div class="input-group">
<input type="text" class="form-control" name="搜索用户" placeholder="搜索用户" onclick="searchKey()" aria-describedby="basic-addon1">
</div>
</td>
</tr>
</table>
<div class="container">
<span style="color: crimson">${requestScope.deleteSuccessful}</span>
<span style="color: crimson">${requestScope.deleteError}</span>
<span style="color: crimson">${requestScope.updateSuccessful}</span>
<span style="color: crimson">${requestScope.updateError}</span>
<h3 style="text-align: center">用户信息列表</h3><br>
<table border="1" class="table table-bordered table-hover">
<tr class="success">
<th>编号</th>
<th>姓名</th>
<th>性别</th>
<th>年龄</th>
<th>籍贯</th>
<th>QQ</th>
<th>邮箱</th>
<th>操作</th>
</tr>
<c:forEach items="${requestScope.userList}" var="user">
<tr>
<td>${user.id}</td>
<td>${user.name}</td>
<td>${user.sex}</td>
<td>${user.age}</td>
<td>${user.address}</td>
<td>${user.qq}</td>
<td>${user.email}</td>
<td>
<a class="btn btn-default btn-sm"
href="${pageContext.request.contextPath}/queryUserByIdServlet?id=${user.id}">修改
</a>
<a class="btn btn-default btn-sm"
<%-- href="javascript:void(0)"--%>
href="javascript:void(0)"
οnclick="deleteUserById(${user.id})">删除
</a>
</td>
</tr>
</c:forEach>
</table>
</div>
<!-- 2. 导入 jQuery 框架 -->
<script src="js/jquery-3.2.1.min.js"></script>
<!-- 3. 导入bootstrap框架 -->
<script src="js/bootstrap.min.js"></script>
<script type="text/javascript">
function deleteUserById(id) {
// alert(id)
let b = window.confirm("是否确认删除?");
if (b) {
// 确认-》跳转到 web deleteUserServlet处理类
window.location.href = "deleteUserServlet?id=" + id;
}
}
</script>
</body>
</html>
addUser.jsp
<%--
Created by IntelliJ IDEA.
User: cfl
Date: 2021/05/03
Time: 10:34
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<!--使用微软最新的浏览器Edge的内核来解析当前的HTML文件,最新的浏览器都支持 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!--
响应式布局参数:
viewport: 视口的参数
width=device-width:默认的网页宽度是设备的宽度
initial-scale=1: 初始的缩放比1:1
-->
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<link href="css/login.css" rel="stylesheet">
<!-- 2. 导入 jQuery 框架 -->
<script src="js/jquery-3.2.1.min.js"></script>
<!-- 3. 导入bootstrap框架 -->
<script src="js/bootstrap.min.js"></script>
<script src="js/jquery.js"></script>
<script src="js/bootstrap.js"></script>
<title>Title</title>
</head>
<body>
<div class="container text-left">
<center><h3>添加联系人页面</h3></center>
<center><font color="red">${requestScope.msg}</font></center>
<form action="${pageContext.request.contextPath}/addUserServlet" method="post" class="form-horizontal">
<div class="form-group">
<label class="col-lg-2 control-label" for="name">姓名:</label>
<div class="col-lg-8">
<input type="text" class="form-control" id="name" name="name" placeholder="请输入姓名">
</div>
<label class="col-lg-2 control-label" id="nameMsg"></label>
</div>
<div class="form-group">
<label class="col-lg-2 control-label">性别:</label>
<div class="col-lg-3">
<input type="radio" name="sex" value="男" checked="checked"/>男
</div>
<div class="col-lg-3">
<input type="radio" name="sex" value="女"/>女
</div>
<label class="col-lg-2 control-label" id="sexMsg"></label>
</div>
<div class="form-group">
<label for="age" class="control-label col-lg-2">年龄:</label>
<div class="col-lg-8">
<input type="text" class="form-control" id="age" name="age" placeholder="请输入年龄">
</div>
</div>
<div class="form-group">
<label for="jiguan" class="col-lg-2 control-label">籍贯:</label>
<div class="col-lg-8">
<select name="address" class="form-control" id="jiguan">
<option value="广东">广东</option>
<option value="广西">广西</option>
<option value="湖南">湖南</option>
</select>
</div>
</div>
<div class="form-group">
<label for="qq" class="control-label col-lg-2">QQ:</label>
<div class="col-lg-8">
<input type="text" class="form-control" id="qq" name="qq" placeholder="请输入QQ号码"/>
</div>
</div>
<div class="form-group">
<label for="email" class="col-lg-2 control-label">Email:</label>
<div class="col-lg-8">
<input type="text" class="form-control" id="email" name="email" placeholder="请输入邮箱地址"/>
</div>
</div>
<div class="form-group" style="text-align: center">
<input class="btn btn-primary" type="submit" value="提交" />
<input class="btn btn-default" type="reset" value="重置" />
<%-- <input class="btn btn-default" type="button" value="返回" />--%>
</div>
</form>
</div>
</body>
</html>
update.jsp
<%--
Created by IntelliJ IDEA.
User: cfl
Date: 2021/05/03
Time: 16:00
To change this template use File | Settings | File Templates.
--%>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE html>
<!-- 网页使用的语言 -->
<html lang="zh-CN">
<head>
<base href="<%=basePath%>"/>
<!-- 指定字符集 -->
<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>
<script src="js/bootstrap.min.js"></script>
</head>
<body>
<div class="container" style="width: 400px;">
<h3 style="text-align: center;">修改联系人</h3>
<form action="/updateUserServlet" method="post">
<%-- 【id不需要显示在页面上,通过隐藏域传递值】
type="hidden" 表示隐藏域 页面不会显示 但是真实存在
--%>
<input type="hidden" value="${user.id}" name="id">
<div class="form-group">
<label for="name">姓名:</label>
<input type="text" value="${user.name}"
class="form-control" id="name" name="name" placeholder="请输入姓名" />
</div>
<div class="form-group">
<label>性别:</label>
<input type="radio" name="sex" value="男"
<c:if test="${user.sex == '男'}">
checked="checked"
</c:if>
/>男
<input type="radio" name="sex" value="女"
<c:if test="${user.sex == '女'}">
checked="checked"
</c:if>
/>女
</div>
<div class="form-group">
<label for="age">年龄:</label>
<input type="text" value="${user.age}"
class="form-control" id="age" name="age" placeholder="请输入年龄" />
</div>
<div class="form-group">
<label for="address" id="address">籍贯:</label>
<select name="address" class="form-control" >
<option value="广东"
<c:if test="${user.address=='广东'}">
selected="selected"
</c:if>
>广东</option>
<option value="广西"
<c:if test="${requestScope.user.address=='广西'}">
selected="selected"
</c:if>
>广西</option>
<option value="湖南"
<c:if test="${user.address=='湖南'}">selected="selected"</c:if>
>湖南</option>
</select>
</div>
<div class="form-group">
<label for="qq" id="qq">QQ:</label>
<input type="text" value="${user.qq}"
readonly="readonly" class="form-control" name="qq" placeholder="请输入QQ号码"/>
</div>
<div class="form-group">
<label for="email" id="email">Email:</label>
<input type="text" value="${user.email}"
readonly="readonly" class="form-control" name="email" placeholder="请输入邮箱地址"/>
</div>
<div class="form-group" style="text-align: center">
<input class="btn btn-primary" type="submit" value="提交" />
<input class="btn btn-default" type="reset" value="重置" />
<%-- <input class="btn btn-default" type="button" value="返回"/>--%>
</div>
</form>
</div>
</body>
</html>
updateOk.jsp
可不用 更新后直接转发到查询 提示是否更新成功,并重新显示所有用户信息
<%--
Created by IntelliJ IDEA.
User: cfl
Date: 2021/05/03
Time: 15:29
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<!-- 指定字符集 -->
<meta charset="utf-8">
<!-- 使用Edge最新的浏览器的渲染方式 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- viewport视口:网页可以根据设置的宽度自动进行适配,在浏览器的内部虚拟一个容器,容器的宽度与设备的宽度相同。
width: 默认宽度与设备的宽度相同
initial-scale: 初始的缩放比,为1:1 -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<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>
</head>
<body>
<div align="center">
<center><font color="red">${requestScope.updateSuccessful}</font></center>
<center><font color="red">${requestScope.deleteError}</font></center>
<a href="${pageContext.request.contextPath}/queryUserInfoServlet"
class="btn btn-success" style="text-decoration:none;font-size:33px">查询所有用户信息</a>
<a href="${pageContext.request.contextPath}/index.html"
class="btn btn-success" style="text-decoration:none;font-size:33px">主页</a>
</div>
</body>
</html>
deleteOk.jsp
可不用 删除后直接转发到查询 提示是否删除成功,并重新显示所有用户信息
<%--
Created by IntelliJ IDEA.
User: cfl
Date: 2021/05/03
Time: 15:29
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<!-- 指定字符集 -->
<meta charset="utf-8">
<!-- 使用Edge最新的浏览器的渲染方式 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- viewport视口:网页可以根据设置的宽度自动进行适配,在浏览器的内部虚拟一个容器,容器的宽度与设备的宽度相同。
width: 默认宽度与设备的宽度相同
initial-scale: 初始的缩放比,为1:1 -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<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>
</head>
<body>
<div align="center">
<center><font color="red">${requestScope.deleteSuccessful}</font></center>
<center><font color="red">${requestScope.deleteError}</font></center>
<a href="${pageContext.request.contextPath}/queryUserInfoServlet"
class="btn btn-success" style="text-decoration:none;font-size:33px">查询所有用户信息</a>
<a href="${pageContext.request.contextPath}/index.html"
class="btn btn-success" style="text-decoration:none;font-size:33px">主页</a>
</div>
</body>
</html>
page.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--
Created by IntelliJ IDEA.
User: cfl
Date: 2021/05/03
Time: 10:02
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<!--使用微软最新的浏览器Edge的内核来解析当前的HTML文件,最新的浏览器都支持 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!--
响应式布局参数:
viewport: 视口的参数
width=device-width:默认的网页宽度是设备的宽度
initial-scale=1: 初始的缩放比1:1
-->
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<!-- 1. 导入bootstrap的全局css样式 -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<title>用户信管理系统</title>
<style type="text/css">
td, th {
text-align: center;
}
</style>
</head>
<body>
<table class="table table-striped text-left">
<tr>
<td>
<a href="${pageContext.request.contextPath}/index.html" class="btn btn-primary">主页</a>
</td>
<td>
<a class="btn btn-success" href="addUser.jsp">添加用户</a>
</td>
<td>
<div class="input-group">
<%-- <input type="button" class="btn btn-info" value="搜索用户" onclick="searchKey()"/>--%>
<%-- <span class="input-group-addon" id="basic-addon1" >添加用户</span>--%>
<input type="text" class="form-control" name="搜索用户" placeholder="搜索用户" onclick="searchKey()" aria-describedby="basic-addon1">
</div>
</td>
</tr>
</table>
<div class="container">
<h3 style="text-align: center">用户信息列表</h3><br>
<table border="1" class="table table-bordered table-hover">
<tr class="success">
<th>编号</th>
<th>姓名</th>
<th>性别</th>
<th>年龄</th>
<th>籍贯</th>
<th>QQ</th>
<th>邮箱</th>
<th>操作</th>
</tr>
<c:forEach items="${pb.data}" var="u">
<tr>
<td>${u.id}</td>
<td>${u.name}</td>
<td>${u.sex}</td>
<td>${u.age}</td>
<td>${u.address}</td>
<td>${u.qq}</td>
<td>${u.email}</td>
<td>
<a class="btn btn-default btn-sm" href="/queryUserByIdServlet?id=${u.id}">修改</a>
<a class="btn btn-default btn-sm" href="javascript:void(0)" onclick="deleteUserById(${u.id})">删除</a>
</td>
</tr>
</c:forEach>
<%-- <tr>
<td colspan="8" align="center"><a class="btn btn-primary" href="addUser.jsp">添加联系人</a></td>
</tr>--%>
</table>
<br><br>
<br><br>
<br>
<%--分页栏--%>
<div align="center">
<nav>
<ul class="pagination">
<%-- 上一页 --%>
<%-- 判断当前页是否等于1,如果等于1,不能点击上一页 --%>
<c:if test="${requestScope.pb.curPage==1}">
<li class="disabled">
<a href="#">
<span>«</span>
</a>
</li>
</c:if>
<%--如果当前页不等于1,可以点击上一页,那么在当前页面上-1--%>
<c:if test="${requestScope.pb.curPage!=1}">
<li>
<a href="/pageBeanServlet?curPage=${pb.curPage-1}">
<span>«</span>
</a>
</li>
</c:if>
<%-- 页码显示区
begin="1" 表示从第一页开始
end="${pb.totalPage}" 表示最后一页
var="n" 表示每一页
--%>
<c:forEach begin="1" end="${requestScope.pb.totalPage}" var="n">
<c:if test="${pb.curPage==n}">
<li class="active"><span style="background-color: hotpink">${n}</span></li>
</c:if>
<c:if test="${pb.curPage!=n}">
<li class="active"><a href="/pageBeanServlet?curPage=${n}">${n}</a></li>
</c:if>
</c:forEach>
<%-- 下一页 --%>
<%-- 判断当前页是否等于最后一页,如果等于,不能点击下一页 --%>
<c:if test="${pb.curPage==pb.totalPage}">
<li class="disabled">
<a href="#"><span>»</span></a>
</li>
</c:if>
<%--如果当前页不等于最后一页,可以点击下一页,并且在当前页面上+1--%>
<c:if test="${pb.curPage!=pb.totalPage}">
<li>
<a href="/pageBeanServlet?curPage=${pb.curPage+1}"><span>»</span></a>
</li>
</c:if>
</ul>
</nav>
</div>
</div>
<!-- 2. 导入 jQuery 框架 -->
<script src="js/jquery-3.2.1.min.js"></script>
<!-- 3. 导入bootstrap框架 -->
<script src="js/bootstrap.min.js"></script>
<script type="text/javascript">
function deleteUserById(id) {
// alert(id)
let b = window.confirm("是否确认删除?");
if (b) {
// 确认-》跳转到 web deleteUserServlet处理类
window.location.href = "deleteUserServlet?id=" + id;
}
}
</script>
</body>
</html>
3、后端业务代码实现
1)test测试连接数据库
public class TestUser {
@Test
public void testQuery(){
// 创建sql 会话对象
//SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSession();
// 获取接口对象 (代理类)
UserMapper userMapper = SqlSessionFactoryUtils.getMapper(UserMapper.class);
// 使用代理对象调用 查询方法
List<User> userList = userMapper.queryUserInfo();
userList.forEach(System.out::println);
}
}
2)util工具
CommonUtils工具类
封装数据到实体类中 使用 BeanUtils 工具包
public class CommonUtils {
//静态方法向实体类中封装数据
public static <T> T commonPopulate(Class<T> clazz,
HttpServletRequest request){
T obj = null;
//通过字节码对象创建实体类对象
try {
obj = clazz.newInstance();
//将map集合中的数据封装到实体类中
BeanUtils.populate(obj,request.getParameterMap());
} catch (Exception e) {
e.printStackTrace();
}
//返回对象
return obj;
}
}
SessionFactoryUtil 工具类
public class SqlSessionFactoryUtils {
/**
* 1. 全局变量 【维护会话工厂】
* 2. ThreadLocal是一个JDK自带的线程容器,给线程绑定一个Object内容,
* 只要线程不变,可直接取出
* ThreadLocal不是用来解决对象共享访问问题的,
* 而主要是提供了保持对象的方法和避免参数传递的方便的对象访问方式。归纳了两点:
* 1。每个线程中都有一个自己的ThreadLocalMap类对象,
* 2。将一个共用的ThreadLocal静态实例作为key,
*/
private static SqlSessionFactory sqlSessionFactory;
private static final ThreadLocal<SqlSession> threadLocal = new ThreadLocal<>();
/* 2. 静态代码块加载mybatis核心配置文件,初始化sqlSessionFactory */
static {
initFactory();
}
/**
* 3. 创建 初始化session工厂的 方法
*/
private static void initFactory() {
String resource = "mybatis-config.xml";
InputStream is = null;
try {
is = Resources.getResourceAsStream(resource);
} catch (IOException e) {
e.printStackTrace();
}
sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
}
/**
* 4. 创建 获取sql会话对象的 方法
*/
public static SqlSession getSqlSession() {
// 获得本地线程容器里的 sqlSession对象
SqlSession sqlSession = threadLocal.get();
if (sqlSession == null) {
sqlSession = sqlSessionFactory.openSession();
// 把对象放回线程中,通过threadLocal线程容器
// 【为每一个线程都维护一个私有的会话对象,防止出现并发问题】
threadLocal.set(sqlSession);
}
return sqlSession;
}
/**
* 5. 创建 获取动态代理对象的 方法
*/
public static <T> T getMapper(Class<T> tClass) {
// 调用获取sql会话对象方法
SqlSession sqlSession = getSqlSession();
// 获得动态代理对象
return sqlSession.getMapper(tClass);
}
/**
* 6. 创建 关闭资源 的方法
*/
public static void close() {
SqlSession sqlSession = threadLocal.get();
if (sqlSession != null) {
sqlSession.close();
}
}
/**
* 7. 创建 事务提交 方法
*/
public static void commit() {
SqlSession sqlSession = threadLocal.get();
if (sqlSession != null) {
sqlSession.commit();
}
}
/**
* 8. 创建 事务回滚 方法
*/
public static void rollback() {
SqlSession sqlSession = threadLocal.get();
if (sqlSession != null) {
sqlSession.rollback();
}
}
}
EncodingFilter 处理请求与响应编码
@WebFilter("/*")
public class EncodingFilter implements Filter {
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
//如果是POST方法,就对汉字进行编码的操作
request.setCharacterEncoding("utf-8");
//处理响应乱码
response.setContentType("text/html;charset=utf-8");
chain.doFilter(request, response);
}
@Override
public void init(FilterConfig config) throws ServletException {
}
}
LoginUserFilter未登录拦截访问
//@WebFilter(value = "*.jsp")
/*@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface WebInitParam {
String name();
String value();
String description() default "";
}*/
@WebFilter(value = {"/userList.jsp", "/page.jsp","/update.jsp"},
dispatcherTypes = {DispatcherType.REQUEST,DispatcherType.FORWARD})
public class LoginUserFilter implements Filter {
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
Admin admin = (Admin) request.getSession().getAttribute("admin");
if (admin == null) {
// 重定向 默认拦截 据情况而定
// response.sendRedirect("/login.jsp");
// 转发 过滤器默认不拦截
request.getRequestDispatcher("/login.jsp")
.forward(request, response);
} else {
chain.doFilter(request, response);
}
}
@Override
public void init(FilterConfig config) throws ServletException {
}
}
3)pojo实体类
Admin类
public class Admin {
private Integer id;
private String name;
private String password;
@Override
public String toString() {
return "Admin{" +
"id=" + id +
", name='" + name + '\'' +
", password='" + password + '\'' +
'}';
}
public Admin() {
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
User类
/*
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`sex` varchar(50) NOT NULL,
`age` int NOT NULL,
`address` varchar(50) NOT NULL,
`qq` varchar(50) NOT NULL,
`email` varchar(50) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `email` (`email`)
*/
public class User {
private Integer id;
private String name;
private String sex;
private Integer age;
private String address;
private String qq;
private String email;
private Integer isDelete;
public Integer getIsDelete() {
return isDelete;
}
public void setIsDelete(Integer isDelete) {
this.isDelete = isDelete;
}
public User() {
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", sex='" + sex + '\'' +
", age=" + age +
", address='" + address + '\'' +
", qq='" + qq + '\'' +
", email='" + email + '\'' +
", isDelete=" + isDelete +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getQq() {
return qq;
}
public void setQq(String qq) {
this.qq = qq;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
PageBean类
public class PageBean {
/*
1. 实现分页查询需要用到5个变量:
1)当前页数:curPage; // 当前页数curPage是页面上用户选择的。需要从前台传递过来;
2)每页显示的数据条数:pageSize;// 每页显的数据条数:pageSize,可以由我们程序员指定;
3)查询时的起始索引:startIndex;// 查询时的起始索引:startIndex= (curPage-1)*pageSize;
4)数据库中的数据总条数count;
5)每一页显示的数据 List<User> data; // 由数据库查询的数据来提供;
6. totalPage(总的页数) // 不需要定义属性 在页面显示需要此数据
=Math.ceil(count(总条数)*1.0/pageSize(每一页显示的数据的条数)
*/
private int curPage;
private int pageSize;
private int count;
private List<User> data;
@Override
public String toString() {
return "PageBean{" +
"curPage=" + curPage +
", pageSize=" + pageSize +
", count=" + count +
", data=" + data +
'}';
}
public PageBean() {
}
public int getStartIndex(){
return (curPage - 1) * pageSize;
}
public int getTotalPage() {
return (int) Math.ceil(count*1.0/pageSize);
}
public int getCurPage() {
return curPage;
}
public void setCurPage(int curPage) {
this.curPage = curPage;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public List<User> getData() {
return data;
}
public void setData(List<User> data) {
this.data = data;
}
}
ter
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "Book{" +
"id=" + id +
", name='" + name + '\'' +
", author='" + author + '\'' +
", price=" + price +
'}';
}
}
4)dao层
UserMapper映射接口
public interface UserMapper {
@Select("select * from admin where name=#{name} and password=#{password}")
public Admin queryAdmin(Admin admin);
// 1、查询所有用户
@Select("select * from t_user where is_delete = 0")
public List<User> queryUserInfo();
// 2、查询时的 email=#{email} #{} 中的可以任意定义
// 如果有@Param("email") String #{} 中的必须和@Param("")双引号中的保持一致
@Select("select * from t_user where email=#{email}")
public User queryUserByEmail(String email);
// 插入时 #{}中的值 和 pojo实体类的 get set 方法名 后的值保持一致 底层是反射
@Insert("insert into t_user value(null,#{name},#{sex}," +
"#{age},#{address},#{qq},#{email},0)")
public int addUser(User user);
// 3、软删除用户
@Update("update t_user set is_delete=1 where id=#{id}")
public int deleteUserById(Integer id);
///4、根据id查询用户 浏览器回显
@Select("select * from t_user where id=#{id}")
public User queryUserById(Integer id);
// 根据id 更新用户信息
@Update("update t_user set name=#{name},sex=#{sex},age=#{age},address=#{address} where id=#{id} ")
public int updateUserById(User user);
///5、分页查询 每页显示的数据
@Select("select *from t_user where is_delete=0 limit #{startIndex},#{pageSize}")
public List<User> queryPageData(@Param("startIndex") int startIndex,@Param("pageSize") int pageSize);
// 查询用户的总数
@Select("select count(*) from t_user where is_delete = 0")
public int queryUserCount();
}
5)service层
UserService业务处理
public class UserService {
// 管理员登陆
public boolean queryAdminBy(Admin admin) {
UserMapper userMapper = SqlSessionFactoryUtils.getMapper(UserMapper.class);
Admin ad = userMapper.queryAdmin(admin);
return ad != null;
}
// 查询用户信息业务
public List<User> queryUserInfo() {
// 创建sql 会话对象
//SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSession();
// 获取接口对象 (代理类)
UserMapper userMapper = SqlSessionFactoryUtils.getMapper(UserMapper.class);
// 使用代理对象调用 查询方法
List<User> userList = userMapper.queryUserInfo();
// 在这里关闭sql会话 这里不能在更新 和 删除 业务处理时关闭
// 因为 更新 和 删除 业务 处理结束 要转发到查询 业务 ,是一个线程处理
// 因为 sql会话 在工具类创建的 使用了ThreadLocal线程,
// 关闭再创建也是另一个线程的sql会话了,
SqlSessionFactoryUtils.close();
return userList;
}
// 添加用户业务
public boolean addUser(User user) {
// 创建sql会话对象 和 获取映射接口类(代理类)
UserMapper userMapper = SqlSessionFactoryUtils.getMapper(UserMapper.class);
// 接口对象调用 User queryUserByEmail()方法 判断用户是否存在
User u = userMapper.queryUserByEmail(user.getEmail());
// 不存在 进行添加
if (u == null) {
int row = userMapper.addUser(user);
if (row > 0) {
// 修改成功 提交事务 关闭会话
SqlSessionFactoryUtils.commit();
SqlSessionFactoryUtils.close();
return true;
} else {
return false;
}
}
// 存在 直接返回不成功
return false;
}
// 删除用户业务
public boolean deleteUser(Integer id) {
// 获取sql会话对象 和 映射接口对象
UserMapper userMapper = SqlSessionFactoryUtils.getMapper(UserMapper.class);
// 调用 软删除 方法 ,删除用户
int row = userMapper.deleteUserById(id);
System.out.println(row);
if (row > 0) {
SqlSessionFactoryUtils.commit();
// 使用了ThreadLocal线程 不能在这里关
// SqlSessionFactoryUtils.close();
return true;
}
return false;
}
// 根据id 查询用户业务
public User queryUserById(Integer id) {
// 获取sql会话对象 获取映射接口对象
UserMapper userMapper = SqlSessionFactoryUtils.getMapper(UserMapper.class);
return userMapper.queryUserById(id);
}
// 根据用户id 更新 用户信息
public boolean updateUserById(User user) {
// 获取mybatis 的 sql会话对象 和 映射接口对象
SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
int row = userMapper.updateUserById(user);
if (row > 0) {
SqlSessionFactoryUtils.commit();
// SqlSessionFactoryUtils.close();
return true;
}
return false;
}
public PageBean getPageBean(PageBean pb) {
// 获取sql会话对象 和 映射接口对象
UserMapper userMapper = SqlSessionFactoryUtils.getMapper(UserMapper.class);
// 调用dao层方法查询每页显示的数据
List<User> onePageData = userMapper.queryPageData(pb.getStartIndex(), pb.getPageSize());
pb.setData(onePageData);
// 调用dao层方法查询总共有多少用户
int count = userMapper.queryUserCount();
pb.setCount(count);
return pb;
}
}
6)web层
CheckCodeServlet(生成验证码)
@WebServlet("/checkCodeServlet")
public class CheckCodeServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("----请求验证码----");
/*
说明:验证码是一张图片,而这个图片中的内容是使用代码生成的。
分析和步骤:
1)创建一个可以存放图片的缓冲区BufferedImage作为画布;
2)通过画布获取到针对这个画布的画笔;
3)修改画布的背景颜色为白色;
4)设置画布的边框,画边框的时候需要注意下,如果这里写画布的宽width和高height ,就会超出画布就会看不见,所以width和height 分别-1;
5)创建一个获取随机数的对象;
6)给画布上写数据;
7)给画布上画干扰线;
8)需要把画布中的内容响应给浏览器;ImageIO.write(bi,"JPG",response.getOutputStream());
*/
//定义画布的宽和高
int width=120;
int height=30;
//创建一个可以存放图片的缓冲区,作为画布
//BufferedImage.TYPE_INT_RGB 表示生成图片的类型
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//通过画布获取到针对这个画布的画笔
Graphics g = bi.getGraphics();
//修改画布的背景颜色 每次使用画笔的时候都得给画笔指定颜色
g.setColor(Color.WHITE);
//填充画布
g.fillRect(0, 0, width, height);
//设置画布的边框
//给画笔指定颜色
g.setColor(Color.RED);
//给画布画边框 如果这里写width height 就会超过画布,因为边框也会占一个像素,所以这里宽和高都需要-1
g.drawRect(0, 0, width-1, height-1);
//创建一个获取随机数的对象
Random r = new Random();
//给画布上画干扰线
//循环控制画多条线
for(int i=1;i<=3;i++)
{
//设置画笔的颜色
g.setColor(new Color(r.nextInt(255),r.nextInt(255),r.nextInt(255)));
//向画布上画干扰线
//drawLine(x1, y1, x2, y2) 这里四个参数是因为两个点画成一条线
g.drawLine(r.nextInt(width), r.nextInt(height), r.nextInt(width), r.nextInt(height));
}
//定义数据准备向画布中写数据
String data="abcdefghigklmnpqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ123456789";
//创建字符串缓冲区
StringBuilder sb = new StringBuilder();
//循环控制画四个字符
for (int i = 1; i <=4; i++) {
//设置画笔的颜色 Color.BLUE这里的颜色固定了,只能是蓝色,我们可以让颜色随机变化
// g.setColor(Color.BLUE);
g.setColor(new Color(r.nextInt(255),r.nextInt(255),r.nextInt(255)));
//设置字体 Font.ITALIC表示斜体
g.setFont(new Font("宋体", Font.ITALIC, 20));
//给画布上写内容 20表示从x轴的位置开始书写 25表示y轴位置开始书写
// g.drawString("哈哈哈哈", 20, 25);
/*
* data.charAt()表示根据函数的参数进行查找字符
* data.length()表示字符串的长度
* r.nextInt()表示生成随机数,但是随机数的范围在0~data字符串的长度
*/
String str = data.charAt(r.nextInt(data.length())) + "";
g.drawString(str, 20*i, 25);
//将验证码内容拼接到字符串缓冲区中
sb.append(str);
}
// 验证码保存到session中
request.getSession().setAttribute("serverCheckCode",sb.toString());
//将生成的验证码图片响应给浏览器
ImageIO.write(bi,"JPG",response.getOutputStream());
}
}
LoginServlet实现类
@WebServlet("/loginUserServlet")
public class LoginUserServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 工具封装数据到实体类
Admin admin = CommonUtils.commonPopulate(Admin.class, request);
UserService userService = new UserService();
boolean b = userService.queryAdminBy(admin);
if(b){
String check = request.getParameter("checkbox");
if("on".equals(check)){
Cookie cookieName = new Cookie("name", admin.getName());
Cookie cookiePassword = new Cookie("password", admin.getPassword());
// 添加cookie
response.addCookie(cookieName);
response.addCookie(cookiePassword);
// 设置最大有效时间
cookieName.setMaxAge(60*60);
cookiePassword.setMaxAge(60*60);
}
request.getSession().setAttribute("admin", admin);
request.getRequestDispatcher("/queryUserInfoServlet").forward(request, response);
}else {
request.setAttribute("msgErr", "用户名或密码错误!");
request.getRequestDispatcher("/login.jsp").forward(request, response);
}
}
}
QueryUserInfoServlet实现类
@WebServlet("/queryUserInfoServlet")
public class QueryUserInfoServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取service层 的User业务逻辑对象
UserService userService = new UserService();
// 调用查询方法 -》得到用户数据信息
List<User> userList = userService.queryUserInfo();
// 设置request域对象参数 -》 把数据集合存到 request中
request.setAttribute("userList", userList);
// 转发 到 list01.jsp 显示 用户数据
request.getRequestDispatcher("/userList.jsp").forward(request, response);
}
}
QueryUserByIdServlet实现类
@WebServlet("/queryUserByIdServlet")
public class QueryUserByIdServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取 id 参数
String id = request.getParameter("id");
// 创建业务层对象 并调用业务方法
UserService userService = new UserService();
User user = userService.queryUserById(Integer.parseInt(id));
// 处理结果 设置 request域对象
request.setAttribute("user", user);
// 转发到update.jsp
request.getRequestDispatcher("/update.jsp")
.forward(request, response);
}
}
AddUserServlet实现类
@WebServlet("/addUserServlet")
public class AddUserServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/* // 获取页面中所有数据
Map<String, String[]> map = request.getParameterMap();
// 创建User对象
User user = new User();
// 使用BeanUtils 将用户信息封装到User对象中
try {
BeanUtils.populate(user, map);
} catch (Exception e) {
e.printStackTrace();
}*/
// 使用工具类 封装数据到User实体类中
User user = CommonUtils.commonPopulate(User.class, request);
// 创建业务层对象, 调用其中添加用户方法 addUser()
UserService userService = new UserService();
// 根据业务层执行方法返回的结果判断是否添加成功
boolean b = userService.addUser(user);
// 成功 跳转到 index.html【】
if (b) {
request.getRequestDispatcher("/index.html")
.forward(request, response);
} else {
// 失败 设置失败信息 转发 addUser.jsp
request.setAttribute("msg", "添加失败,您的邮箱重复");
request.getRequestDispatcher("/addUser.jsp").forward(request, response);
}
}
}
UpdateUserServlet类
@WebServlet("/updateUserServlet")
public class UpdateUserServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 将request对象中 修改的用户信息 封装到 User类
User user = CommonUtils.commonPopulate(User.class, request);
// 根据id 更新用户
UserService userService = new UserService();
boolean b = userService.updateUserById(user);
if (b) {
request.setAttribute("updateSuccessful", "修改成功!");
} else {
request.setAttribute("updateError", "修改失败!");
}
request.getRequestDispatcher("/queryUserInfoServlet")
.forward(request, response);
}
}
DeleteUserServlet类
@WebServlet("/deleteUserServlet")
public class DeleteUserServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 接收请求对象 获取 参数id
String id = request.getParameter("id");
// 调用 service的 deleteUser方法
UserService userService = new UserService();
boolean b = userService.deleteUser(Integer.parseInt(id));
// 判断处理结果
if(b){
request.setAttribute("deleteSuccessful", "删除成功!");
}else {
request.setAttribute("deleteError", "删除失败!");
}
// request.getRequestDispatcher("/deleteOk.jsp").forward(request, response);
request.getRequestDispatcher("/queryUserInfoServlet").forward(request, response);
}
}
PageBeanServlet类
@WebServlet("/pageBeanServlet")
public class PageBeanServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 从浏览器 获取当前页数
int curPage = Integer.parseInt(request.getParameter("curPage"));
// 2. 每页显示3条数据
PageBean pageBean = new PageBean();
pageBean.setPageSize(4);
pageBean.setCurPage(curPage);
// 3. 将数据作为参数 传递给 业务层 getPageBean()方法
UserService userService = new UserService();
PageBean pb = userService.getPageBean(pageBean);
// 4. 将分页对象 存储到 request域对象中
request.setAttribute("pb", pb);
// 5. 转发到 page.jsp
request.getRequestDispatcher("/page.jsp")
.forward(request, response);
}
}