我们将使用 Maven 来管理项目依赖,这是目前 Java 项目的标准做法。

用java web编写注册网页
(图片来源网络,侵删)

项目结构

一个标准的 Maven Java Web 项目结构如下:

registration-webapp/
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── com/
│   │   │       └── example/
│   │   │           └── controller/
│   │   │               └── RegisterServlet.java      // 处理注册请求的Servlet
│   │   │           └── model/
│   │   │               └── User.java                // 用户实体类
│   │   │           └── util/
│   │   │               └── DBUtil.java               // 数据库连接工具类
│   │   ├── resources/
│   │   │   └── db.properties                         // 数据库配置文件
│   │   └── webapp/
│   │       ├── WEB-INF/
│   │       │   └── web.xml                          // 部署描述符
│   │       ├── register.html                        // 注册页面
│   │       └── welcome.jsp                          // 注册成功后的欢迎页面
│   └── test/
│       └── java/
├── pom.xml                                           // Maven 项目配置文件

第1步:准备数据库

你需要一个 MySQL 数据库,如果没有,请先安装并启动 MySQL 服务。

  1. 创建一个数据库:

    CREATE DATABASE javaweb_demo;
  2. javaweb_demo 数据库中创建一个 users 表:

    用java web编写注册网页
    (图片来源网络,侵删)
    USE javaweb_demo;
    CREATE TABLE users (
        id INT PRIMARY KEY AUTO_INCREMENT,
        username VARCHAR(50) NOT NULL UNIQUE,
        password VARCHAR(100) NOT NULL,
        email VARCHAR(100) NOT NULL UNIQUE,
        registration_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    );
    • id:主键,自增。
    • username:用户名,必须唯一。
    • password:密码,我们将在后端进行加密存储。
    • email:邮箱,也必须唯一。

第2步:创建 Maven Web 项目

在你的 IDE(如 IntelliJ IDEA 或 Eclipse)中,创建一个新的 Maven 项目,并选择 maven-archetype-webapp 模板。


第3步:配置 pom.xml

pom.xml 文件中,添加项目所需的依赖:

  1. Servlet API: 用于编写后端控制器。
  2. JSP API: 用于支持 JSP 页面。
  3. JSTL (JSP Standard Tag Library): 用于在 JSP 中简化逻辑判断和循环。
  4. MySQL Connector/J: 用于 Java 连接 MySQL 数据库。
  5. BCrypt: 一个安全的密码哈希库,用于加密用户密码。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>registration-webapp</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>
    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <!-- Servlet API -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>
        <!-- JSP API -->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.3</version>
            <scope>provided</scope>
        </dependency>
        <!-- JSTL -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <!-- MySQL Connector -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.28</version>
        </dependency>
        <!-- BCrypt for password hashing -->
        <dependency>
            <groupId>org.mindrot</groupId>
            <artifactId>jbcrypt</artifactId>
            <version>0.4</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.3.2</version>
            </plugin>
        </plugins>
    </build>
</project>

第4步:编写后端代码

数据库配置 (src/main/resources/db.properties)

创建一个文件来存储数据库连接信息,方便日后修改。

# Database Connection Properties
db.driver=com.mysql.cj.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/javaweb_demo?useSSL=false&serverTimezone=UTC
db.username=root
db.password=your_password # 替换成你的MySQL root密码

数据库工具类 (src/main/java/com/example/util/DBUtil.java)

这个类负责从配置文件中读取信息并创建数据库连接。

用java web编写注册网页
(图片来源网络,侵删)
package com.example.util;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
public class DBUtil {
    private static Properties props = new Properties();
    private static String DRIVER;
    private static String URL;
    private static String USERNAME;
    private static String PASSWORD;
    static {
        try (InputStream is = DBUtil.class.getClassLoader().getResourceAsStream("db.properties")) {
            if (is == null) {
                throw new RuntimeException("db.properties not found!");
            }
            props.load(is);
            DRIVER = props.getProperty("db.driver");
            URL = props.getProperty("db.url");
            USERNAME = props.getProperty("db.username");
            PASSWORD = props.getProperty("db.password");
            Class.forName(DRIVER);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
            throw new RuntimeException("Failed to load database properties or driver.", e);
        }
    }
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(URL, USERNAME, PASSWORD);
    }
}

用户实体类 (src/main/java/com/example/model/User.java)

这是一个简单的 Java Bean,用于封装用户数据。

package com.example.model;
public class User {
    private int id;
    private String username;
    private String password; // 存储的是哈希后的密码
    private String email;
    // Getters and Setters
    public int getId() { return id; }
    public void setId(int id) { this.id = id; }
    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 getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
}

注册控制器 (src/main/java/com/example/controller/RegisterServlet.java)

这是整个应用的核心,它接收前端的注册请求,处理数据,并与数据库交互。

package com.example.controller;
import com.example.model.User;
import com.example.util.DBUtil;
import org.mindrot.jbcrypt.BCrypt;
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.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
@WebServlet("/register") // URL 映射
public class RegisterServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 1. 获取前端表单数据
        String username = req.getParameter("username");
        String plainPassword = req.getParameter("password");
        String email = req.getParameter("email");
        // 2. 数据验证 (简单示例,实际应用中需要更复杂的验证)
        if (username == null || username.isEmpty() || plainPassword == null || plainPassword.isEmpty() || email == null || email.isEmpty()) {
            req.setAttribute("error", "所有字段都必须填写!");
            req.getRequestDispatcher("register.html").forward(req, resp);
            return;
        }
        // 3. 使用 BCrypt 加密密码
        String hashedPassword = BCrypt.hashpw(plainPassword, BCrypt.gensalt());
        // 4. 创建 User 对象
        User user = new User();
        user.setUsername(username);
        user.setPassword(hashedPassword);
        user.setEmail(email);
        // 5. 保存到数据库
        Connection conn = null;
        PreparedStatement pstmt = null;
        try {
            conn = DBUtil.getConnection();
            String sql = "INSERT INTO users (username, password, email) VALUES (?, ?, ?)";
            pstmt = conn.prepareStatement(sql);
            pstmt.setString(1, user.getUsername());
            pstmt.setString(2, user.getPassword());
            pstmt.setString(3, user.getEmail());
            int rowsAffected = pstmt.executeUpdate();
            if (rowsAffected > 0) {
                // 注册成功,重定向到欢迎页面
                resp.sendRedirect(req.getContextPath() + "/welcome.jsp?username=" + user.getUsername());
            } else {
                // 注册失败
                req.setAttribute("error", "注册失败,请稍后重试。");
                req.getRequestDispatcher("register.html").forward(req, resp);
            }
        } catch (SQLException e) {
            e.printStackTrace();
            // 处理用户名或邮箱已存在的情况
            if (e.getErrorCode() == 1062) { // MySQL 唯一约束冲突的错误码
                req.setAttribute("error", "用户名或邮箱已被注册!");
            } else {
                req.setAttribute("error", "数据库错误,请联系管理员。");
            }
            req.getRequestDispatcher("register.html").forward(req, resp);
        } finally {
            // 6. 关闭资源
            try {
                if (pstmt != null) pstmt.close();
                if (conn != null) conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

第5步:编写前端页面

注册页面 (src/main/webapp/register.html)

这是一个简单的 HTML 表单,action 指向我们的 RegisterServlet

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">用户注册</title>
    <style>
        body { font-family: Arial, sans-serif; background-color: #f4f4f4; margin: 0; padding: 20px; }
        .container { max-width: 400px; margin: auto; background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
        h2 { text-align: center; color: #333; }
        label { display: block; margin-bottom: 8px; }
        input[type="text"], input[type="password"], input[type="email"] {
            width: 100%;
            padding: 10px;
            margin-bottom: 20px;
            border: 1px solid #ddd;
            border-radius: 4px;
            box-sizing: border-box; /* Important for padding and width */
        }
        button {
            width: 100%;
            padding: 10px;
            background-color: #5cb85c;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 16px;
        }
        button:hover { background-color: #4cae4c; }
        .error-message { color: #d9534f; margin-bottom: 15px; text-align: center; }
    </style>
</head>
<body>
    <div class="container">
        <h2>创建新账户</h2>
        <%-- 使用 JSTL 显示错误信息 --%>
        <%-- @ 表示这是一个 JSP 指令,用于引入 JSTL 核心标签库 --%>
        <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
        <c:if test="${not empty error}">
            <div class="error-message">
                ${error}
            </div>
        </c:if>
        <form action="${pageContext.request.contextPath}/register" method="post">
            <label for="username">用户名:</label>
            <input type="text" id="username" name="username" required>
            <label for="email">电子邮箱:</label>
            <input type="email" id="email" name="email" required>
            <label for="password">密码:</label>
            <input type="password" id="password" name="password" required>
            <button type="submit">注册</button>
        </form>
    </div>
</body>
</html>

欢迎页面 (src/main/webapp/welcome.jsp)

注册成功后,用户会被重定向到这个页面。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>注册成功</title>
    <style>
        body { font-family: Arial, sans-serif; background-color: #f4f4f4; margin: 0; padding: 20px; text-align: center; }
        .container { max-width: 400px; margin: auto; background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
        h2 { color: #5cb85c; }
    </style>
</head>
<body>
    <div class="container">
        <h2>注册成功!</h2>
        <p>欢迎您,<strong>${param.username}</strong>!</p>
        <p>您已成功创建账户。</p>
    </div>
</body>
</html>

第6步:配置 web.xml

虽然我们使用了 @WebServlet 注解,但为了完整性,也可以在 web.xml 中进行配置,对于现代项目,注解方式更常用。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <display-name>Registration WebApp</display-name>
    <!-- 如果不使用 @WebServlet 注解,可以在这里配置 Servlet -->
    <!--
    <servlet>
        <servlet-name>RegisterServlet</servlet-name>
        <servlet-class>com.example.controller.RegisterServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>RegisterServlet</servlet-name>
        <url-pattern>/register</url-pattern>
    </servlet-mapping>
    -->
    <welcome-file-list>
        <welcome-file>register.html</welcome-file>
    </welcome-file-list>
</web-app>

第7步:部署和运行

  1. 配置数据库:确保 db.properties 文件中的数据库连接信息(尤其是密码)是正确的。
  2. 打包项目:在项目根目录下运行 mvn clean package 命令,这会在 target 目录下生成一个 .war 文件(registration-webapp-1.0-SNAPSHOT.war)。
  3. 部署到服务器
    • Tomcat: 将生成的 .war 文件复制到你的 Tomcat 服务器的 webapps 目录下。
    • 启动 Tomcat 服务器。
  4. 访问:在浏览器中访问 http://localhost:8080/registration-webapp/register.html (端口号和路径可能根据你的 Tomcat 配置和项目名有所不同)。

你应该能看到一个注册页面,填写信息并提交,如果一切正常,数据将被存入数据库,并且页面会跳转到欢迎页面。


总结与扩展

这个例子涵盖了 Java Web 开发的基础流程:

  • MVC 模式User.java 是 Model (模型),register.html 是 View (视图),RegisterServlet 是 Controller (控制器)。
  • 请求-响应:浏览器发送请求,Servlet 处理并返回响应。
  • 数据持久化:通过 JDBC 将数据保存到 MySQL 数据库。
  • 安全性:使用 BCrypt 对密码进行哈希处理,而不是明文存储。

可以进一步扩展的功能:

  • 登录功能:创建一个 LoginServlet,验证用户提交的用户名和密码(与数据库中的哈希值比对)。
  • 会话管理:使用 HttpSession 来跟踪已登录的用户。
  • 输入验证:在前端(JavaScript)和后端(Java)都进行更严格的输入验证(如密码强度、邮箱格式等)。
  • 分页和查询:在用户表中添加更多功能,如分页显示所有用户。
  • 使用框架:对于更复杂的项目,可以考虑使用 Spring Boot 或 Jakarta EE (Jakarta EE) 等现代框架,它们能大大简化开发流程。