以下是一个完整的 Java Web 应用程序代码，满足您的需求，包括前端网页操作界面、后端登录系统、数据库连接，以及随机生成 4 位数字验证码的功能。

开发环境和依赖版本：

Java SE 8
Apache Tomcat 9.0
MySQL 5.7
JDBC 驱动程序：mysql-connector-java-8.0.27.jar
密码哈希库：jbcrypt-0.4.jar
前端：HTML5、JavaScript
数据库设置
1. 创建数据库和用户表

使用以下 SQL 脚本在 MySQL 中创建数据库和用户表：


-- MySQL 版本：5.7

CREATE DATABASE login_system;

USE login_system;

CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50) NOT NULL UNIQUE,
    password_hash VARCHAR(255) NOT NULL
);
后端代码
2. 数据库工具类

DatabaseUtility.java - 用于获取数据库连接。


// DatabaseUtility.java

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class DatabaseUtility {
    // JDBC 驱动程序名称和数据库 URL
    static final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver";  
    static final String DB_URL = "jdbc:mysql://localhost:3306/login_system?useSSL=false&serverTimezone=UTC";

    // 数据库凭证
    static final String USER = "您的数据库用户名";
    static final String PASS = "您的数据库密码";

    public static Connection getConnection() throws SQLException, ClassNotFoundException {
        Class.forName(JDBC_DRIVER);
        return DriverManager.getConnection(DB_URL, USER, PASS);
    }
}
请将"您的数据库用户名"和"您的数据库密码"替换为您的实际数据库用户名和密码。

3. 用户数据访问对象

UserDAO.java - 包含用户注册和认证的方法。


// UserDAO.java

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class UserDAO {
    public boolean registerUser(String username, String passwordHash) {
        String sql = "INSERT INTO users (username, password_hash) VALUES (?, ?)";
        try (Connection conn = DatabaseUtility.getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setString(1, username);
            pstmt.setString(2, passwordHash);
            pstmt.executeUpdate();
            return true;
        } catch (SQLException | ClassNotFoundException e) {
            // 处理异常（例如，用户名已存在）
            e.printStackTrace();
            return false;
        }
    }

    public boolean authenticateUser(String username, String password) {
        String sql = "SELECT password_hash FROM users WHERE username = ?";
        try (Connection conn = DatabaseUtility.getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setString(1, username);
            try (ResultSet rs = pstmt.executeQuery()) {
                if (rs.next()) {
                    String storedHash = rs.getString("password_hash");
                    return PasswordUtil.verifyPassword(password, storedHash);
                } else {
                    // 用户不存在
                    return false;
                }
            }
        } catch (SQLException | ClassNotFoundException e) {
            // 处理异常
            e.printStackTrace();
            return false;
        }
    }
}
4. 密码工具类

PasswordUtil.java - 用于密码的哈希和验证，使用 BCrypt。


// PasswordUtil.java

import org.mindrot.jbcrypt.BCrypt;

public class PasswordUtil {
    public static String hashPassword(String plainTextPassword){
        return BCrypt.hashpw(plainTextPassword, BCrypt.gensalt());
    }

    public static boolean verifyPassword(String plainTextPassword, String hashedPassword){
        return BCrypt.checkpw(plainTextPassword, hashedPassword);
    }
}
依赖库：

请下载 jbcrypt-0.4.jar 并将其添加到项目的类路径中。

5. 注册 Servlet

RegistrationServlet.java - 处理用户注册请求。


// RegistrationServlet.java

import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.*;

public class RegistrationServlet extends HttpServlet {

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 获取表单参数
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String captchaInput = request.getParameter("captcha");

        // 从会话中获取验证码
        HttpSession session = request.getSession();
        String captchaValue = (String) session.getAttribute("captcha");
        
        if(captchaValue != null && captchaValue.equals(captchaInput)){
            // 对密码进行哈希
            String passwordHash = PasswordUtil.hashPassword(password);

            // 注册用户
            UserDAO userDAO = new UserDAO();
            if(userDAO.registerUser(username, passwordHash)){
                // 注册成功
                response.sendRedirect("login.jsp");
            } else {
                // 注册失败（例如，用户名已存在）
                request.setAttribute("errorMessage", "注册失败：用户名可能已存在。");
                RequestDispatcher dispatcher = request.getRequestDispatcher("register.jsp");
                dispatcher.forward(request, response);
            }
        } else {
            // 验证码不正确
            request.setAttribute("errorMessage", "验证码不正确。");
            RequestDispatcher dispatcher = request.getRequestDispatcher("register.jsp");
            dispatcher.forward(request, response);
        }
    }
}
6. 登录 Servlet

LoginServlet.java - 处理用户登录请求。


// LoginServlet.java

import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.*;

public class LoginServlet extends HttpServlet {

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 获取表单参数
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String captchaInput = request.getParameter("captcha");

        // 从会话中获取验证码
        HttpSession session = request.getSession();
        String captchaValue = (String) session.getAttribute("captcha");
        
        if(captchaValue != null && captchaValue.equals(captchaInput)){
            // 验证用户
            UserDAO userDAO = new UserDAO();
            if(userDAO.authenticateUser(username, password)){
                // 登录成功
                session.setAttribute("user", username);
                response.sendRedirect("welcome.jsp");
            } else {
                // 登录失败
                request.setAttribute("errorMessage", "用户名或密码错误。");
                RequestDispatcher dispatcher = request.getRequestDispatcher("login.jsp");
                dispatcher.forward(request, response);
            }
        } else {
            // 验证码不正确
            request.setAttribute("errorMessage", "验证码不正确。");
            RequestDispatcher dispatcher = request.getRequestDispatcher("login.jsp");
            dispatcher.forward(request, response);
        }
    }
}
7. web.xml 配置

配置 Servlet 映射：


<!-- web.xml -->

<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_3_1.xsd" 
         version="3.1">

    <!-- 注册 Servlet -->
    <servlet>
        <servlet-name>RegistrationServlet</servlet-name>
        <servlet-class>RegistrationServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>RegistrationServlet</servlet-name>
        <url-pattern>/registerAction</url-pattern>
    </servlet-mapping>

    <!-- 登录 Servlet -->
    <servlet>
        <servlet-name>LoginServlet</servlet-name>
        <servlet-class>LoginServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>LoginServlet</servlet-name>
        <url-pattern>/loginAction</url-pattern>
    </servlet-mapping>

</web-app>
前端代码
8. 注册页面

register.jsp - 包含用户名、密码、验证码输入框和注册按钮。


<!-- register.jsp -->

<%@ page import="java.util.Random" %>
<%
    // 生成 4 位随机验证码
    Random rand = new Random();
    String captchaValue = String.format("%04d", rand.nextInt(10000));
    session.setAttribute("captcha", captchaValue);
%>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>注册</title>
</head>
<body>
    <h2>注册</h2>
    <form action="registerAction" method="post">
        <p>
            用户名：<input type="text" name="username" required>
        </p>
        <p>
            密码：<input type="password" name="password" required>
        </p>
        <p>
            验证码：<%= captchaValue %><br>
            输入验证码：<input type="text" name="captcha" required>
        </p>
        <% String errorMessage = (String) request.getAttribute("errorMessage");
           if(errorMessage != null){ %>
            <p style="color:red;"><%= errorMessage %></p>
        <% } %>
        <p>
            <input type="submit" value="注册">
        </p>
    </form>
    <p><a href="login.jsp">已有账户？点击登录。</a></p>
</body>
</html>
9. 登录页面

login.jsp - 包含用户名、密码、验证码输入框和登录按钮。


<!-- login.jsp -->

<%@ page import="java.util.Random" %>
<%
    // 生成 4 位随机验证码
    Random rand = new Random();
    String captchaValue = String.format("%04d", rand.nextInt(10000));
    session.setAttribute("captcha", captchaValue);
%>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>登录</title>
</head>
<body>
    <h2>登录</h2>
    <form action="loginAction" method="post">
        <p>
            用户名：<input type="text" name="username" required>
        </p>
        <p>
            密码：<input type="password" name="password" required>
        </p>
        <p>
            验证码：<%= captchaValue %><br>
            输入验证码：<input type="text" name="captcha" required>
        </p>
        <% String errorMessage = (String) request.getAttribute("errorMessage");
           if(errorMessage != null){ %>
            <p style="color:red;"><%= errorMessage %></p>
        <% } %>
        <p>
            <input type="submit" value="登录">
        </p>
    </form>
    <p><a href="register.jsp">没有账户？点击注册。</a></p>
</body>
</html>
10. 欢迎页面

welcome.jsp - 登录成功后的欢迎页面。


<!-- welcome.jsp -->

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>欢迎</title>
</head>
<body>
    <%
        String username = (String) session.getAttribute("user");
        if(username != null){ %>
            <h2>欢迎，<%= username %>！</h2>
    <% } else { %>
            <h2>您尚未登录。</h2>
            <p><a href="login.jsp">点击登录</a></p>
    <% } %>
</body>
</html>
注意事项
安全性： 此示例为了演示简单的登录注册功能，验证码直接以明文方式显示，实际应用中应使用图片验证码或更安全的验证码机制。
密码保存： 使用 BCrypt 对密码进行哈希，防止明文密码泄露。
防范 SQL 注入： 使用 PreparedStatement 预编译 SQL 语句，防止 SQL 注入攻击。
依赖库配置： 确保将 mysql-connector-java-8.0.27.jar 和 jbcrypt-0.4.jar 添加到项目的类路径中。
对上述内容进行详细注解,我需要的是一个门外汉都能看懂的标注