Day37

Day37

综合案例

http请求方式有哪些?

GET:请求指定的页面信息,并返回实体主体。这是最常见的请求方式,用于从服务器获取数据。
HEAD:类似于GET请求,只不过返回的响应中没有具体的内容,只有报文头,用于获取报文头信息。
POST:向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。
PUT:从客户端向服务器传送的数据取代指定的文档的内容。
DELETE:请求服务器删除指定的页面。
CONNECT:HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。
OPTIONS:允许客户端查看服务器的性能。
TRACE:回显服务器收到的请求,主要用于测试或诊断。
PATCH:对PUT方法的补充,用来对已知资源进行局部更新。
这些请求方式各有其用途,例如GET和POST是最常用的两种请求方式,其中GET用于获取数据,而POST用于提交数据。其他请求方式如PUT、DELETE等则用于更新或删除服务器上的资源。

WEB版学生管理系统

注册

拿到项目先做需求分析:

用户角色:登录(验证码、记住我)、安全退出、修改密码

学生角色:注册、修改信息

老师角色:修改信息、查询所有学生(分页查询)、修改学生信息、删除学生信息

数据库搭建:

​ 创建表:学生表(username、password、name、sex、age、hobbies)

​ 老师表(username、password、name、courseId)

​ 学科表(id、name)

项目搭建:

​ 导包(servlet、sql、druid),导入会有路径问题,在problem那里查看解决。

​ 创建包:utils(需要放入properties文件)、pojo、servlet。

​ 写前端页面:两个超链接:一个是登录(写login.html),一个是注册(register.html)。登录有验证码、记住我、返回等。

欢迎页面:

<?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>

登录页面:

<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><style>body {display: flex;justify-content: center;align-items: center;height: 100vh;margin: 0;font-family: Arial, sans-serif;background: #f0f0f0;}</style>
</head>
<body>
<div><form action="LoginServlet" method="post"><h2>欢迎来到登录界面</h2><br/><table><tr><td>账号:<input type="text" name="username"/></td></tr><tr><td>密码:<input type="password" name="password"/></td></tr><tr><td>验证码:<input type="text" name="userCode" /><img  width="120px" height="30px"><a href="#" onclick="flushCode()">刷新</a><br /></td></tr><tr><td>角色:<input type="radio" name="role" value="student"/>学生<input type="radio"name="role" value="teacher"/>老师</td></tr><tr><td>记住我:<input type="checkbox" name="rememberMe"/><br/></td></tr><tr><td><input type="submit" value="登录"/></td></tr></table></form>
</div>
<script type="text/javascript">function flushCode(){}
</script>
</body>
</html>

注册页面:

<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><style>body {display: flex;justify-content: center;align-items: center;height: 100vh;margin: 0;font-family: Arial, sans-serif;background: #f0f0f0;}</style>
</head>
<body><form action="RegisterServlet" method="post"><h2>欢迎来到注册页面</h2><br/>账号:<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" checked="checked"/>足球<input type="checkbox" name="hobbies" value="basketball" />篮球<input type="checkbox" name="hobbies" value="shop" />购物<br /><input type="submit" value="注册" /><button type="button" onclick="fun01()">返回</button>
</form><script type="text/javascript">function fun01(){window.location = "welcome.html";}
</script></body>
</html>

写实体类pojo:

​ User类:属性(表内字段)、构造方法、getset()、toString()

​ Student类继承User:属性、构造(有参选择父类有参)、getset、toString

​ Teacher类继承User:属性、构造()、getset、toString()

​ Course类:属性、构造、getset、toString()

package com.qf.pojo;public class User {private String username;private String password;private String name;public User() {}public User(String username, String password, String name) {this.username = username;this.password = password;this.name = name;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "User{" +"username='" + username + '\'' +", password='" + password + '\'' +", name='" + name + '\'' +'}';}
}
package com.qf.pojo;public class Student extends User{private String sex;private int age;private String hobbies;public Student(String username, String password, String name, String sex, int age, String hobbies) {super(username, password, name);this.sex = sex;this.age = age;this.hobbies = hobbies;}public Student() {}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getHobbies() {return hobbies;}public void setHobbies(String hobbies) {this.hobbies = hobbies;}@Overridepublic String toString() {return "Student{" +"sex='" + sex + '\'' +", age=" + age +", hobbies='" + hobbies + '\'' +"} " + super.toString();}
}
package com.qf.pojo;public class Teacher extends User{private int courseId;public Teacher(String username, String password, String name, int courseId) {super(username, password, name);this.courseId = courseId;}public Teacher() {}public int getCourseId() {return courseId;}public void setCourseId(int courseId) {this.courseId = courseId;}@Overridepublic String toString() {return "Teacher{" +"courseId=" + courseId +"} " + super.toString();}
}
package com.qf.pojo;public class Course {private int id;private String name;public Course() {}public Course(int id, String name) {this.id = id;this.name = name;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "Course{" +"id=" + id +", name='" + name + '\'' +'}';}
}

​ 写RegisterServlet类,继承HttpServlet,注释,设置编码格式,获取请求中的数据,将获取的数据封装成一个对象(打印一下查看是否获取到数据),注意其中的hobbies要转换为String,age要从String转换为Integer。再判断账号是否存在,用commonQueryObj方法返回对象,如果等于null,就允许注册,插入sql语句,然后跳转到登录页面。如果非空进行提示。

(优化:获取数据这个过程getParameter()太冗杂,用request.getParameterMap()方法,放的是字段和字段数组。

写一个将数组转换为String的工具类StringUtil,静态方法parseString(Object[] objs),用StringBuffer来添加数组内容,不要用Arrays.toString,因为会带有中括号。

package com.qf.utils;public class StringUtil {public static String parseString(Object[] objs){StringBuffer sb = new StringBuffer();for(Object obj :objs){if(sb.length()!=0){sb.append(",");}sb.append(obj);}return sb.toString();}
}

写一个工具类BeanUtil:

编写getField方法获取本类及其父类属性对象;

编写setProperty(Object bean,String name,Object value)方法设置属性,注意这里的key,value可能是字符串数组,要加判断,使用编写的StringUtil的方法把字符串数组转换为字符串。并进行set设置;

编写getProperty(Object bean,String name)方法获取本类及父类的属性值;

编写无返回值的populate(Object bean,Map<String,String[]> properties)方法,把字段数组放入对象中。(request.getParameterMap()方法返回的键都是String,值都是String[])

package com.qf.utils;import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;public class BeanUtil {/*** 获取本类及其父类的属性对象* @param clazz* @param name* @return*/public static Field getField(Class<?> clazz,String name) {for(Class<?> c=clazz;c!=null;c=c.getSuperclass()){try {return c.getDeclaredField(name);} catch (NoSuchFieldException e) {throw new RuntimeException(e);}}return null;}/*** 获取对象及其父类对象的属性值* @param bean* @param name* @return*/public static Object getProperty(Object bean,String name){Class<?> clazz = bean.getClass();Field field = getField(clazz, name);if(field==null){return null;}field.setAccessible(true);try {Object fieldVal = field.get(bean);return fieldVal;} catch (IllegalAccessException e) {throw new RuntimeException(e);}}/*** 设置对象属性* @param bean* @param name* @param value*/public static void setProperty(Object bean,String name,Object value){Class<?> clazz = bean.getClass();Field field = getField(clazz, name);if(field==null){return;}field.setAccessible(true);try {if(field.getType()==String.class){if(value.getClass()==String[].class){String[] ss= (String[]) value;String str = StringUtil.parseString(ss);field.set(bean,str);}}if(field.getType()==String[].class){if(value.getClass()==String[].class){String[] ss = (String[]) value;field.set(bean,ss);}}if(field.getType()==int.class){if(value.getClass()==String[].class){String[] ss = (String[]) value;String str = StringUtil.parseString(ss);int num = Integer.parseInt(str);field.set(bean,num);}}}catch (IllegalAccessException e) {throw new RuntimeException(e);}}public static void populate(Object bean, Map<String,String[]> properties){Set<Map.Entry<String, String[]>> entries = properties.entrySet();for(Map.Entry<String, String[]> entry:entries){String key = entry.getKey();String[] value = entry.getValue();setProperty(bean,key,value);}}
}

DButil里面添加commonQueryObj()方法返回单个对象。思路为调用commonQueryList()方法,进行内容判断。)

package com.qf.utils;import com.alibaba.druid.pool.DruidDataSource;import java.io.IOException;
import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;public class DBUtil {//druid数据库连接池private static DruidDataSource pool;static{Properties properties = new Properties();try {properties.load(DBUtil.class.getClassLoader().getResourceAsStream("DBConfig.properties"));} catch (IOException e) {throw new RuntimeException(e);}String driverName = properties.getProperty("driverName");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(driverName);pool.setUrl(url);pool.setUsername(username);pool.setPassword(password);pool.setMaxActive(maxActive);local = new ThreadLocal<>();}private static ThreadLocal<Connection> local;/*** 开启事务*/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 = null;}}/*** 回滚事务*/public static void rollback() throws SQLException {Connection connection = local.get();if(connection != null){connection.rollback();connection = null;}}/*** 获取连接对象*/public static Connection getConnection() throws SQLException {Connection connection = local.get();if(connection == null){connection = pool.getConnection();//设置事务的隔离界别connection.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);local.set(connection);}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 int commonUpdate(String sql,Object... params) throws SQLException {Connection connection = null;PreparedStatement statement = null;try {connection = getConnection();statement = connection.prepareStatement(sql);paramsHandler(statement,params);int num = statement.executeUpdate();return num;} finally {close(connection,statement,null);}}/*** 主键回填*/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);paramsHandler(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, InstantiationException, IllegalAccessException {Connection connection = null;PreparedStatement statement = null;ResultSet resultSet = null;try {connection = getConnection();statement = connection.prepareStatement(sql);paramsHandler(statement,params);resultSet = statement.executeQuery();//获取表信息对象ResultSetMetaData metaData = resultSet.getMetaData();//获取字段个数int fieldCount = metaData.getColumnCount();List<T> list = new ArrayList<>();while(resultSet.next()){//创建对象T t = clazz.newInstance();for (int i = 1; i <= fieldCount ; i++) {//获取字段名String fieldName = metaData.getColumnName(i);//获取该数据行上对应字段的数据Object val = resultSet.getObject(fieldName);//利用反射设置对象里对应的属性setField(t,fieldName,val);}//将对象添加到List集合中list.add(t);}return list;} finally {close(connection,statement,resultSet);}}/*** 查询单个对象*/public static <T> T commonQueryObj(Class<T> clazz,String sql,Object... params) throws SQLException, InstantiationException, IllegalAccessException {List<T> list = commonQueryList(clazz, sql, params);if(list.isEmpty()){return null;}T t = list.get(0);return t;}/*** 处理sql命令中的参数*/private static void paramsHandler(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();}}}}

RegisterServlet:

package com.qf.servlet;import com.qf.pojo.Student;
import com.qf.utils.BeanUtil;
import com.qf.utils.DBUtil;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Map;@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");Map<String, String[]> parameterMap = request.getParameterMap();Student stu = new Student();BeanUtil.populate(stu,parameterMap);//判断账号是否存在try {Student student = DBUtil.commonQueryObj(stu.getClass(),"select * from student where username=?",stu.getUsername());if(student==null){//允许注册String insertSql="insert into student(username,password,name,age,sex,hobbies) values(?,?,?,?,?,?)";DBUtil.commonInsert(insertSql,stu.getUsername(),stu.getPassword(),stu.getName(),stu.getAge(),stu.getSex(),stu.getHobbies());response.sendRedirect("login.html");}else{//不允许注册}} catch (SQLException e) {throw new RuntimeException(e);} catch (InstantiationException e) {throw new RuntimeException(e);} catch (IllegalAccessException e) {throw new RuntimeException(e);}}
}
登录

LoginServlet编写:
设置编码格式,获取请求里的数据,但是无法封装成对象,因为数据是杂乱的,有账号、密码、验证码、角色、记住我。

获取数据后先判断角色,建议颠倒写法,如if(“student”.equals(role)),防止传入数据为空导致空指针异常,然后传入sql语句调用工具类相关方法进行查询。

再利用多态的思想,判断user是否为空,如果为空跳转注册,不为空跳转登录。

package com.qf.servlet;import com.qf.pojo.Student;
import com.qf.pojo.Teacher;
import com.qf.pojo.User;
import com.qf.utils.DBUtil;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.SQLException;@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");User user = new User();//判断角色并获取相应角色的数据try {if("student".equals(role)) {String sql = "select * from student where username=? and password = ?";user = DBUtil.commonQueryObj(Student.class, sql, username, password);}else if("teacher".equals(role)){String sql = "select * from teacher where username=? and password = ?";user = DBUtil.commonQueryObj(Teacher.class,sql,username,password);}} catch (Exception e) {throw new RuntimeException(e);}if(user!=null){//有相关数据,登录成功response.sendRedirect("index.html");}else{//登录失败response.sendRedirect("welcome.html");}}
}
验证码

验证码功能:防止恶意登录(利用代码循环机器登录)。

获取验证码通过CodeServlet在后端发送,因为前端可以看到代码,所以放在后端安全性更高。

绘制验证码:

CodeServlet:

画一张验证码,传回前端。步骤:设置画布,填充颜色,获取画笔,设置画笔颜色,填充矩形(和前端验证码框大小一致),画笔位置改变,用其他颜色做适量的干扰线,最后将图片传回给客户端。

package com.qf.servlet;import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;@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 ran = new Random();String[] codes = {"A","B","C","D","E","F","G","H","I","J","K","L","M","N","P","Q","R","S","T","U","V","W","X","Y","Z","1","2","3","4","5","6","7","8","9","0"};Color[] colors={Color.cyan,Color.RED,Color.PINK,Color.GREEN};StringBuffer sb = new StringBuffer();for(int i=0;i<4;i++){//设置字体格式graphics.setFont(new Font("宋体",Font.BOLD,20+ran.nextInt(10)));//设置字体颜色graphics.setColor(colors[ran.nextInt(colors.length)]);//绘制单个字体String code = codes[ran.nextInt(codes.length)];sb.append(code);graphics.drawString(code,20+20*i,20+ran.nextInt(10));}//绘制干扰线graphics.setColor(Color.YELLOW);for(int i=0;i<3;i++){graphics.drawLine(ran.nextInt(width), ran.nextInt(height), ran.nextInt(width), ran.nextInt(height));}//把验证码图片返回客户端ImageIO.write(image,"jpg",response.getOutputStream());}
}
刷新展示验证码:

在login.html里设置

浏览器有保护机制,不能重复发相同的请求,所以可以利用时间发送不同名字的请求。

<tr><td>验证码:<input type="text" name="userCode" /><img  id="code" src="CodeServlet" width="120px" height="30px"><a href="#" onclick="flushCode()">刷新</a><br /></td></tr><script type="text/javascript">var code=document.getElementById("code");function flushCode(){code.src="CodeServlet?"+ new Date();}</script>
判断验证码

设置静态属性sysCode

思路:在CodeServlet里返回,在LoginServlet里去获取,并判断是否相同。但是会出现问题:多个浏览器连接验证码会冲突。

解决方案:不同的浏览器同时连接服务器,会产生不同的会话对象HttpSession,应该把系统生成的验证码设置到Session中,然后在LoginServlet中利用响应获取验证码。

CodeServlet中:

//将系统生成的验证码设置到session中HttpSession session = request.getSession();session.setAttribute("Syscode",sb.toString());

LoginServlet获取并用来和获取的登录信息中验证码填写比较:

String sysCode= (String) request.getSession().getAttribute("Syscode");User user = new User();//判断角色并获取相应角色的数据if(sysCode.equalsIgnoreCase(userCode)){try {if("student".equals(role)) {String sql = "select * from student where username=? and password = ?";user = DBUtil.commonQueryObj(Student.class, sql, username, password);}else if("teacher".equals(role)){String sql = "select * from teacher where username=? and password = ?";user = DBUtil.commonQueryObj(Teacher.class,sql,username,password);}} catch (Exception e) {throw new RuntimeException(e);}if(user!=null){//有相关数据,登录成功response.sendRedirect("index.html");}else{//登录失败response.sendRedirect("welcome.html");}}
登录、注册失败提示

JSP—Java Server Page Java服务页面

理解:可以写HTML+Java代码

在不允许注册里:

请求里存储会话域数据,将数据设置到请求对象中

将register.html删掉,换成register.jsp

jsp中写java代码格式:<% //Java代码 %>

package com.qf.servlet;import com.qf.pojo.Student;
import com.qf.utils.BeanUtil;
import com.qf.utils.DBUtil;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Map;@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");Map<String, String[]> parameterMap = request.getParameterMap();Student stu = new Student();BeanUtil.populate(stu,parameterMap);//判断账号是否存在try {Student student = DBUtil.commonQueryObj(stu.getClass(),"select * from student",stu.getUsername());if(student==null){//允许注册String insertSql="insert into student(username,password,name,age,sex,hobbies) values(?,?,?,?,?,?)";DBUtil.commonInsert(insertSql,stu.getUsername(),stu.getPassword(),stu.getName(),stu.getAge(),stu.getSex(),stu.getHobbies());response.sendRedirect("login.jsp");}else{//不允许注册//将信息设置到session里面request.setAttribute("msg","注册失败,已有该账号");request.getRequestDispatcher("register.jsp").forward(request,response);}} catch (SQLException e) {throw new RuntimeException(e);} catch (InstantiationException e) {throw new RuntimeException(e);} catch (IllegalAccessException e) {throw new RuntimeException(e);}}
}
<%--Created by IntelliJ IDEA.User: GuDate: 2024-06-13Time: 18:43To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><style>body {display: flex;justify-content: center;align-items: center;height: 100vh;margin: 0;font-family: Arial, sans-serif;background: #f0f0f0;}</style>
</head>
<body><%//从请求对象中获取数据String msg = (String) request.getSession().getAttribute("msg");%><%= (msg!=null)?msg:"" %><form action="RegisterServlet" method="post"><h2>欢迎来到注册页面</h2><br/>账号:<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" checked="checked"/>足球<input type="checkbox" name="hobbies" value="basketball" />篮球<input type="checkbox" name="hobbies" value="shop" />购物<br /><input type="submit" value="注册" /><button type="button" οnclick="fun01()">返回</button>
</form><script type="text/javascript">function fun01(){window.location = "welcome.html";}
</script></body>
</html>

注意:放在请求里的数据不能用重定向,因为会发送两次请求,数据会重置。

登录同理,login.html改为login.jsp。

package com.qf.servlet;import com.qf.pojo.Student;
import com.qf.pojo.Teacher;
import com.qf.pojo.User;
import com.qf.utils.DBUtil;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.SQLException;@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");User user = new User();//判断角色并获取相应角色的数据if(sysCode.equalsIgnoreCase(userCode)){try {if("student".equals(role)) {String sql = "select * from student where username=? and password = ?";user = DBUtil.commonQueryObj(Student.class, sql, username, password);}else if("teacher".equals(role)){String sql = "select * from teacher where username=? and password = ?";user = DBUtil.commonQueryObj(Teacher.class,sql,username,password);}} catch (Exception e) {throw new RuntimeException(e);}if(user!=null){//有相关数据,登录成功response.sendRedirect("index.html");}else{//登录失败 --账号或密码错误request.setAttribute("msg","登录失败,账号或密码错误");request.getRequestDispatcher("login.jsp").forward(request,response);}}else{//登录失败--验证码错误request.setAttribute("msg","登录失败,验证码错误");request.getRequestDispatcher("login.jsp").forward(request,response);}}
}
<%--Created by IntelliJ IDEA.User: GuDate: 2024-06-13Time: 18:43To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><style>body {display: flex;justify-content: center;align-items: center;height: 100vh;margin: 0;font-family: Arial, sans-serif;background: #f0f0f0;}</style>
</head>
<body><%String msg= (String) request.getSession().getAttribute("msg");%><%= (msg!=null)?msg:"" %>
<div><form action="LoginServlet" method="post"><h2>欢迎来到登录界面</h2><br/><table><tr><td>账号:<input type="text" name="username"/></td></tr><tr><td>密码:<input type="password" name="password"/></td></tr><tr><td>验证码:<input type="text" name="userCode" /><img  id="code" src="CodeServlet" width="120px" height="30px"><a href="#" οnclick="flushCode()">刷新</a><br /></td></tr><tr><td>角色:<input type="radio" name="role" value="student"/>学生<input type="radio"name="role" value="teacher"/>老师</td></tr><tr><td>记住我:<input type="checkbox" name="rememberMe"/><br/></td></tr><tr><td><input type="submit" value="登录"/></td></tr></table></form>
</div>
<script type="text/javascript">var code=document.getElementById("code");function flushCode(){code.src="CodeServlet?"+ new Date();}
</script>
</body>
</html>

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

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

相关文章

北斗应急通信手持终端如何在户外使用

北斗应急通信手持终端在户外的使用&#xff0c;需要遵循一定的步骤和注意事项以确保其高效、安全地运作。以下是一个清晰的使用指南&#xff1a; 一、准备阶段 检查电量&#xff1a;确保北斗应急通信手持终端的电量充足&#xff0c;并携带备用电源以应对长时间使用的情况。 熟…

Ubuntu系统设置中文输入法

重新设置超级用户权限(root)密码(非必要) sudo passwd root 需要注意的是Ubuntu的root密码不能少于8个字符 设置成功后输入命令和新的密码即可无需输入sudo启用root命令 su - 更新软件包列表 sudo apt update sudo apt upgrade 安装fcitx5输入法框架 个别情况需要卸载旧的…

红黑树【C++实现】

文章目录 红黑树的概念红黑树的性质红黑树的操作红黑树结点的定义红黑树的插入情况一&#xff1a;插入结点的叔叔存在&#xff0c;且叔叔的颜色是红色情况二: 插入结点的叔叔存在&#xff0c;且叔叔的颜色是黑色情况三: 插入结点的叔叔不存在 红黑树的验证红黑树的查找 红黑树的…

实现直流高电压(100Vdc~1000Vdc)检测的采样电路(隔离方案)

目前&#xff0c;在电力系统自动化领域、新能源电动汽车领域以及高压储能领域&#xff0c;经常需要采样、检测高压直流母线电压&#xff0c;一般直流高压可能达到100Vdc&#xff5e;1000Vdc&#xff0c;结合电路成本和采样精度&#xff0c;我们设计人员就需要选择合适的采样电路…

【elementui源码解析】如何实现自动渲染md文档-第一篇

文章目录 目录 背景 获取源码 代码分析 背景 之前基于vant3的源码开发过二次开发过组件&#xff0c;其中vant实现了将md文档渲染到界面上&#xff0c;有天突发奇想想知道这是如何实现的将md文档渲染到界面上的&#xff0c;因为平时开发中使用elementui占多数&#xff0c;所…

java线程池讲解!核心参数

创建方式 | 构造方法 Executor构造方法 存放线程的容器&#xff1a; private final HashSet<Worker> workers new HashSet<Worker>(); 构造方法&#xff1a; public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit uni…

利用Morph Studio平台免费生成AI视频教程和效果体验

今天体验一下生成AI视频平台&#xff0c;目前是免费的&#xff0c;但生成效果还是不错的,可以根据输入文字&#xff0c;或者上传图片&#xff0c;或者上传视频来自动生成视频。 访问官网&#xff0c;登录之后点击“create Library” &#xff0c;比如我建了一个“AI视频”的Li…

4S店试驾线上预约小程序源码系统 前后端分离 带完整的源代码包+安装部署教程

系统概述 这款 4S 店试驾线上预约小程序源码系统旨在为 4S 店和消费者提供便捷、高效的试驾预约服务。通过小程序&#xff0c;消费者可以轻松预约试驾&#xff0c;4S 店可以方便地管理预约信息&#xff0c;提高工作效率和服务质量。 代码示例 系统特色功能一览 1.便捷的预约流…

面向对象编程重载

系列文章目录 文章目录 系列文章目录前言一、重载&#xff08;overload&#xff09; 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&#xff0c;看懂了…

52.@NotNUll,@NotBlank,@NotEmpty的使用区别

1.NotNull 适用于基本数据类型(Integer&#xff0c;Long&#xff0c;Double等等)&#xff0c;当 NotNull 注解被使用在 String 类型的数据上&#xff0c;则表示该数据不能为 Null&#xff08;但是可以为 Empty&#xff09; NotNull(message "id不能为空", groups …

000003 - Hadoop集群配置

Hadoop集群配置 1. 背景2. 实践2.1 集群规划2.2 配置文件说明2.3 配置 1. 背景 在000002 - Hadoop环境安装&#xff0c;我们已经执行完了如下步骤。接下来就是将不同服务器上的Hadoop配置为一个整体的集群。 准备三台Linux服务器&#xff0c;服务器之间相互配置免密ssh登陆在…

floating_point的IP核使用

参考文章&#xff1a;Vivado IP核之定点数转为浮点数Floating-point_vivado 浮点数-CSDN博客 IP核的配置 后边还要做FFT&#xff0c;所以理论上最好的输出方式是单精度浮点。 输入精度&#xff1a;为了满足要求&#xff0c;输出数据的24位&#xff0c;其中 1位符号位&#xff…

2024年【制冷与空调设备运行操作】考试内容及制冷与空调设备运行操作考试报名

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 制冷与空调设备运行操作考试内容考前必练&#xff01;安全生产模拟考试一点通每个月更新制冷与空调设备运行操作考试报名题目及答案&#xff01;多做几遍&#xff0c;其实通过制冷与空调设备运行操作新版试题很简单。…

工厂模式(设计模式)

使用工厂模式创建对象的好处在于&#xff0c;具体的实现类可以随意换&#xff08;解耦&#xff09;。因为在返回创建的对象的时候&#xff0c;我将此对象向上转型。那么如果需求变动&#xff0c;我可以再写一个这个接口的实现类&#xff0c;只用修改这个工厂类中的代码。而使用…

pytest配置文件配置并通过allure生成报告

之前已经学习了使用pytestrequests实现各种方式的调用和一些脚本的执行&#xff0c;今天来学习下如何使用pytest.ini配置文件来管理用例的执行以及如何使用allure生成测试报告。 1.pytest.ini文件配置 在项目目录下新建pytest.ini文件&#xff0c;然后进行配置&#xff0c;pyt…

从路边摊到五星级酒店:六西格玛培训的价格与品质探秘!

当我们深入探讨市面上的六西格玛培训价格差异时&#xff0c;确实会发现不同机构之间存在着显著的差别。以张驰咨询和xx机构为例&#xff0c;两者在价格定位上形成了鲜明的对比&#xff0c;同时也展示了不同机构在教学理念和服务品质上的不同。 xx机构之所以能以亲民的价格吸引…

JVM常用概念之扁平化堆容器

扁平化堆容器是OpenJDK Valhalla 项目提出的&#xff0c;其主要目标为将值对象扁平化到其堆容器中&#xff0c;同时支持这些容器的所有指定行为&#xff0c;从而达到不影响原有功能的情况下&#xff0c;显著减少内存空间的占用&#xff08;理想条件下可以减少24倍&#xff09;。…

力扣416 分割等和子集 Java版本

文章目录 题目描述思路代码 题目描述 给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集&#xff0c;使得两个子集的元素和相等。 示例 1&#xff1a; 输入&#xff1a;nums [1,5,11,5] 输出&#xff1a;true 解释&#xff1a;数组可以…

【技巧】Leetcode 191. 位1的个数【简单】

位1的个数 编写一个函数&#xff0c;输入是一个无符号整数&#xff08;以二进制串的形式&#xff09;&#xff0c;返回其二进制表达式中 设置位 的个数&#xff08;也被称为汉明重量&#xff09;。 示例 1&#xff1a; 输入&#xff1a;n 11 输出&#xff1a;3 解释&#x…

Vue前端环境搭建:从四个方面、五个方面、六个方面和七个方面深度解析

Vue前端环境搭建&#xff1a;从四个方面、五个方面、六个方面和七个方面深度解析 在构建Vue.js项目时&#xff0c;搭建一个稳定且高效的前端环境至关重要。这不仅关乎项目的顺利推进&#xff0c;更直接影响开发者的效率和代码质量。本文将从四个方面、五个方面、六个方面和七个…