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; } @Override public 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; } @Override public 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; } @Override public 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; } @Override public 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) { //这里不能处理,否则找不到父类属性!!! } } /** * 设置对象属性 * @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 { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } @Override protected 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 { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } @Override protected 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 { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } @Override protected 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 { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } @Override protected 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: Gu Date: 2024-06-13 Time: 18:43 To 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 { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } @Override protected 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: Gu Date: 2024-06-13 Time: 18:43 To 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>