JavaWeb-03-Servlet-07-在线考试管理系统

JavaWeb-03-Servlet-07-在线考试管理系统-用户信息管理模块

试题信息管理传送门:试题信息管理
考试管理模块传送门:考试管理

本次项目文件:点击下载
提取码:922w

1.目标

用户信息管理模块

2.功能实现

  1. 用户信息注册
  2. 用户信息查询
  3. 用户信息删除
  4. 用户信息更新
  5. 用户登录验证

3.准备工作

3.1创建用户信息表(t_users.frm)

drop table if exists t_users;
create table t_users (
    userId int primary key auto_increment,#用户编号,设置为自增
    userName varchar(255),      #用户名
    passWord varchar(255),      #用户密码
    sex char(1),                #用户性别'男'or'女'
    age int,                    #用户年龄
    email varchar(255) unique   #用户邮箱,设置为唯一不可重复
);
insert into t_users(userName,passWord,sex,age,email) value('张三','111','男',20,'zhangsan@qq.com');
insert into t_users(userName,passWord,sex,age,email) value('李四','222','女',21,'lisi@qq.com');
commit;
select * from t_users;

导入数据库中:

3.2创建用户信息表对应实体类Users

在src下,创建com.tsccg.entity.Users实体类

package com.tsccg.entity;

import org.omg.PortableInterceptor.INACTIVE;

/**
 * @Author: TSCCG
 * @Date: 2021/08/14 15:18
 * 用户信息表对应的实体类
 */
public class Users {
    private Integer userId;
    private String userName;
    private String passWord;
    private String sex;
    private Integer age;
    private String email;

    /**
     * 无参构造
     */
    public Users() {
    }

    /**
     * 有参构造
     * @param userId 用户编号
     * @param userName 用户名
     * @param passWord 用户密码
     * @param sex 用户性别'男'or'女'
     * @param age 用户年龄
     * @param email 用户邮箱
     */
    public Users(Integer userId, String userName, String passWord, String sex, Integer age, String email) {
        this.userId = userId;
        this.userName = userName;
        this.passWord = passWord;
        this.sex = sex;
        this.age = age;
        this.email = email;
    }

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    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 getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

3.3编写JDBC工具类

在/web/WEB-INF目录下,创建一个文件夹,命名为lib,将MySQL驱动放进去。

在src下,创建一个配置文件JDBC.properties。把驱动名、数据库等信息都放到里面。

driverName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/db_user
user=root
password=123456

在src下,创建com.tsccg.util.JdbcUtil工具类。

使用资源绑定器获取相关信息。

package com.tsccg.util;

import java.sql.*;
import java.util.ResourceBundle;

/**
 * @Author: TSCCG
 * @Date: 2021/08/14 15:32
 * JDBC工具类
 * 1.注册驱动*
 * 2.获取连接*
 * 3.获取预编译的数据库操作对象
 * 4.执行sql
 * 5.处理查询结果集
 * 6.关闭资源*
 */
public class JdbcUtil {
    /**
     * 创建资源绑定器对象
     */
    private static final ResourceBundle BUNDLE = ResourceBundle.getBundle("JDBC");
    //1.注册驱动
    static {
        try {
            Class.forName(BUNDLE.getString("driverName"));
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    /**
     * 2.获取连接
     * @return 返回连接对象
     * @throws SQLException 将SQLException异常上抛
     */
    public static Connection connect() throws SQLException {
        return DriverManager.getConnection(BUNDLE.getString("url"),
                BUNDLE.getString("user"),BUNDLE.getString("password"));
    }
    /**
     * 6.释放资源
     * @param conn 连接对象
     * @param stmt 数据库操作对象
     * @param rs 查询结果集对象
     */
    public static void closeAll(Connection conn, Statement stmt, ResultSet rs) {
        if(rs != null) {
            try {
                rs.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if(stmt != null) {
            try {
                stmt.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }

        if(conn != null) {
            try {
                conn.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}

4.导航页面

在从浏览器向服务器发送请求时,需要发送各种地址,为了方便用户操作,需要一个导航页面。

在/web目录下新建一个html文件,命名为index.html

<html>
<head>
    <meta charset="UTF-8">
    <title>导航栏</title>
</head>
<frameset rows="15%,85%">
    <frame name="top" src="/MyWeb/top.html" />
    <frameset cols="15%,85%">
        <frame name="left" src="/MyWeb/left.html"/>
        <frame name="right"/>
    </frameset>
</frameset>

</html>

在/web目录下新建top.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>top</title>
</head>
<body style="background-color: #00fff6">
    <h1 align="center" style="color: #ff0000">在线考试管理系统</h1>
</body>
</html>

在/web目录下新建left.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>left</title>
</head>
<body>
    <ul>
        <li>用户信息管理
            <ol>
                <li><a href="/MyWeb/user_add.html" target="right">用户信息注册</a></li>
                <li><a href="/MyWeb/user/find" target="right">用户信息查询</a></li>
            </ol>
        </li>
        <li>试题信息管理</li>
        <li>考试管理</li>
    </ul>
</body>
</html>

5.用户信息注册

5.1用户信息注册流程图

5.2创建前台页面

HTML文件属于静态资源文件,需要放在/web目录下。

在/web目录下新建user_add.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用户注册</title>
</head>
<body>
<form action="http://localhost:8080/MyWeb/user/add" method="GET" id="form">
    <h2 align="center">用户注册</h2>
    <table align="center">
        <!-- 用户名  -->
        <tr>
            <td>用户名:</td>
            <td><input type="text" name="userName"></td>
        </tr>
        <!-- 密码  -->
        <tr>
            <td>密码:</td>
            <td><input type="password" name="passWord"></td>
        </tr>
        <!-- 性别  -->   
        <tr>
            <td>性别:</td>
            <td>
                <label>
                    <input type="radio" name="sex" value="男" checked="checked">男
                </label> 
                <label>
                    <input type="radio" name="sex" value="女">女
                </label>
            </td>
        </tr>
        <!-- 年龄  -->   
        <tr>
            <td>年龄:</td>
            <td><input type="text" name="age"></td>
        </tr>
        <!-- 邮箱地址  -->   
        <tr>
            <td>邮箱地址:</td>
            <td><input type="text" name="email"></td>
        </tr>
        <!-- 提交  -->
        <tr>
            <td><input type="submit" value="提交"></td>
            <td><input type="reset" value="重置"></td>
        </tr>
    </table>
</form>
</body>
</html>

5.3编写JDBC类【UserDao】

这个类的主要作用就是连接数据库,对数据库中的数据进行增删查改。

这里先实现【添加】功能,将用户信息写入数据库中。

package com.tsccg.com.tsccg.dao;

import com.tsccg.entity.Users;
import com.tsccg.util.JdbcUtil;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

/**
 * @Author: TSCCG
 * @Date: 2021/08/14 21:07
 */
public class UserDao {
    /**
     * 向数据库中添加用户信息
     * @param users 用户信息表对应实体类
     * @return 返回
     */
    public boolean add(Users users) {
        Connection conn = null;
        PreparedStatement ps = null;
        boolean result = false;
        try {
            //注册、获取连接对象
            conn = JdbcUtil.connect();
            //获取预编译的数据库操作对象
            String sql = "insert into t_users(userName,passWord,sex,age,email) " +
                    "value(?,?,?,?,?)";
            ps = conn.prepareStatement(sql);
            ps.setString(1,users.getUserName());
            ps.setString(2,users.getPassWord());
            ps.setString(3,users.getSex());
            ps.setInt(4,users.getAge());
            ps.setString(5,users.getEmail());
            if(ps.executeUpdate() > 0) {
                result = true;
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            JdbcUtil.closeAll(conn,ps,null);
        }
        return result;
    }
}

5.4编写Servlet接口实现类【UserAddServlet】

这个类的主要作用有三个:

  1. 调用【请求对象】读取请求头/请求体中的请求参数信息,也就是用户输入的信息
  2. 调用【UserDao】将用户信息放入insert命令,并借助JDBC规范发送到数据库服务器
  3. 调用【响应对象】将【处理结果】以二进制形式写入响应体中
package com.tsccg.controller;

import com.tsccg.com.tsccg.dao.UserDao;
import com.tsccg.entity.Users;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * @Author: TSCCG
 * @Date: 2021/08/14 20:11
 */
public class UserAddServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //通知请求对象,使用utf-8字符集对请求体内的二进制内容进行一次重新解码
        request.setCharacterEncoding("utf-8");
        insert(request,response);
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        insert(request,response);
    }

    private static void insert(HttpServletRequest request, HttpServletResponse response) throws IOException {
        //1.调用【请求对象】读取【请求头】中的请求参数信息,得到用户的信息
        String userName,passWord,sex,age,email;
        UserDao dao = null;
        Users users = null;
        PrintWriter out = null;
        userName = request.getParameter("userName");
        passWord = request.getParameter("passWord");
        sex = request.getParameter("sex");
        age = request.getParameter("age");
        email = request.getParameter("email");
        //2.调用【UserDao】将用户信息放入insert命令,并借助JDBC规范发送到数据库服务器
        dao = new UserDao();
        users = new Users(null,userName,passWord,sex,Integer.valueOf(age),email);
        boolean result = dao.add(users);
        //3.调用【响应对象】将【处理结果】以二进制形式写入响应体中
        response.setContentType("text/html;charset=utf-8");
        out = response.getWriter();
        out.print(result ? "<font style='color: green;font-size: 30px'>注册成功</font>"
                : "<font style='color: red;font-size: 30px'>注册失败</font>");
    }
}

5.5注册功能测试

发布网站,开启服务器。

如果用户信息成功写入数据库,则显示【注册成功】,反之显示【注册失败】。

6.用户信息查询

6.1用户信息查询流程图

6.2在【UserDao】类中添加查询功能

package com.tsccg.com.tsccg.dao;

import com.tsccg.entity.Users;
import com.tsccg.util.JdbcUtil;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author: TSCCG
 * @Date: 2021/08/14 21:07
 */
public class UserDao {
    /**
     * 向数据库中添加用户信息
     * @param users 用户信息表对应实体类
     * @return 返回
     */
    public boolean add(Users users) {...}

    /**
     * 查询所有用户信息
     * @return List<Users> 存放User对象的List集合
     */
    public List<Users> findAll() {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        //创建一个Users对象,用于存储单条用户记录
        Users users = null;
        //创建一个List集合,用于存储Users对象
        List<Users> userList = new ArrayList<>();
        try {
            conn = JdbcUtil.connect();
            String sql = "select * from t_users";
            ps = conn.prepareStatement(sql);
            rs = ps.executeQuery();
            //遍历查询结果集
            while(rs.next()) {
                //获取查询结果集中单条记录中的用户信息
                Integer userId = rs.getInt("userId");
                String userName = rs.getString("userName");
                String passWord = rs.getString("passWord");
                String sex = rs.getString("sex");
                Integer age = rs.getInt("age");
                String email = rs.getString("email");
                //将单条用户记录放入User对象中
                users = new Users(userId,userName,passWord,sex,age,email);
                //将Users对象添加到List集合中
                userList.add(users);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //释放资源
            JdbcUtil.closeAll(conn,ps,rs);
        }
        //将存储用户信息的List集合对象返回
        return userList;
    }
}

6.3编写Servlet接口实现类【UserFindServlet】

这个类的作用主要有两个:

  1. 调用【UserDao】类将查询命令发送到数据库服务器上,得到所有的用户信息【List】
  2. 调用【响应对象】将用户信息结合< table>标签命令以二进制形式写入响应体中。
package com.tsccg.controller;

import com.tsccg.com.tsccg.dao.UserDao;
import com.tsccg.entity.Users;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

/**
 * @Author: TSCCG
 * @Date: 2021/08/15 16:52
 */
public class UserFindServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        UserDao dao = new UserDao();
        List<Users> usersList = null;
        PrintWriter out = null;
        //1. 调用【UserDao】类将查询命令发送到数据库服务器上,得到所有的用户信息【List】
        usersList = dao.findAll();
        //2. 调用【响应对象】将用户信息结合< table>标签命令以二进制形式写入响应体中。
        //在获取输出流前,通过响应对象设置浏览器解析响应体内容的方式以及字符集
        response.setContentType("text/html;charset=utf-8");
        //通过响应对象向Tomcat服务器借用输出流
        out = response.getWriter();
        /*
        <table border="1" align="center" cellspacing="0" cellpadding="0">
            <!-- 标题行 -->
            <tr>
                <th>用户编号</th>
                <th>用户姓名</th>
                <th>用户密码</th>
                <th>用户性别</th>
                <th>用户年龄</th>
                <th>用户邮箱</th>
            </tr>
            <!-- 数据行 -->
            <tr>
                <th>1</th>
                <th>张三</th>
                <th>111</th>
                <th>男</th>
                <th>20</th>
                <th>zhangsan@qq.com</th>
            </tr>
        </table>
         */
        //写入响应体
        out.print("<table border='1' align='center' cellspacing='0' cellpadding='0'>");
        //标题行
        out.print("<tr>");
        out.print("<th>用户编号</th>");
        out.print("<th>用户姓名</th>");
        out.print("<th>用户密码</th>");
        out.print("<th>用户性别</th>");
        out.print("<th>用户年龄</th>");
        out.print("<th>用户邮箱</th>");
        out.print("</tr>");
        //数据行
        for (Users users : usersList) {
            out.print("<tr>");
            out.print("<td>" + users.getUserId() + "</td>");
            out.print("<td>" + users.getUserName() + "</td>");
            out.print("<td>" + users.getPassWord() + "</td>");
            out.print("<td>" + users.getSex() + "</td>");
            out.print("<td>" + users.getAge() + "</td>");
            out.print("<td>" + users.getEmail() + "</td>");
            out.print("</tr>");
        }
        out.print("</table>");
    }
}

6.4查询功能测试

7.用户信息删除

7.1添加删除列

在查询出的用户信息表中额外添加一列,用于删除用户信息。

在UserFindServlet类里,在发送回浏览器的用户信息表的【标题行】内添加一个【操作】列,在【数据行】内添加【删除用户】列。

【删除用户】是一个超链接,点击发送请求:"/MyWeb/user/delete?userId=" + users.getUserId()

携带的参数是该行用户的用户编号。

out.print("<table border='1' align='center' cellspacing='0' cellpadding='0'>");
//标题行
out.print("<tr>");
out.print("<th>用户编号</th>");
out.print("<th>用户姓名</th>");
out.print("<th>用户密码</th>");
out.print("<th>用户性别</th>");
out.print("<th>用户年龄</th>");
out.print("<th>用户邮箱</th>");
out.print("<th>操作</th>");//修改1
out.print("</tr>");
//数据行
for (Users users : usersList) {
    out.print("<tr>");
    out.print("<td>" + users.getUserId() + "</td>");
    out.print("<td>" + users.getUserName() + "</td>");
    out.print("<td>" + users.getPassWord() + "</td>");
    out.print("<td>" + users.getSex() + "</td>");
    out.print("<td>" + users.getAge() + "</td>");
    out.print("<td>" + users.getEmail() + "</td>");
    out.print("<td><a href='/MyWeb/user/delete?userId="
            + users.getUserId() + "'>删除用户</a></td>");//修改2
    out.print("</tr>");
}
out.print("</table>");

7.2在【UserDao】类中添加删除功能

package com.tsccg.com.tsccg.dao;

import com.tsccg.entity.Users;
import com.tsccg.util.JdbcUtil;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author: TSCCG
 * @Date: 2021/08/14 21:07
 */
public class UserDao {
    /**
     * 向数据库中添加用户信息
     * @param users 用户信息表对应实体类
     * @return 返回处理结果,添加成功返回true,失败返回false
     */
    public boolean add(Users users) {...}

    /**
     * 查询所有用户信息
     * @return List<Users> 存放User对象的List集合
     */
    public List<Users> findAll() {...}

    /**
     * 删除用户信息
     * @param userId 用户编号
     * @return 返回处理结果,删除成功返回true,失败返回false
     */
    public boolean delete(String userId) {
        Connection conn = null;
        PreparedStatement ps = null;
        boolean result = false;
        try {
            conn = JdbcUtil.connect();
            String sql = "delete from t_users where userId = ?";
            ps = conn.prepareStatement(sql);
            ps.setInt(1,Integer.parseInt(userId));
            if(ps.executeUpdate() > 0) {
                result = true;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtil.closeAll(conn,ps,null);
        }
        return result;
    }
}

7.3编写Servlet接口实现类【UserDeleteServlet】

该类主要作用三个:

  1. 调用【请求对象】读取请求头中的请求参数信息,也就是【用户编号】
  2. 调用【UserDao】将【用户编号】插入delete命令,并借助JDBC规范发送到数据库服务器
  3. 调用【响应对象】将【处理结果】以二进制形式写入响应体中
package com.tsccg.controller;

import com.tsccg.com.tsccg.dao.UserDao;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * @Author: TSCCG
 * @Date: 2021/08/15 20:38
 */
public class UserDeleteServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 调用【请求对象】读取请求头中的请求参数信息,也就是【用户编号】
        String userId = request.getParameter("userId");
        //2. 调用【UserDao】将【用户编号】插入delete命令,并借助JDBC规范发送到数据库服务器
        UserDao dao = new UserDao();
        boolean result = dao.delete(userId);
        //3. 调用【响应对象】将【处理结果】以二进制形式写入响应体中
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.print(result ? "<font style='color: green;font-size: 30px'>删除用户成功</font>"
                :"<font style='color: red;font-size: 30px'>删除用户失败</font>");

    }
}

7.4删除功能测试

8.用户登录验证

8.1登录验证流程图

8.2编写登录页面

要求:

  1. 用户名
    1. 长度不得为空
    2. 长度不得大于10
  2. 密码
    1. 长度不得为空
    2. 长度不得小于3且不能大于20
  3. 所有信息都合法才能提交表单

在/web目录下新建login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
    <style type="text/css">
        h1 {
            font-size: 30px;
        }
        table {
            font-size: 20px;
            position: absolute;
            top: 100px;
            left: 600px;
        }
        span {
            font-size: 14px;
            color: red;
        }
    </style>
</head>
<body>
<h1 align="center">登录</h1>
<form action="/MyWeb/login" method="post" id="form">
    <table>
        <tr>
            <td>用户名:</td>
            <td><input type="text" name="userName" id="userName"/></td>
            <td><span id="userNameError"></span></td>
        </tr>
        <tr>
            <td>密 码:</td>
            <td><input type="password" name="passWord" id="passWord"/></td>
            <td><span id="passWordError"></span></td>
        </tr>
        <tr>
            <td>
                <input type="button" value="登录" id="subBtn"/>
            </td>
            <td>
                <input type="reset" value="重置"/>
            </td>
        </tr>
    </table>
</form>
<script type="text/javascript">
    window.onload = function() {
        /*
            1.检查用户名文本框
            用户名不为空;
            用户名长度不得超过10;
         */
        //获取用户名后面的span对象
        const userNameErrorElt = document.getElementById("userNameError");
        //获取用户名文本框对象
        const userNameElt = document.getElementById("userName");
        //当光标离开用户名文本框时检查value是否合法
        userNameElt.onblur = function() {
            //获取用户名文本框的value,并去除左右空白
            const userName = userNameElt.value.trim();
            if(userName.length === 0) {
                userNameErrorElt.innerText = "用户名不能为空!";
            } else if(userName.length > 10) {
                userNameErrorElt.innerText = "用户名长度不得大于10!";
            }
            clear(userNameElt,userNameErrorElt);
        }
        /*
            2.检查密码文本框
            密码不为空;
            密码长度不得超过20且不能小于3;
        */
        //获取用户名后面的span对象
        const passWordErrorElt = document.getElementById("passWordError");
        //获取用户名文本框对象
        const passWordElt = document.getElementById("passWord");
        //当光标离开用户名文本框时检查value是否合法
        passWordElt.onblur = function() {
            //获取用户名文本框的value,并去除左右空白
            const passWord = passWordElt.value.trim();
            if(passWord.length === 0) {
                passWordErrorElt.innerText = "密码不能为空!";
            } else if(passWord.length < 3 || passWord.length > 20) {
                passWordErrorElt.innerText = "密码长度为[3~20]!";
            }
            clear(passWordElt,passWordErrorElt);
        }
        /*
            3.当光标回到文本框内时,清空提示信息、不合法内容
            textElt:文本框对象
            errorElt:文本框后面的提示信息span对象
         */
        const clear = function(textElt,errorElt) {
            textElt.onfocus = function() {
                //如果文本框后面存在提示信息,则文本框内容不合法
                if(errorElt.innerText) {
                    //清空不合法内容
                    textElt.value = "";
                }
                //清空提示信息
                errorElt.innerText = "";
            }
        }
        /*
            4.当所有文本框里的内容都合法时,才能登录
         */
        //获取登录按钮对象
        const subBtnElt = document.getElementById("subBtn");
        subBtnElt.onclick = function() {
            //触发一次所有文本框的获得焦点、失去焦点事件
            userNameElt.focus();
            userNameElt.blur();
            passWordElt.focus();
            passWordElt.blur();
            //判断所有文本框后面是否有提示信息
            if (userNameErrorElt.innerText.length ===0
                && passWordErrorElt.innerText.length ===0) {
                //获取表单对象
                const formElt = document.getElementById("form");
                //提交表单
                formElt.submit();
            }
        }
    }
</script>
</body>
</html>

8.3编写登录失败页面

登录失败页面就是在登录页面的基础上,在上方添加一句:”登录失败,请重新登录“

在/web目录下,新建loginError.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
    <style type="text/css">
        h1 {
            font-size: 30px;
        }
        table {
            font-size: 20px;
            position: absolute;
            top: 100px;
            left: 600px;
        }
        span {
            font-size: 14px;
            color: red;
        }
        #loginError {
            font-size: 30px;
            color: red;

        }
    </style>
</head>
<body>
<div id="loginError" align="center">登录失败,请重新登录</div>
<h1 align="center">登录</h1>
<form action="/MyWeb/login" method="post" id="form">
    <table>
        <tr>
            <td>用户名:</td>
            <td><input type="text" name="userName" id="userName"/></td>
            <td><span id="userNameError"></span></td>
        </tr>
        <tr>
            <td>密 码:</td>
            <td><input type="password" name="passWord" id="passWord"/></td>
            <td><span id="passWordError"></span></td>
        </tr>
        <tr>
            <td>
                <input type="button" value="登录" id="subBtn"/>
            </td>
            <td>
                <input type="reset" value="重置"/>
            </td>
        </tr>
    </table>
</form>
<script type="text/javascript">
    window.onload = function() {
        /*
            1.检查用户名文本框
            用户名不为空;
            用户名长度不得超过10;
         */
        //获取用户名后面的span对象
        const userNameErrorElt = document.getElementById("userNameError");
        //获取用户名文本框对象
        const userNameElt = document.getElementById("userName");
        //当光标离开用户名文本框时检查value是否合法
        userNameElt.onblur = function() {
            //获取用户名文本框的value,并去除左右空白
            const userName = userNameElt.value.trim();
            if(userName.length === 0) {
                userNameErrorElt.innerText = "用户名不能为空!";
            } else if(userName.length > 10) {
                userNameErrorElt.innerText = "用户名长度不得大于10!";
            }
            clear(userNameElt,userNameErrorElt);
        }
        /*
            2.检查密码文本框
            密码不为空;
            密码长度不得超过20且不能小于3;
        */
        //获取用户名后面的span对象
        const passWordErrorElt = document.getElementById("passWordError");
        //获取用户名文本框对象
        const passWordElt = document.getElementById("passWord");
        //当光标离开用户名文本框时检查value是否合法
        passWordElt.onblur = function() {
            //获取用户名文本框的value,并去除左右空白
            const passWord = passWordElt.value.trim();
            if(passWord.length === 0) {
                passWordErrorElt.innerText = "密码不能为空!";
            } else if(passWord.length < 3 || passWord.length > 20) {
                passWordErrorElt.innerText = "密码长度为[3~20]!";
            }
            clear(passWordElt,passWordErrorElt);
        }
        /*
            3.当光标回到文本框内时,清空提示信息、不合法内容
            textElt:文本框对象
            errorElt:文本框后面的提示信息span对象
         */
        const clear = function(textElt,errorElt) {
            textElt.onfocus = function() {
                //如果文本框后面存在提示信息,则文本框内容不合法
                if(errorElt.innerText) {
                    //清空不合法内容
                    textElt.value = "";
                }
                //清空提示信息
                errorElt.innerText = "";
            }
        }
        /*
            4.当所有文本框里的内容都合法时,才能登录
         */
        //获取登录按钮对象
        const subBtnElt = document.getElementById("subBtn");
        subBtnElt.onclick = function() {
            //触发一次所有文本框的获得焦点、失去焦点事件
            userNameElt.focus();
            userNameElt.blur();
            passWordElt.focus();
            passWordElt.blur();
            //判断所有文本框后面是否有提示信息
            if (userNameErrorElt.innerText.length ===0
                && passWordErrorElt.innerText.length ===0) {
                //获取表单对象
                const formElt = document.getElementById("form");
                //提交表单
                formElt.submit();
            }
        }
    }
</script>
</body>
</html>

8.4在【UserDao】类中添加登录验证功能

package com.tsccg.com.tsccg.dao;

import com.tsccg.entity.Users;
import com.tsccg.util.JdbcUtil;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author: TSCCG
 * @Date: 2021/08/14 21:07
 */
public class UserDao {
    /**
     * 向数据库中添加用户信息
     * @param users 用户信息表对应实体类
     * @return 返回处理结果,添加成功返回true,失败返回false
     */
    public boolean add(Users users) {...}

    /**
     * 查询所有用户信息
     * @return List<Users> 存放User对象的List集合
     */
    public List<Users> findAll() {...}

    /**
     * 删除用户信息
     * @param userId 用户编号
     * @return 返回处理结果,删除成功返回true,失败返回false
     */
    public boolean delete(String userId) {...}

    /**
     * 验证用户信息
     * @param userName 用户名
     * @param passWord 用户密码
     * @return 返回验证结果,成功返回true,失败返回false
     */
    public boolean login(String userName,String passWord) {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        boolean result = false;
        try {
            conn = JdbcUtil.connect();
            String sql = "select * from t_users where userName=? and passWord=?";
            ps = conn.prepareStatement(sql);
            ps.setString(1,userName);
            ps.setString(2,passWord);
            //执行sql语句,得到查询结果集
            rs = ps.executeQuery();
            //如果查询到数据,那么说明验证成功
            if(rs.next()) {
                result = true;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtil.closeAll(conn,ps,rs);
        }
        return result;
    }
}

8.5编写Servlet接口实现类【LoginServlet】

1.告诉请求对象使用【utf-8】的方式对请求体中的内容进行重新编译
2.调用请求对象获取请求体中的【请求参数信息】
3.调用【UserDao】类将登录验证信息发送给数据库服务器
4.调用响应对象,根据验证结果,将不同【资源文件地址】写入响应头中的location属性,发送给浏览器

package com.tsccg.controller;

import com.tsccg.com.tsccg.dao.UserDao;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * @Author: TSCCG
 * @Date: 2021/08/15 23:51
 */
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.告诉请求对象使用【utf-8】的方式对请求体中的内容进行重新编译
        request.setCharacterEncoding("utf-8");
        //2.调用请求对象获取请求体中的【请求参数信息】
        String userName = request.getParameter("userName");
        String passWord = request.getParameter("passWord");
        //3.调用【UserDao】类将登录验证信息发送给数据库服务器
        UserDao dao = new UserDao();
        boolean result = dao.login(userName,passWord);
        //4.调用响应对象,根据验证结果,将不同【资源文件地址】写入响应头中的location属性,发送给浏览器
        if(result) {
            response.sendRedirect("/MyWeb/index.html");
        } else {
            response.sendRedirect("/MyWeb/loginError.html");
        }
    }
}

8.6验证登录验证功能

9.设置欢迎资源文件

当你想要打开百度时,可能会在浏览器地址栏里写上百度的默认网址【http://www.baidu.com】,但大概率不会加上百度网站下某个具体的资源文件名【https://www.baidu.com/index.html】。

用户会记住一个网站的名字,但通常不会记网站里的某个资源文件名。

正常请求:http://localhost:8080/MyWeb/index.html【请求访问index.html资源文件】

默认请求:http://localhost:8080/MyWeb【未说明想要访问的资源文件】

为了方便用户访问,当用户针对某一个网站发送了默认请求时,服务器会将网站中某一个【资源文件】发送过去。而这个默认的资源文件就叫做【欢迎资源文件】。

以Tomcat举例,

Tomcat对于默认欢迎资源文件定位规则:

  1. 规则设置位置:Tomcat安装位置/conf/web.xml
  2. 规则命令:
<welcome-file-list>
    <welcome-file>index.html</welcome-file><!-- 首选资源文件 -->
    <welcome-file>index.htm</welcome-file><!-- 次选资源文件 -->
    <welcome-file>index.jsp</welcome-file><!-- 前面的文件都没有找到,才选择这个资源文件 -->
    <!-- 如果上面的文件都没有找到,返回404状态码给浏览器 -->
</welcome-file-list>

我们在开发中,可以设定当前网站的默认欢迎文件规则:

  1. 设置位置:当前网站/web/WEB-INF/web.xml
  2. 规则命令:
<welcome-file-list>
    <welcome-file>login.html</welcome-file>
    <welcome-file>user/add</welcome-file><!-- 如果设置的是动态资源文件,前面不用加斜杠【/】 -->
</welcome-file-list>

开启服务器,默认打开当前项目的登录页面【login.html】:

posted @ 2021-08-14 22:44  TSCCG  阅读(1001)  评论(1编辑  收藏  举报