Day59 学生管理系统 web1.0
1.项目需求
有两个角色,老师和学生,相同的功能提取到父类用户角色
2.数据库搭建
设计学生表
设计老师表
插入数据 (超级管理员)
设计学科表
3.项目搭建
处理基础页面,分包,实体类,导入数据库
项目结构,导入数据库相关内容
数据库工具类
package com.qf.utils;public class DBUtils {private static DruidDataSource pool;private static ThreadLocal<Connection> local;static{Properties properties = new Properties();try {properties.load(DBUtils.class.getClassLoader().getResourceAsStream("DBConfig.properties"));} catch (IOException e) {throw new RuntimeException(e);}String driverClassName = properties.getProperty("driverClassName");String url = properties.getProperty("url");String username = properties.getProperty("username");String password = properties.getProperty("password");int maxActive = Integer.parseInt(properties.getProperty("maxActive"));//初始化数据库连接池pool = new DruidDataSource();//设置参数pool.setDriverClassName(driverClassName);pool.setUrl(url);pool.setUsername(username);pool.setPassword(password);pool.setMaxActive(maxActive);local = new ThreadLocal<>();}/*** 获取连接对象*/public static Connection getConnection() throws SQLException {Connection connection = local.get();//获取当前线程的Connection对象if(connection == null){connection = pool.getConnection();//获取数据库连接池里的连接对象local.set(connection);//将Connection对象添加到local中}return connection;}/*** 关闭资源*/public static void close(Connection connection, Statement statement, ResultSet resultSet){if(resultSet != null){try {resultSet.close();} catch (SQLException e) {throw new RuntimeException(e);}}if(statement != null){try {statement.close();} catch (SQLException e) {throw new RuntimeException(e);}}if(connection != null){try {if(connection.getAutoCommit()){connection.close();local.set(null);}} catch (SQLException e) {throw new RuntimeException(e);}}}/*** 开启事务*/public static void startTransaction() throws SQLException {Connection connection = getConnection();connection.setAutoCommit(false);}/*** 提交事务*/public static void commit() throws SQLException {Connection connection = local.get();if(connection != null){connection.commit();connection.close();local.set(null);}}public static void rollback() throws SQLException {Connection connection = local.get();if(connection != null){connection.rollback();connection.close();local.set(null);}}/*** 更新数据(添加、删除、修改)*/public static int commonUpdate(String sql,Object... params) throws SQLException {Connection connection = null;PreparedStatement statement = null;try {connection = getConnection();statement = connection.prepareStatement(sql);paramHandler(statement,params);int num = statement.executeUpdate();return num;}finally {close(connection,statement,null);}}/*** 添加数据 - 主键回填(主键是int类型可以返回)*/public static int commonInsert(String sql,Object... params) throws SQLException {Connection connection = null;PreparedStatement statement = null;ResultSet resultSet = null;try {connection = getConnection();statement = connection.prepareStatement(sql,PreparedStatement.RETURN_GENERATED_KEYS);paramHandler(statement,params);statement.executeUpdate();resultSet = statement.getGeneratedKeys();int primaryKey = 0;if(resultSet.next()){primaryKey = resultSet.getInt(1);}return primaryKey;}finally {close(connection,statement,resultSet);}}/*** 查询多个数据*/public static <T> List<T> commonQueryList(Class<T> clazz,String sql, Object... params) throws SQLException{Connection connection = null;PreparedStatement statement = null;ResultSet resultSet = null;try {connection = getConnection();statement = connection.prepareStatement(sql);paramHandler(statement,params);resultSet = statement.executeQuery();//获取表数据对象ResultSetMetaData metaData = resultSet.getMetaData();//获取字段个数int count = metaData.getColumnCount();List<T> list = new ArrayList<>();while(resultSet.next()){T t = null;try {t = clazz.newInstance();} catch (InstantiationException e) {throw new RuntimeException(e);} catch (IllegalAccessException e) {throw new RuntimeException(e);}//获取字段名及数据for (int i = 1; i <= count; i++) {String fieldName = metaData.getColumnName(i);Object fieldVal = resultSet.getObject(fieldName);setField(t,fieldName,fieldVal);}list.add(t);}return list;} finally {DBUtils.close(connection,statement,resultSet);}}/*** 查询单个数据*/public static <T> T commonQueryObj(Class<T> clazz,String sql, Object... params) throws SQLException{Connection connection = null;PreparedStatement statement = null;ResultSet resultSet = null;try {connection = getConnection();statement = connection.prepareStatement(sql);paramHandler(statement,params);resultSet = statement.executeQuery();//获取表数据对象ResultSetMetaData metaData = resultSet.getMetaData();//获取字段个数int count = metaData.getColumnCount();if(resultSet.next()){T t = null;try {t = clazz.newInstance();} catch (InstantiationException e) {throw new RuntimeException(e);} catch (IllegalAccessException e) {throw new RuntimeException(e);}//获取字段名及数据for (int i = 1; i <= count; i++) {String fieldName = metaData.getColumnName(i);Object fieldVal = resultSet.getObject(fieldName);setField(t,fieldName,fieldVal);}return t;}} finally {DBUtils.close(connection,statement,resultSet);}return null;}/*** 获取当前表的总条数*/public static int getAllCount(String table) throws SQLException {Connection connection = getConnection();String sql = "select count(1) from " + table;PreparedStatement statement = connection.prepareStatement(sql);ResultSet resultSet = statement.executeQuery();if(resultSet.next()){int allCount = resultSet.getInt(1);return allCount;}return 0;}/*** 处理statement对象参数数据的处理器*/private static void paramHandler(PreparedStatement statement,Object... params) throws SQLException {for (int i = 0; i < params.length; i++) {statement.setObject(i+1,params[i]);}}/*** 获取当前类及其父类的属性对象* @param clazz class对象* @param name 属性名* @return 属性对象*/private static Field getField(Class<?> clazz,String name){for(Class<?> c = clazz;c != null;c = c.getSuperclass()){try {Field field = c.getDeclaredField(name);return field;} catch (NoSuchFieldException e) {} catch (SecurityException e) {}}return null;}/*** 设置对象中的属性* @param obj 对象* @param name 属性名* @param value 属性值*/private static void setField(Object obj,String name,Object value){Field field = getField(obj.getClass(), name);if(field != null){field.setAccessible(true);try {field.set(obj, value);} catch (IllegalArgumentException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}}}
}
创建首页 Welcome.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>首页</title>
</head>
<body><h1>欢迎来到学生管理系统页面</h1><hr><span>请选择你的操作:</span><br/><a href="login.jsp">登录</a><a href="register.jsp">注册</a>
</body>
</html>
web.xml配置首页
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0">//设置首页<welcome-file-list><welcome-file>Welcome.html</welcome-file></welcome-file-list></web-app>
实现类创建
User
package com.qf.pojo;public class User {private String username;private String password;private String name;private String sex;private int age;//无参构造,有参构造,get,set,toString方法省略
Teacher
public class Teacher extends User{private int course;public Teacher() {}//无参构造,有参构造带父类的属性,get,set,toString方法省略
Student
package com.qf.pojo;public class Student extends User{private String hobbies;//无参构造,有参构造带父类的属性,get,set,toString方法省略
Course
package com.qf.pojo;public class Course {private int id;private String name;//无参构造,有参构造,get,set,toString方法省略
4.注册功能
注册流程图
注册逻辑 RegisterServlet
注意:老师不用注册是管理员自动分配账号,而学生需要注册
注册逻辑:
1.设置请求、响应编码格式
2.获取请求中的数据
3.通过username查询数据库中的学生对象
4.通过学生对象进行非空判断
没找到就允许注册,将数据插入到学生表中,利用重定向跳转到登录页面
在数据库中就不允许注册,利用重定向跳转到注册页面
注意:
request.getParameter表示获取前端的参数,参数为页面提交的数据(二进制流不使用这个)
request.getAttribute获取请求对象(请求域)中的数据
package com.qf.Servlet;@WebServlet("/RegisterServlet")
public class RegisterServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//设置请求、响应编码格式request.setCharacterEncoding("UTF-8");response.setContentType("text/html;charset=UTF-8");//获取请求中的数据String username = request.getParameter("username");String password = request.getParameter("password");String name = request.getParameter("name");String sex = request.getParameter("sex");String age = request.getParameter("age");String[] hobbies = request.getParameterValues("hobbies");//通过username查询数据库中的学生对象Student student = null;try {student = DBUtils.commonQueryObj(Student.class, "select * from student where username=?", username);} catch (SQLException e) {throw new RuntimeException(e);}if(student == null){//在数据库中没有找到,说明没有这个学生,就允许注册//将数据插入到学生表中try {DBUtils.commonUpdate("insert into student(username,password,name,sex,age,hobbies) values(?,?,?,?,?,?)",username,password,name,sex,age, StringUtils.handleArray(hobbies));} catch (SQLException e) {throw new RuntimeException(e);}//利用重定向跳转到登录页面response.sendRedirect("login.jsp");}else{//不允许注册//展示信息,将数据直接设置在request中//将数据存储到请求域中,生命周期非常短,一来一回就死亡了//请求发送后,响应后就死亡了request.setAttribute("msg","注册失败 -- 账号已存在");//利用转发跳转到注册页面request.getRequestDispatcher("register.jsp").forward(request,response);}}
}
理解以下代码
请求域对象都是使用request
//展示提示信息,将数据存储到请求对象(请求域)中,生命周期非常短,一来一回就死亡了,请求发送后,响应后就死亡了
//只是在web容器内部流转,仅仅是请求处理阶段
request.setAttribute("msg","注册失败 -- 账号已存在");//利用转发跳转到注册页面
request.getRequestDispatcher("register.jsp").forward(request,response); //register.jsp前端获取
<%String msg = (String) request.getAttribute("msg");
%>
注册页面 register.jsp
JSP的脚本:JSP定义Java代码的方式
可以简单理解为几个标签,带有<% % >
<% java代码 %>:写的是java的逻辑代码
<%= java‘代码 %>:写的java代码,会输出展示到页面上。输出语句中可以定义什么,jsp页面就会显示什么内容
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body><!-- 在jsp中写java代码用<% %> 包裹,拿到请求对象(请求域)中的提示信息:注册失败 -- 账号已存在 -->
<%String msg = (String) request.getAttribute("msg");
%>
<!-- 在页面中展示提示信息 三目运算符 第一次进入为空不展示-->
<%= (msg != null)? msg:"" %> <h1>注册页面</h1>
<form action="RegisterServlet" method="post">账号:<input type="text" name="username"/><br/>密码:<input type="password" name="password"/><br/>姓名:<input type="text" name="name"/><br/>年龄:<input type="text" name="age"/><br/>性别:<input type="radio" name="sex" value="man" checked="checked"/>男<input type="radio" name="sex" value="woman"/>女<br/>爱好:<input type="checkbox" name="hobbies" value="football"/>足球<input type="checkbox" name="hobbies" value="basketball"/>篮球<input type="checkbox" name="hobbies" value="shop"/>购物<br/><input type="submit" value="注册"/><input type="button" value="返回" οnclick="goWelcome()"></form><script type="text/javascript">function goWelcome(){window.location = "http://localhost:8080/StudentManagementSystem_Web_exploded/";}
</script>
</body>
</html>
优化注册页面 register.jsp
<!-- 在jsp中写java代码用<% %> 包裹 -->
<%String msg = (String) request.getAttribute("msg");
%>
<!-- 在页面中展示数据 三目运算符 第一次进入为空不展示-->
<%= (msg != null)? msg : "" %>//上面的不要,直接用这一行代码展示msg(页面会自动拿到数据)
${msg}
因为hobbies是一个字符串数组,所以写一个工具类,让其拼接字符串
StringUtils
利用反射操作数组
package com.qf.utils;import java.lang.reflect.Array;public class StringUtils {public static String handleArray(Object[] os){StringBuffer sb = new StringBuffer();for (int i=0;i< Array.getLength(os);i++){//利用反射操作数组Arrayif (i!=0){sb.append(",");}//获取当前下标上的元素Object element = Array.get(os, i);sb.append(element);}// for (Object element : os) {
// if(sb.length() !=0){
// sb.append(",");
// }
// sb.append(element);
// }return sb.toString();}
}
运行结果:
点击注册,输入数据,注册成功(账号没有在数据库里就会注册成功)跳转到登录页面,失败会跳转到注册页面,页面上会显示提示信息 注册失败 – 账号已存在
查看数据库
5.登录页面
LoginServlet
1.设置请求、响应编码格式
2.获取请求中的数据
3.验证码是否输入正确
不正确登录失败 - 验证码错误
4.正确,通过username、password查询数据库中的用户对象
5.通过用户对象判断(是否在数据库中)
登录成功,利用重定向跳转到详情页面(凭证添加到Cookie,数据存储到Session)登录失败 – 账号或密码错误,利用重定向跳转到登录页面
package com.qf.Servlet;@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//设置请求、响应编码格式request.setCharacterEncoding("UTF-8");response.setContentType("text/html;charset=UTF-8");//获取请求中的数据String username = request.getParameter("username");String password = request.getParameter("password");String userCode = request.getParameter("userCode");String rememberMe = request.getParameter("rememberMe");String role = request.getParameter("role");String sysCode = (String) request.getSession().getAttribute("sysCode");if (sysCode.equalsIgnoreCase(userCode)){ //验证码是否输入正确User user=null;try {if ("student".equals(role)){user=DBUtils.commonQueryObj(Student.class,"select * from student where username=? and password=?",username,password);} else if ("teacher".equals(role)) {user=DBUtils.commonQueryObj(Teacher.class,"select * from teacher where username=? and password=?", username, password);}} catch (SQLException e) {throw new RuntimeException(e);}if (user!=null){//登录成功//判断是否记住我if(rememberMe != null){//将凭证添加到Cookie中//cookie保存在浏览器中response.addCookie(CookieUtils.createCookie("username",user.getUsername(),60*60*24*5));response.addCookie(CookieUtils.createCookie("name",user.getName(),60*60*24*5));response.addCookie(CookieUtils.createCookie("role",role,60*60*24*5));}//将数据存储到Session中(后续需要使用的)//浏览器向服务器发送一个请求,服务器会生成一个session对象,保存在服务器中HttpSession session = request.getSession();session.setAttribute("username",user.getUsername());session.setAttribute("name",user.getName());session.setAttribute("role",role);response.sendRedirect("index.jsp");}else{//登录失败 -- 账号或密码错误request.setAttribute("msg","登录失败--账号或密码错误");request.getRequestDispatcher("login.jsp").forward(request,response);}}else{//登录失败 - 验证码错误//将数据发送到请求对象(请求域)中,时间在一瞬间,交互很短//我们使用request.setAttribute()方法设置了一个名为 “msg” 的属性,并将其值设置为 “登录失败--验证码错误”。// 然后,我们可以通过请求转发(forward)将这个属性传递给其他组件,如另一个Servlet或JSP页面request.setAttribute("msg","登录失败--验证码错误");request.getRequestDispatcher("login.jsp").forward(request,response);}}
}
login.jsp
关注验证码的写法,还有就是刷新验证码和点击验证码自动刷新
注意设置刷新验证码的函数
<%@ page import="java.net.URLDecoder" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body><!-- 记住我的代码 -->
<%Cookie[] cookies = request.getCookies();if(cookies != null){int count = 0;for (Cookie cookie : cookies) {String name = cookie.getName();String value = URLDecoder.decode(cookie.getValue(),"UTF-8");if("username".equals(name)){session.setAttribute("username",value);count++;}if("name".equals(name)){session.setAttribute("name",value);count++;}if("role".equals(name)){session.setAttribute("role",value);count++;}}if(count == 3){response.sendRedirect("index.jsp");}}
%><!-- 判断登录结果,成功还是失败,提示信息显示在页面上方 -->
<%String msg = (String) request.getAttribute("msg");
%>
<%= (msg!=null)?msg:""%><h1>登录页面</h1>
<!--点击登录页面,会方式两次请求,一次是LoginServlet,第二次是CodeServlet-->
<form action="LoginServlet" method="post">账号:<input type="text" name="username"/><br/>密码:<input type="password" name="password"/><br/>验证码:<input type="text" name="userCode"/><img src="CodeServlet" width="120px" height="30px" οnclick="refresh()"><a href="#" οnclick="refresh()">刷新</a><br/>记住我:<input type="checkbox" name="rememberMe"/><br/>角色:<select name="role"><option value="student">学生</option><option value="teacher">老师</option></select><br/><input type="submit" value="登录"/><input type="button" value="返回" οnclick="goWelcome()"/>
</form><script type="text/javascript">function goWelcome(){window.location = "welcome.html";}//刷新验证码img = document.getElementsByTagName("img")[0];function refresh(){img.src = "CodeServlet?" + new Date();}</script></body>
</html>
优化login.jsp
<%@ page import="java.net.URLDecoder" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body><!-- 记住我的java代码直接写出去 rememberMe.jsp,然后导包 -->
<%@include file="rememberMe.jsp"%><!-- 判断登录结果,成功还是失败,显示在页面上方 -->
<%--<%--%>
<%-- String msg = (String) request.getAttribute("msg");--%>
<%--%>--%>
<%--<%= (msg!=null)?msg:""%>--%>${msg}<h1>登录页面</h1>
<!--点击登录页面,会方式两次请求,一次是LoginServlet,第二次是CodeServlet-->
<form action="LoginServlet" method="post">账号:<input type="text" name="username"/><br/>密码:<input type="password" name="password"/><br/>...省略</body>
</html>
java代码直接写出去 rememberMe.jsp,然后导包
rememberMe.jsp
<%@ page import="java.net.URLDecoder" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%Cookie[] cookies = request.getCookies();if(cookies != null){int count = 0;for (Cookie cookie : cookies) {String name = cookie.getName();String value = URLDecoder.decode(cookie.getValue(),"UTF-8");if("username".equals(name)){session.setAttribute("username",value);count++;}if("name".equals(name)){session.setAttribute("name",value);count++;}if("role".equals(name)){session.setAttribute("role",value);count++;}}if(count == 3){response.sendRedirect("index.jsp");}}
%>
5.1 绘制验证码
CodeServlet
1.创建画布(前提定义宽高)
2.通过画布获取画笔
3.设置背景色 – 填充矩形【利用画笔】
4.设置验证码
创建验证码数字数组、颜色数组
利用随机数进行获取随机下标从而获取随机数字和颜色
设置随机颜色
设置字体(字体,样式,大小)
设置单个验证码
StringBffer拼接成验证码
设置干扰线
6.ImageIO将画布以jpg形式的文件传出给客户端
package com.qf.Servlet;@WebServlet("/CodeServlet")
public class CodeServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//验证码是图片,不需要编码格式//设置宽高的变量int width = 120;int height = 30;//创建画布BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);//获取画笔Graphics graphics = image.getGraphics();//设置背景色 -- 填充矩形graphics.setColor(Color.BLUE);//选择颜色graphics.fillRect(0,0,width,height);//填充整个图片区域//设置验证码Random random = new Random();String[] codes = {"A","B","C","D","E","F","G","H","J","K","M","N","P","Q","R","S","T","U","V","W","X","Y","Z","0","1","2","3","4","5","6","7","8","9"};Color[] colors = {Color.CYAN,Color.BLACK,Color.GREEN,Color.PINK,Color.WHITE,Color.RED,Color.ORANGE};StringBuffer sb = new StringBuffer();for (int i = 0; i < 4; i++) {String randomCode = codes[random.nextInt(codes.length)];//随机内容Color randomColor = colors[random.nextInt(colors.length)];//随机颜色graphics.setColor(randomColor);//设置随机颜色graphics.setFont(new Font("宋体",Font.BOLD,20+random.nextInt(10)));//设置字体(字体,样式,大小)graphics.drawString(randomCode,20+i*25,15+random.nextInt(10));//设置单个验证码sb.append(randomCode);}//将系统验证码设置到Session对象中(会话对象),存储在服务器中//浏览器向服务器发送一个请求,服务器会生成一个session对象HttpSession session = request.getSession();//获取请求里的JSESSIONID(客户端Cookie里的数据),如果没有就创建Session对象,如果有就从Session容器中获取会话对象session.setAttribute("sysCode",sb.toString());//键值对,键是String类型,值是Object对象//设置干扰线graphics.setColor(Color.YELLOW);for (int i = 0; i < 3; i++) {graphics.drawLine(random.nextInt(width),random.nextInt(height),random.nextInt(width),random.nextInt(height));//绘制直线(x1,y1,x2,y2) -> 两点为一线}//将画布以jpg形式的文件传出给客户端,ImageIO工具ImageIO.write(image,"jpg",response.getOutputStream());}
}
5.2 分析验证码功能制作
注册功能中的request.getAttribute:将数据直接设置在request中,利用request调用,存储时间短
验证码功能中的HttpSession session = request.getSession(); 浏览器向服务器发送一个请求,服务器会生成一个session对象,利用session(request.getSession() )去调用,30分钟
区别:session的过期时间是30分钟,可以调,长时间的属性可以放在session,一瞬间的数据可以放在jsp里请求对象request里
session对象的作用域为一次会话,通常浏览器不关闭,保存的值就不会消失,当然也会出现session超时(tomcat默认为30分钟)
session.getAttribute(“”) 取到的类型是是object,所以赋值前要强转一下 ,转成你需要的类型
Session的基本工作原理:
- 用户访问Web应用程序时,服务器为每个用户创建一个唯一的Session对象。
- 服务器将Session ID 分配给每个Session对象,并将Session ID 存储在用户的浏览器中的Cookie中。Session ID 在服务器端和客户端之间用于标识Session。
- 当用户发送请求时,服务器使用Session ID 来查找相应的Session对象。
- 服务器可以将数据存储在Session对象中,以便在用户的不同请求之间共享。
- 当用户关闭浏览器或Session超时时,Session对象被销毁。
session的相关使用
1.获取Session对象,使用的是request对象
HttpSession session = request.getSession();
2.存储数据到 session 域中
session.setAttribute(String name, Object o)
3.根据 key,获取值
session.getAttribute(String name)
验证码功能就是把把验证码存在session对象中,设置键值对属性
输入一个验证码,会寻找对应的session ID,获取对应的值,这个有30分钟,不同的验证码请求有不同的ID
//将系统验证码设置到Session对象中(会话对象)//浏览器向服务器发送一个请求,服务器会生成一个session对象HttpSession session = request.getSession();//获取请求里的JSESSIONID(客户端Cookie里的数据),如果没有获取到就创建Session对象,如果有就从Session容器中获取会话对象session.setAttribute("sysCode",sb.toString());//键值对,键是String类型,值是Object对象
从Session对象中取出来判断
request.getSession() -->获取到这个session对象,再获取里面的value
//从Session对象中获取系统的验证码String sysCode = (String) request.getSession().getAttribute("sysCode");if(sysCode.equalsIgnoreCase(userCode)){......}
结论
1.Cookie是用来保证用户在未登录情况下的身份识别
2.Session是用来保存用户登录后的数据
3.Session是存储在服务端,而Cookie是存储在客户端
4.购物车、记住我功能:使用Cookie来存储
5.以登录用户的名称展示、验证码:使用Session来存储
运行结果:
输入一个在数据库有的数据
5.3 记住我(存Session、存Cookie)
流程图
实现:存Session、存Cookie
LoginServlet
添加存凭证
1.当第一次登录时,点击了“记住我”,就会存凭证【username、name、role合起来是一个凭证】存在Cookie中
2.再次登录就会判断,是否有凭证
有,直接跳详情页面,不过在跳转前会将凭证存在session中【因为详情页展示需要session的数据】
没有,就不管,就用户直接输入登录
package com.qf.Servlet;@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {String sysCode = (String) request.getSession().getAttribute("sysCode");if (sysCode.equalsIgnoreCase(userCode)){ //验证码是否输入正确User user=null;try {if ("student".equals(role)){user=DBUtils.commonQueryObj(Student.class,"select * from student where username=? and password=?",username,password);} else if ("teacher".equals(role)) {user=DBUtils.commonQueryObj(Teacher.class,"select * from teacher where username=? and password=?", username, password);}} catch (SQLException e) {throw new RuntimeException(e);}if (user!=null){//登录成功//判断是否记住我if(rememberMe != null){//将凭证添加到Cookie中//cookie保存在客户端中(键值对都是String类型)response.addCookie(CookieUtils.createCookie("username",user.getUsername(),60*60*24*5));response.addCookie(CookieUtils.createCookie("name",user.getName(),60*60*24*5));response.addCookie(CookieUtils.createCookie("role",role,60*60*24*5));}//将凭证数据存储到Session中//浏览器向服务器发送一个请求,服务器会生成一个session对象,保存在服务器中HttpSession session = request.getSession();session.setAttribute("username",user.getUsername());session.setAttribute("name",user.getName());session.setAttribute("role",role);response.sendRedirect("index.jsp");}else{//登录失败 -- 账号或密码错误request.setAttribute("msg","登录失败--账号或密码错误");request.getRequestDispatcher("login.jsp").forward(request,response);}
添加cookie工具类
CookieUtils
package com.qf.utils;public class CookieUtils {public static Cookie createCookie(String name,String value,int time) {Cookie cookie=null;try {//数据中有中文,必须设置编码格式cookie= new Cookie(name, URLEncoder.encode(value, "UTF-8"));} catch (UnsupportedEncodingException e) {throw new RuntimeException(e);}cookie.setMaxAge(time);return cookie;}
}
login.jsp
<%@ page import="java.net.URLDecoder" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body><!-- 记住我的代码 -->
<%Cookie[] cookies = request.getCookies();if(cookies != null){int count = 0;for (Cookie cookie : cookies) {String name = cookie.getName();//取数据时需要解码String value = URLDecoder.decode(cookie.getValue(),"UTF-8");if("username".equals(name)){//存储value值session.setAttribute("username",value);count++;}if("name".equals(name)){session.setAttribute("name",value);count++;}if("role".equals(name)){session.setAttribute("role",value);count++;}}if(count == 3){response.sendRedirect("index.jsp");}}
%><!-- 判断登录结果,成功还是失败,显示在页面上方 -->
<%String msg = (String) request.getAttribute("msg");
%>
<%= (msg!=null)?msg:""%><h1>登录页面</h1>.......
Cookie:
1.创建Cookie对象,并设置值:
Cookie cookie = new Cookie("key","value");
2.发送Cookie到客户端使用的是Reponse对象:
response.addCookie(cookie);
3.获取Cookie:使用Request对象获取Cookie数组:
Cookie[] cookies = request.getCookies();
6.详情页
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body>
<%//取出登录页面存储的session对象String username = (String) session.getAttribute("username");String name = (String) session.getAttribute("name");String role = (String) session.getAttribute("role");
%><button onclick="safeExit()">安全退出</button>
<h1>详情页面</h1>
<h1>欢迎<%=name%><%=("student".equals(role))?"学员":""%><%=("teacher".equals(role))?"老师":""%>进入到学生管理系统</h1><a href="resetPassword.jsp">修改密码</a><%if("student".equals(role)){%>
<!-- 在这个servlet通过username找到这个学生,再跳转到信息修改页面 -->
<a href="StuInitModifyServlet?username=<%=username%>">修改信息</a>
<%}%><%if("teacher".equals(role)){%>
<a href="TeaInitModifyServlet?username=<%=username%>">修改信息</a>
<a href="#">查看所有学生</a>
<%}%><script type="text/javascript">function safeExit(){window.location = "SafeExitServlet";}
</script>
</body>
</html>
优化:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%><html>
<head><title>Title</title>
</head>
<body>
<%--<%--%>
<%-- String username = (String) session.getAttribute("username");--%>
<%-- String name = (String) session.getAttribute("name");--%>
<%-- String role = (String) session.getAttribute("role");--%>
<%--%>--%><button onclick="safeExit()">安全退出</button>
<h1>详情页面</h1>
<%--<%=("student".equals(role))?"学员":""%>--%>
<%--${(role eq "student")?"学员":""}--%><h1>欢迎${name}${(role eq "student")?"学员":""}${(role eq "teacher")?"学员":""}进入到学生管理系统</h1><a href="resetPassword.jsp">修改密码</a><c:if test="${role eq 'student'}"><a href="StuInitModifyServlet?username=${username}">修改信息</a>
</c:if><%--<%if("student".equals(role)){%>--%>
<%--<!-- 在这个servlet通过username找到这个学生,再跳转到信息修改页面 -->--%>
<%--<a href="StuInitModifyServlet?username=<%=username%>">修改信息</a>--%>
<%--<%}%>--%><%--<%if("teacher".equals(role)){%>--%>
<%--<a href="TeaInitModifyServlet?username=<%=username%>">修改信息</a>--%>
<%--<a href="GetStuListServlet?curPage=1">查看所有学生</a>--%>
<%--<%}%>--%><c:if test="${role eq 'teacher'}"><a href="TeaInitModifyServlet?username=${usename}">修改信息</a><a href="GetStuListServlet?curPage=1">查看所有学生</a>
</c:if><script type="text/javascript">function safeExit(){window.location = "SafeExitServlet";}
</script>
</body>
</html>
8.安全退出(删Session、删Cookie)
删除账号所有信息 cookie,session
<button οnclick="safeExit()">安全退出</button>
<h1>详情页面</h1>
<h1>欢迎<%=name%><%=("student".equals(role))?"学员":""%><%=("teacher".equals(role))?"老师":""%>进入到学生管理系统</h1><script type="text/javascript">function safeExit(){window.location = "SafeExitServlet";}
</script>
SafeExitServlet
package com.qf.Servlet;
import com.qf.utils.CookieUtils;@WebServlet("/SafeExitServlet")
public class SafeExitServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//删除Cookie里的数据//把时间设置为0,就是删除response.addCookie(CookieUtils.createCookie("username","",0));response.addCookie(CookieUtils.createCookie("name","",0));response.addCookie(CookieUtils.createCookie("role","",0));//删除Session里的数据HttpSession session = request.getSession();session.removeAttribute("username");session.removeAttribute("name");session.removeAttribute("role");//跳转response.sendRedirect("Welcome.html");}
}
9.修改密码
index.jsp
<button onclick="safeExit()">安全退出</button>
<h1>详情页面</h1>
<h1>欢迎<%=name%><%=("student".equals(role))?"学员":""%><%=("teacher".equals(role))?"老师":""%>进入到学生管理系统</h1><a href="resetPassword.jsp">修改密码</a>// ...省略
resetPassword.jsp
需要展示页面就要先获取session中的username
要用户输入原密码和新密码【对于为什么要原密码,就是在用户电脑在登录情况下被别人直接改密码】
注意1:对于ResetPasswordServlet查询用户对象,是需要username和role,怎么获取?
方案:在这个表单直接请求传过去(使用隐藏域),ResetPasswordServlet就可以在请求中取
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body><%//从前端页面中取出来数据(当前页面没用,但是后面的ResetPasswordServlet有用)String username = (String) session.getAttribute("username");String role = (String) session.getAttribute("role");//提示信息String msg = (String) request.getAttribute("msg");
%><%=(msg!=null)?msg:""%><form action="ResetPasswordServlet" method="post">//传入给后端ResetPasswordServlet<!--隐藏域,不会在页面中展示,但是发送请求后会携带到后端--><input type="hidden" name="username" value="<%=username%>"/><input type="hidden" name="role" value="<%=role%>"/>账号:<%=username%><br/>原密码:<input type="password" name="password"/><br/>新密码:<input type="password" name="newPassword"/><br/><input type="submit" value="修改"/><input type="button" value="返回" οnclick="goIndex()"/>
</form><script type="text/javascript">function goIndex(){window.location = "index.jsp";}
</script>
</body>
</html>
ResetPasswordServlet
1.设置请求、响应编码格式
2.获取请求中的数据
3.通过username、password查询数据库中的用户对象
4.通过用户对象进行非空判断
用户存在,判断角色修改密码,注意要做安全退出【不然在有记住我的情况下,第二次登录直接进来】 用户不存在,设置提示修改密码失败信息,又转发方式跳转回到修改密码页面
package com.qf.Servlet;@WebServlet("/ResetPasswordServlet")
public class ResetPasswordServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//设置请求、响应编码格式request.setCharacterEncoding("UTF-8");response.setContentType("text/html;charset=UTF-8");//获取请求中的数据String username = request.getParameter("username");String password = request.getParameter("password");String newPassword = request.getParameter("newPassword");String role = request.getParameter("role");User user=null;try {//判断角色if ("student".equals(role)) {user= DBUtils.commonQueryObj(Student.class,"select * from student where username=? and password=?", username, password);} else if ("teacher".equals(role)) {user= DBUtils.commonQueryObj(Teacher.class,"select * from teacher where username=? and password=?", username, password);}if (user!=null){//修改if ("student".equals(role)){DBUtils.commonUpdate("update student set password=? where username=?",newPassword,username);} else if ("teacher".equals(role)) {DBUtils.commonUpdate("update teacher set password=? where username=?",newPassword,username);}//修改密码成功后,做安全退出的功能//修改密码了,相当于退出了request.getRequestDispatcher("SafeExitServlet").forward(request,response);}else {//修改密码失败--原密码不正确request.setAttribute("msg","修改密码失败--原密码不正确");request.getRequestDispatcher("resetPassword.jsp").forward(request,response);}} catch (SQLException e) {throw new RuntimeException(e);}}
}
10.修改学生信息(StuInitModifyServlet、StuModifyServlet)
index.jsp
不能直接跳转到修改信息页面,因为拿不到session数据,需要中间页面StuInitModifyServlet(页面跳页面获取学生信息)
在路径中传username, 使StuInitModifyServlet可以拿到账号到数据库查询到改账号的学生信息
<h1>详情页面</h1><%if("student".equals(role)){%>
<!-- 在这个servlet通过username找到这个学生,再跳转到信息修改页面 -->
<a href="StuInitModifyServlet?username=<%=username%>">修改信息</a>
<%}%>
StuInitModifyServlet
操作:初始化修改学生数据
- 设置请求、响应编码格式
- 获取请求中的数据
- 从数据库中获取学生对象
- 将学生对象存在请求中,转发方式到学生修改信息页面stuInfo.jsp
package com.qf.Servlet;@WebServlet("/StuInitModifyServlet")
public class StuInitModifyServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//设置请求、响应编码格式request.setCharacterEncoding("UTF-8");response.setContentType("text/html;charset=UTF-8");//获取请求中的数据String username = request.getParameter("username");//从数据库中获取学生对象Student student = null;try {student = DBUtils.commonQueryObj(Student.class, "select * from student where username=?", username);} catch (SQLException e) {throw new RuntimeException(e);}request.setAttribute("student",student);request.getRequestDispatcher("stuInfo.jsp").forward(request,response);}
}
stuInfo.jsp
对于没有学生信息,需要先到StuInitModifyServlet获取到学生对象,再获取其中信息,上传到stuInfo.jsp,用来修改页面展示和表单发送StuModifyServlet中的修改
注意:对性别和爱好的选择处理
<%@ page import="com.qf.pojo.Student" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body><%Student student = (Student) request.getAttribute("student");
%><h1>学生修改信息页面</h1><form action="StuModifyServlet" method="post"><input type="hidden" name="username" value="<%=student.getUsername()%>"/>账号:<%=student.getUsername()%><br/>姓名:<input type="text" name="name" value="<%=student.getName()%>"/><br/>年龄:<input type="text" name="age" value="<%=student.getAge()%>"/><br/>性别:<input type="radio" name="sex" value="man" <%=(student.getSex().equals("man"))?"checked='checked'":""%>/>男<input type="radio" name="sex" value="woman" <%=(student.getSex().equals("woman"))?"checked='checked'":""%>/>女<br/>爱好:<input type="checkbox" name="hobbies" value="football" <%=(student.getHobbies().contains("football"))?"checked='checked'":""%>/>足球<input type="checkbox" name="hobbies" value="basketball" <%=(student.getHobbies().contains("basketball"))?"checked='checked'":""%>/>篮球<input type="checkbox" name="hobbies" value="shop" <%=(student.getHobbies().contains("shop"))?"checked='checked'":""%>/>购物<br/><input type="submit" value="修改"/><input type="button" value="返回" οnclick="goIndex()"/>
</form><script type="text/javascript">function goIndex(){window.location = "index.jsp";}
</script>
</body>
</html>
优化:
主要是jsp的EL和JSTL表达式的改进
<%@ page import="com.qf.pojo.Student" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
<html>
<head><title>Title</title>
</head>
<body><%--<%--%>
<%-- Student student = (Student) request.getAttribute("student");--%>
<%--%>--%><h1>学生修改信息页面</h1><form action="StuModifyServlet" method="post"><input type="hidden" name="username" value="${student.username}"/>账号:${student.username}<br/>姓名:<input type="text" name="name" value="${student.name}"/><br/>年龄:<input type="text" name="age" value="${student.age}"/><br/>性别:<input type="radio" name="sex" value="man" ${(student.sex eq 'man')?"checked='checked'":""}/>男<input type="radio" name="sex" value="woman" ${(student.sex eq 'woman')?"checked='checked'":""}/>女<br/>爱好:<input type="checkbox" name="hobbies" value="football" <c:if test="${fn:contains(student.hobbies, 'football')}">checked='checked'</c:if>/>足球<input type="checkbox" name="hobbies" value="basketball" <c:if test="${fn:contains(student.hobbies, 'basketball')}">checked='checked'</c:if>/>篮球<input type="checkbox" name="hobbies" value="shop" <c:if test="${fn:contains(student.hobbies, 'shop')}">checked='checked'</c:if>/>购物<br/><input type="submit" value="修改"/><input type="button" value="返回" οnclick="goIndex()"/>
</form><script type="text/javascript">function goIndex(){window.location = "index.jsp";}
</script>
</body>
</html>
StuModifyServlet(修改学生信息的逻辑)
1.设置请求、响应编码格式
2.获取请求中的数据
3.更新数据库里的学生数据
4.更新Session里的数据【原因:可能改名字,如果不改还是原来的名字就会在使用时出错】
5.更新Cookie里的数据【可存可不存,还是存一下,Cookie只有记住我才会有数据,name涉及凭证】
6.重定向方式跳转到详情页面index.jsp
package com.qf.Servlet;@WebServlet("/StuModifyServlet")
public class StuModifyServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//设置请求、响应编码格式request.setCharacterEncoding("UTF-8");response.setContentType("text/html;charset=UTF-8");//获取请求中的数据String username = request.getParameter("username");String name = request.getParameter("name");String sex = request.getParameter("sex");String age = request.getParameter("age");String[] hobbies = request.getParameterValues("hobbies");//更新数据库里的学生数据try {DBUtils.commonUpdate("update student set name=?,sex=?,age=?,hobbies=? where username=?",name,sex,age, StringUtils.handleArray(hobbies),username);} catch (SQLException e) {throw new RuntimeException(e);}String role = (String) request.getSession().getAttribute("role");if("student".equals(role)){//更新Session里的数据request.getSession().setAttribute("name",name);//更新Cookie里的数据response.addCookie(CookieUtils.createCookie("name",name,60*60*24*5));//跳转详情页面response.sendRedirect("index.jsp");}else if("teacher".equals(role)){//跳转response.sendRedirect("GetStuListServlet?curPage=1");}}
}
11.修改老师信息(TeaInitModifyServlet、TeaModifyServlet)
详情页面 index.js
通过username拿到老师数据,交给request对象
<h1>详情页面</h1><%if("student".equals(role)){%>
<!-- 在这个servlet通过username找到这个学生,再跳转到信息修改页面 -->
<a href="StuInitModifyServlet?username=<%=username%>">修改信息</a>
<%}%>//省略
TeaInitModifyServle
操作:初始化修改老师数据
- 设置请求、响应编码格式
- 获取请求中的数据
- 从数据库中获取老师对象
- 将老师对象和课程集合对象存在请求中,转发方式到老师修改信息页面teaInfo.jsp
package com.qf.Servlet;@WebServlet("/TeaInitModifyServlet")
public class TeaInitModifyServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//设置请求、响应编码格式request.setCharacterEncoding("UTF-8");response.setContentType("text/html;charset=UTF-8");//获取请求中的数据String username = request.getParameter("username");//从数据库中获取相应的数据Teacher teacher = null;List<Course> courses = null;try {teacher = DBUtils.commonQueryObj(Teacher.class,"select * from teacher where username=?",username);courses = DBUtils.commonQueryList(Course.class,"select * from course");} catch (SQLException e) {throw new RuntimeException(e);}//存入请求对象中request.setAttribute("teacher",teacher);request.setAttribute("courses",courses);//跳转页面request.getRequestDispatcher("teaInfo.jsp").forward(request,response);}
}
teaInfo.jsp(老师修改信息页面)
需要先到TeaInitModifyServlet获取到老师对象,再获取其中信息,用来修改页面展示和表单发送TeaModifyServlet中的修改
注意:对性别和学科选择的处理
对于学科考虑到会新增的情况,不能写死,通过获取学科集合再遍历的方式进行选择展示
<%@ page import="com.qf.pojo.Teacher" %>
<%@ page import="java.util.List" %>
<%@ page import="com.qf.pojo.Course" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body>
<%Teacher teacher = (Teacher) request.getAttribute("teacher");List<Course> courses = (List<Course>) request.getAttribute("courses");
%><h1>老师修改信息页面</h1><form action="TeaModifyServlet" method="post"><input type="hidden" name="username" value="<%=teacher.getUsername()%>"/>账号:<%=teacher.getUsername()%><br/>姓名:<input type="text" name="name" value="<%=teacher.getName()%>"/><br/>年龄:<input type="text" name="age" value="<%=teacher.getAge()%>"/><br/>性别:<input type="radio" name="sex" value="man" <%=(teacher.getSex().equals("man"))?"checked='checked'":""%>/>男<input type="radio" name="sex" value="woman" <%=(teacher.getSex().equals("woman"))?"checked='checked'":""%>/>女<br/>学科:<select><%for(Course course:courses){%><option value="<%=course.getId()%>" <%=(course.getId() == teacher.getCourseId())?"selected='selected'":""%> ><%=course.getName()%></option>
<%}%></select><br><input type="submit" value="修改"/><input type="button" value="返回" onclick="goIndex()"/>
</form><script type="text/javascript">function goIndex(){window.location = "index.jsp";}
</script>
</body>
</html>
优化:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ page import="com.qf.pojo.Course" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body>
<%--<%--%>
<%-- Teacher teacher = (Teacher) request.getAttribute("teacher");--%>
<%-- List<Course> courses = (List<Course>) request.getAttribute("courses");--%>
<%--%>--%><h1>老师修改信息页面</h1><form action="TeaModifyServlet" method="post"><input type="hidden" name="username" value="${teacher.username}"/>账号:${teacher.username}<br/>姓名:<input type="text" name="name" value="${teacher.name}"/><br/>年龄:<input type="text" name="age" value="${teacher.age}"/><br/>性别:<input type="radio" name="sex" value="man" ${(teacher.sex eq 'man')?"checked='checked'":""}/>男<input type="radio" name="sex" value="woman" ${(teacher.sex eq 'woman')?"checked='checked'":""}/>女<br/>学科:<select name="courseId"><c:forEach items="${courses}" var="course"><option value="${course.id}" <c:if test="${course.id == teacher.courseId}">selected='selected'</c:if> >${course.name}</option></c:forEach></select><br/><input type="submit" value="修改"/><input type="button" value="返回" onclick="goIndex()"/>
</form><script type="text/javascript">function goIndex(){window.location = "index.jsp";}
</script>
</body>
</html>
TeaModifyServlet
设置请求、响应编码格式
获取请求中的数据
更新数据库里的老师数据
更新Session里的数据【原因:可能改名字,如果不改还是原来的名字就会在使用时出错】
更新Cookie里的数据【可存可不存,还是存一下,Cookie只有记住我才会有数据,name涉及凭证】
重定向方式跳转到详情页面index.jsp
package com.qf.Servlet;@WebServlet("/TeaModifyServlet")
public class TeaModifyServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//设置请求、响应编码格式request.setCharacterEncoding("UTF-8");response.setContentType("text/html;charset=UTF-8");//获取请求中的数据String username = request.getParameter("username");String name = request.getParameter("name");String sex = request.getParameter("sex");String age = request.getParameter("age");String courseId = request.getParameter("courseId");//更新数据库里的学生数据try {DBUtils.commonUpdate("update teacher set name=?,sex=?,age=?,courseId=? where username=?",name,sex,age, courseId,username);} catch (SQLException e) {throw new RuntimeException(e);}//更新Session里的数据request.getSession().setAttribute("name",name);//更新Cookie里的数据response.addCookie(CookieUtils.createCookie("name",name,60*60*24*5));response.sendRedirect("index.jsp");}
}
12.老师角色查询所有学生
要用分页技术
index.jsp
不能直接跳stuList.jsp,没数据
TeaInitModifyServlet?username=<%=username%>:拼接一下,传数据
<h1>详情页面</h1><%if("teacher".equals(role)){%>
<a href="TeaInitModifyServlet?username=<%=username%>">修改信息</a>
<a href="GetStuListServlet?curPage=1">查看所有学生</a>
<%}%></script>
</body>
</html>
GetStuListServlet
拿数据和分页
package com.qf.Servlet;@WebServlet("/GetStuListServlet")
public class GetStuListServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {request.setCharacterEncoding("UTF-8");response.setContentType("text/html;charset=UTF-8");//获取当前页数int curPage = Integer.parseInt(request.getParameter("curPage"));//设置当前页的数据条数int count = 15;//计算偏移量int offset = (curPage-1)*count;//计算总页数int totalPage;try {int allCount = DBUtils.getAllCount("student");if(allCount % count == 0){totalPage = allCount/count;}else{totalPage = allCount/count + 1;}} catch (SQLException e) {throw new RuntimeException(e);}//从数据库获取学生的集合List<Student> students = null;try {students = DBUtils.commonQueryList(Student.class, "select * from student limit ?,?", offset, count);} catch (SQLException e) {throw new RuntimeException(e);}//处理学生集合List<StudentDto> studentDtos = DtoUtils.studentDtoListHandler(students);//将数据存入到请求对象中request.setAttribute("curPage",curPage);request.setAttribute("totalPage",totalPage);request.setAttribute("studentDtos",studentDtos);//跳转request.getRequestDispatcher("stuList.jsp").forward(request,response);}
}
stuList.jsp,学生列表页面
添加学生信息处理后获取
<%@ page import="java.util.List" %>
<%@ page import="com.qf.pojo.Student" %>
<%@ page import="com.qf.dto.StudentDto" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body><%List<StudentDto> studentDtos = (List<StudentDto>) request.getAttribute("studentDtos");int curPage = (int) request.getAttribute("curPage");int totalPage = (int) request.getAttribute("totalPage");
%><button οnclick="doIndex()">返回</button>
<h1>学生列表页面</h1><table border="1" width="500px"><tr><th>账号</th><th>姓名</th><th>性别</th><th>年龄</th><th>爱好</th><th>操作</th></tr>//遍历,数据渲染<%for (StudentDto studentDto:studentDtos){%><tr><th><%=studentDto.getStudent().getUsername()%></th><th><%=studentDto.getStudent().getName()%></th><th><%=studentDto.getSex()%></th><th><%=studentDto.getStudent().getAge()%></th><th><%=studentDto.getHobbies()%></th><th><a href="StuInitModifyServlet?username=<%=studentDto.getStudent().getUsername()%>">修改</a><a href="StuDeleteServlet?username=<%=studentDto.getStudent().getUsername()%>">删除</a></th></tr><%}%>
</table>//分页
<a href="GetStuListServlet?curPage=1">首页</a>//第一页的时候不能有上一页
<%if(curPage > 1){%>
<a href="GetStuListServlet?curPage=<%=curPage-1%>">上一页</a>
<%}%>//最后一页的时候不能有下一页
<%if(curPage < totalPage){%>
<a href="GetStuListServlet?curPage=<%=curPage+1%>">下一页</a>
<%}%>
<a href="GetStuListServlet?curPage=<%=totalPage%>">尾页</a><script type="text/javascript">function goIndex(){window.location = "index.jsp";}
</script>
</body>
</html>
DBUtils 数据库工具类
获取当前表的总条数
public static int getAllCount(String table) throws SQLException {Connection connection = getConnection();String sql = "select count(1) from " + table;PreparedStatement statement = connection.prepareStatement(sql);ResultSet resultSet = statement.executeQuery();if(resultSet.next()){int allCount = resultSet.getInt(1);return allCount;}return 0;}
Student
做分页的假数据
public static void main(String[] args) {for (int i = 10; i < 100; i++) {String username = "xiaohei" + i;String password = "123123";String name = "小黑" + i;String sex = "man";int age = 23;String[] hobbies = {"football", "basketball"};try {DBUtils.commonUpdate("insert into student(username,password,name,sex,age,hobbies) values(?,?,?,?,?,?)", username, password, name, sex, age, StringUtils.handleArray(hobbies));} catch (SQLException e) {throw new RuntimeException(e);}}}
运行结果:
性别是man,爱好是英语,不方便观看,需要转成中文
包装学生类,写一个bto包,原来的student类不满足需求
分包新增信息处理类,以方便工具类对学生的信息处理
StudentDto
package com.qf.dto;public class StudentDto {private Student student;private String sex;private String hobbies;//无参构造,有参构造,get,set,toString类}
写一个工具类
DtoUtils
工具类,处理学生信息提升页面展示效果 ,然后在GetStuListServlet里操作
package com.qf.utils;public class DtoUtils {public static StudentDto studentDtoHandler(Student student) {//处理学生的性别数据String sex = student.getSex();if ("man".equals(sex)) {sex = "男";} else if ("woman".equals(sex)) {sex = "女";}//处理学生的爱好数据(做替换)String hobbies = student.getHobbies();hobbies = hobbies.replaceAll("football", "足球");hobbies = hobbies.replaceAll("basketball", "篮球");hobbies = hobbies.replaceAll("shop", "购物");//创建StudentDtoStudentDto studentDto = new StudentDto(student, sex, hobbies);return studentDto;}public static List<StudentDto> studentDtoListHandler(List<Student> students){ArrayList<StudentDto> studentDtos = new ArrayList<>();for (Student student:students){StudentDto studentDto = studentDtoHandler(student);studentDtos.add(studentDto);}return studentDtos;}
}
12.1 优化分页
GetStuListServlet
多了一个这个:设置URL:String url = “GetStuListServlet?curPage=”;
package com.qf.Servlet;@WebServlet("/GetStuListServlet")
public class GetStuListServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {request.setCharacterEncoding("UTF-8");response.setContentType("text/html;charset=UTF-8");//获取当前页数int curPage = Integer.parseInt(request.getParameter("curPage"));//设置URLString url = "GetStuListServlet?curPage=";//设置当前页的数据条数int count = 15;//计算偏移量int offset = (curPage-1)*count;//计算总页数int totalPage;try {int allCount = DBUtils.getAllCount("student");if(allCount % count == 0){totalPage = allCount/count;}else{totalPage = allCount/count + 1;}} catch (SQLException e) {throw new RuntimeException(e);}//从数据库获取学生的集合List<Student> students = null;try {students = DBUtils.commonQueryList(Student.class, "select * from student limit ?,?", offset, count);} catch (SQLException e) {throw new RuntimeException(e);}//处理学生集合List<StudentDto> studentDtos = DtoUtils.studentDtoListHandler(students);//封装Page对象Page<StudentDto> page = new Page<>(url, curPage, totalPage, studentDtos);//将数据存入到请求对象中request.setAttribute("page",page);//跳转request.getRequestDispatcher("stuList.jsp").forward(request,response);}
}
上面的请求对象太多了,同一设置一个page类
原来是这个:
//将数据存入到请求对象中
request.setAttribute(“curPage”,curPage);
request.setAttribute(“totalPage”,totalPage);
request.setAttribute(“studentDtos”,studentDtos);
package com.qf.pojo;public class Page<T> {private String url;private int curPage;private int totalPage;private List<T> list;
//省略
page.jsp
把分页放在外面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<a href="${page.url}1">首页</a>
<c:if test="${page.curPage > 1}"><a href="${page.url}${page.curPage-1}">上一页</a>
</c:if>
<c:if test="${page.curPage < page.totalPage}"><a href="${page.url}${page.curPage+1}">下一页</a>
</c:if>
<a href="${page.url}${page.totalPage}">尾页</a>
13.老师角色操作学生的修改
学生的修改写了的,就是StuInitModifyServlet
stuList.jsp
<%for (StudentDto studentDto:studentDtos){%><tr><th><%=studentDto.getStudent().getUsername()%></th><th><%=studentDto.getStudent().getName()%></th><th><%=studentDto.getSex()%></th><th><%=studentDto.getStudent().getAge()%></th><th><%=studentDto.getHobbies()%></th><th><a href="StuInitModifyServlet?username=<%=studentDto.getStudent().getUsername()%>">修改</a><a href="StuDeleteServlet?username=<%=studentDto.getStudent().getUsername()%>">删除</a></th></tr><%}%>
StuInitModifyServlet,跳转到StuModifyServlet
获取角色
1.通过角色判断修改
2.学生需要更新Session、Cookie里的数据,跳转详情页面
3.老师跳转GetStuListServlet,需要更新数据【因为修改了需要刷新页面】
(老师这里不需要修改cookie和session,最后一步不一样)
package com.qf.Servlet;@WebServlet("/StuModifyServlet")
public class StuModifyServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//设置请求、响应编码格式request.setCharacterEncoding("UTF-8");response.setContentType("text/html;charset=UTF-8");//获取请求中的数据String username = request.getParameter("username");String name = request.getParameter("name");String sex = request.getParameter("sex");String age = request.getParameter("age");String[] hobbies = request.getParameterValues("hobbies");//更新数据库里的学生数据try {DBUtils.commonUpdate("update student set name=?,sex=?,age=?,hobbies=? where username=?",name,sex,age, StringUtils.handleArray(hobbies),username);} catch (SQLException e) {throw new RuntimeException(e);}String role = (String) request.getSession().getAttribute("role");if("student".equals(role)){//更新Session里的数据request.getSession().setAttribute("name",name);//更新Cookie里的数据response.addCookie(CookieUtils.createCookie("name",name,60*60*24*5));//跳转详情页面response.sendRedirect("index.jsp");}else if("teacher".equals(role)){//跳转response.sendRedirect("GetStuListServlet?curPage=1");}}
}
14.老师角色操作学生的删除
stuList.jsp
<h1>学生列表页面</h1><%for (StudentDto studentDto:studentDtos){%><tr><th><%=studentDto.getStudent().getUsername()%></th><th><%=studentDto.getStudent().getName()%></th><th><%=studentDto.getSex()%></th><th><%=studentDto.getStudent().getAge()%></th><th><%=studentDto.getHobbies()%></th><th><a href="StuInitModifyServlet?username=<%=studentDto.getStudent().getUsername()%>">修改</a><a href="StuDeleteServlet?username=<%=studentDto.getStudent().getUsername()%>">删除</a></th></tr><%}%>
</table></body>
</html>
StuDeleteServlet
设置编码格式,获取请求中的账号,通过学生账号删除学生,最后跳转GetStuListServlet同时更新数据
注意:实际开发项目中是不会直接用delete,而是改状态,数据库有提到
package com.qf.Servlet;@WebServlet("/StuDeleteServlet")
public class StuDeleteServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {request.setCharacterEncoding("UTF-8");response.setContentType("text/html;charset=UTF-8");String username = request.getParameter("username");try {DBUtils.commonUpdate("delete from student where username=?",username);} catch (SQLException e) {throw new RuntimeException(e);}//跳转response.sendRedirect("GetStuListServlet?curPage=1");}
}