学习Java的日子 Day59 学生管理系统 web1.0版本

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的基本工作原理:

  1. 用户访问Web应用程序时,服务器为每个用户创建一个唯一的Session对象。
  2. 服务器将Session ID 分配给每个Session对象,并将Session ID 存储在用户的浏览器中的Cookie中。Session ID 在服务器端和客户端之间用于标识Session。
  3. 当用户发送请求时,服务器使用Session ID 来查找相应的Session对象。
  4. 服务器可以将数据存储在Session对象中,以便在用户的不同请求之间共享。
  5. 当用户关闭浏览器或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

操作:初始化修改学生数据

  1. 设置请求、响应编码格式
  2. 获取请求中的数据
  3. 从数据库中获取学生对象
  4. 将学生对象存在请求中,转发方式到学生修改信息页面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

操作:初始化修改老师数据

  1. 设置请求、响应编码格式
  2. 获取请求中的数据
  3. 从数据库中获取老师对象
  4. 将老师对象和课程集合对象存在请求中,转发方式到老师修改信息页面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");}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/390938.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【初学人工智能原理】【12】循环:序列依赖问题

前言 本文教程均来自b站【小白也能听懂的人工智能原理】&#xff0c;感兴趣的可自行到b站观看。 代码及工具箱 本专栏的代码和工具函数已经上传到GitHub&#xff1a;1571859588/xiaobai_AI: 零基础入门人工智能 (github.com)&#xff0c;可以找到对应课程的代码 正文 对于…

LabVIEW水下根石监测系统

开发了一种基于LabVIEW平台开发的水下根石监测系统。该系统利用高精度姿态传感器与位移传感器&#xff0c;实现了水下根石状态的实时自动监测&#xff0c;提高了水利工程安全管理的现代化和精细化水平&#xff0c;具有高精度、高稳定性和良好的操作性。 项目背景&#xff1a; …

canvas绘制文本时,该如何处理首行缩进、自动换行、多内容以省略号结束、竖排的呢?

实现如标题所示的这些文本效果&#xff0c;在css看来&#xff0c;不就是一两行css属性。然而&#xff0c;对于canvas来讲&#xff0c;要想呈现这样的文字样式&#xff0c;就没css那么轻松简便了。 既然如此&#xff0c;那为何还要使用对文本支持度不友好的canvas来绘制文字呢&a…

【开发视角】大模型 RAG 检索增强生成究竟是什么

【大白话讲懂】大模型 RAG 检索增强生成 话先说在前面&#xff0c;本文不讲不会讲太多原理&#xff0c;仅面向工程开发&#xff0c;从工作流程的宏观角度进行梳理&#xff0c;旨在快速上手。 RAG 是什么 基本定义 让我们先来解释名词&#xff0c;看看宏观框架。 RAG 的意思…

科普文:微服务之SpringBoot性能优化器动态线程池【Dynamic-Tp】特性和源码解读

一、简述 gitee地址&#xff1a;https://gitee.com/yanhom/dynamic-tp github地址&#xff1a;https://github.com/lyh200/dynamic-tp dynamic-tp是一个轻量级的动态线程池插件&#xff0c;它是一个基于配置中心的动态线程池&#xff0c;线程池的参数可以通过配置中心配置进…

C++中lambda使用mutable关键字详解

C中lambda使用mutable关键字详解 在《C初学者指南-5.标准库(第二部分)–更改元素算法》中&#xff0c;讲“generate”算法时有下面这段代码&#xff1a; auto gen [i0]() mutable { i 2; return i; }; std::vector<int> v; v.resize(7,0); generate(begin(v)1, begin…

C++ STL在算法题中的常用语法

Vector 1.将vector<int>中的元素全部置换为0 fill(vec.begin(), vec.end(), 0); 2.vector容器是可以直接用比较是否值等的&#xff01; Unordered_set 1. unordered_set的删除&#xff08;count的值也会减少&#xff09; 2.unordered_map中的int默认值是0&#xff0c;…

在Jira中使用AI

Jira已经可以使用AI功能了。 如果您使用的是Jira Cloud&#xff0c;您需要请管理员在管理页面中打开AI功能开关。&#xff08;AI功能在Standard版中未提供&#xff0c;请使用Premium或更高级的版本&#xff09;如果您使用的是自己部署的Jira Data Center&#xff0c;您需要请管…

算法学习day28

一、寻找右区间(二分法) 题意&#xff1a;题目很容易理解 但是转换为二分法有点晦涩 给你一个区间数组 intervals &#xff0c;其中 intervals[i] [starti, endi] &#xff0c;且每个 starti 都 不同 。区间 i 的 右侧区间 可以记作区间 j &#xff0c;并满足 startj > e…

OpenCV||超详细的灰度变换和直方图修正

一、点运算 概念&#xff1a;点运算&#xff08;也称为像素级运算或单像素操作&#xff09;是指对图像中每一个像素点进行独立、相同的操作&#xff0c;而这些操作不会考虑像素点之间的空间关系。点处理优势也称对比度拉伸、对比度增强或灰度变换等。 目的&#xff1a;点运算…

【EtherCAT】Windows+Visual Studio配置SOEM主站——静态库配置+部署

目录 一、准备工作 1. Visual Studio 2022 2. Npcap 1.79 3. SOEM源码 二、静态库配置 1. 修改SOEM源码配置 2. 编译SOEM源码 3. 测试 三、静态库部署 1. 新建Visual Studio工程 2. 创建文件夹 3. 创建主函数 4. 复制静态库 5. 复制头文件 6. 配置头文件…

链接、装载和库——1 简介

前言 关于个人的读书笔记 第一章 温故而知新 1.1 从hello&#xff0c;world说起 ​计算机在执行hello&#xff0c;world的时候发生了什么&#xff1f; 1.2 万变不离其宗 ​在计算机多如牛毛的硬件设备中。有三个部件最为关键&#xff0c;它们分别是 CPU、内存和 I/O 控制芯…

一次多波束和浅地层处理的经历—信标机出问题?

最近处理多波束和浅地层时&#xff0c;一个从来没有过的问题出现了。 多波束数据(.pds)是由PDS2000采集的&#xff0c;使用设备型号为T50P。浅地层数据(.raw)是有SESWIN采集的&#xff0c;使用设备型号为SES2000 Standard。 1、多波束处理 多波束数据采用CARIS11.3处理的。船…

开源LivePortrait,快速实现表情包自定义

最近可灵AI很火&#xff0c;看到网上生成的效果也很赞啊&#xff0c;之前发现快手可灵开源了LivePortrait&#xff0c;今天去玩了一下&#xff0c;很有意思。 比如下图官方展示效果&#xff1a; 这些图片开始自带表情了&#xff0c;主要就是通过LivePortrait来实现。 LivePor…

[E二叉树] lc572. 另一棵树的子树(dfs+前中序判断+树哈希+树上KMP+好题)

文章目录 1. 题目来源2. 题目解析 1. 题目来源 链接&#xff1a;572. 另一棵树的子树 2. 题目解析 看到这个题目就感觉不简单&#xff0c;因为写了写 dfs 版本的&#xff0c;发现好像不太会… 还是简单粗暴一点&#xff0c;直接搞一个 前序中序&#xff0c;进行判断即可。我…

【PyTorch】神经风格迁移项目

神经风格迁移中&#xff0c;取一个内容图像和一个风格图像&#xff0c;综合内容图像的内容和风格图像的艺术风格生成新的图像。 目录 准备数据 处理数据 神经风格迁移模型 加载预训练模型 定义损失函数 定义优化器 运行模型 准备数据 创建data文件夹&#xff0c;放入…

数据恢复软件:电脑丢失文件,及时使用数据恢复软件恢复!

数据恢复软件什么时候会用到&#xff1f; 答&#xff1a;如果真的不小心删除文件&#xff0c;清空回收站&#xff0c;电脑重装系统等情况发生&#xff0c;我们要懂的及时停止使用电子设备&#xff0c;使用可靠的数据恢复软件&#xff0c;帮助我们恢复这些电子设备的数据&#…

二进制搭建 Kubernetes v1.20(上)

目录 一、操作系统初始化配置 二、升级Liunx内核 三、部署docker引擎 四、部署etcd集群 五、部署Master组件 六、部署Worker Node组件 hostnameip需要部署k8s集群master0120.0.0.100kube-apiserver kube-controller-manager kube-scheduler etcdk8s集群master0220.0.0.1…

CookieMaker工作室合作开发C++项目十一:拟态病毒

&#xff08;注&#xff1a;本文章使用了“无标题技术”&#xff09; 一天&#xff0c;我和几个同事&#xff0c;平台出了点BUG&#xff0c;居然给我刷出了千年杀&#xff0c;同事看得瑕疵欲裂&#xff0c;发誓要将我挫骨扬灰—— &#xff08;游戏入口&#xff1a;和平精英31.…

【数据脱敏】数据交换平台数据脱敏建设方案

1 概述 1.1 数据脱敏定义 1.2 数据脱敏原则 1.2.1基本原则 1.2.2技术原则 1.2.3管理原则 1.3 数据脱敏常用方法 3.1.1泛化技术 3.1.2抑制技术 3.1.3扰乱技术 3.1.4有损技术 1.4 数据脱敏全生命周期 2 制定数据脱敏规程 3 发现敏感数据 4 定义脱敏规则 5 执…