我们将使用当前最主流、最推荐的技术栈:

- Java Web: Jakarta EE (或 JEE) / Servlet
- 数据库: MySQL
- 数据库驱动: JDBC Driver
- 构建工具: Maven (强烈推荐,用于管理依赖)
- 连接池: HikariCP (目前性能最好的连接池)
第 1 步:环境准备
在开始之前,请确保你已经安装并配置好了以下软件:
- JDK (Java Development Kit): 版本 8 或更高版本。
- MySQL Server: 一个可运行的 MySQL 数据库实例。
- IDE: 如 IntelliJ IDEA, Eclipse 或 VS Code。
- Web 服务器: 如 Apache Tomcat (我们将使用它来部署和运行 Web 应用)。
- 构建工具: Maven (如果你的 IDE 集成了 Maven,可以跳过单独安装)。
第 2 步:创建数据库和用户
在你的 MySQL 服务器上创建一个数据库和一个专门用于 Web 应用的用户。
-
登录 MySQL
mysql -u root -p
-
创建数据库
(图片来源网络,侵删)CREATE DATABASE javaweb_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-
创建用户并授权
CREATE USER 'javaweb_user'@'localhost' IDENTIFIED BY 'your_strong_password'; GRANT ALL PRIVILEGES ON javaweb_db.* TO 'javaweb_user'@'localhost'; FLUSH PRIVILEGES;
javaweb_db: 你创建的数据库名。javaweb_user: 应用连接数据库的用户名。your_strong_password: 请替换为一个强密码。
第 3 步:创建 Java Web 项目并添加依赖
我们将使用 Maven 来创建项目并管理依赖。
-
创建 Maven Web 项目 在你的 IDE (如 IntelliJ IDEA) 中,选择 "New Project" -> "Maven" -> "maven-archetype-webapp",填写 GroupId 和 ArtifactId,然后创建项目。
-
添加 MySQL 和 HikariCP 依赖 打开
pom.xml文件,在<dependencies>标签内添加以下依赖:
(图片来源网络,侵删)<dependencies> <!-- Servlet API (Java Web 核心) --> <dependency> <groupId>jakarta.platform</groupId> <artifactId>jakarta.jakartaee-web-api</artifactId> <version>10.0.0</version> <scope>provided</scope> <!-- 由 Tomcat 提供,无需打包 --> </dependency> <!-- MySQL JDBC 驱动 --> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <version>8.0.33</version> <!-- 建议使用较新版本 --> </dependency> <!-- HikariCP 连接池 --> <dependency> <groupId>com.zaxxer</groupId> <artifactId>HikariCP</artifactId> <version>5.0.1</version> <!-- 建议使用较新版本 --> </dependency> </dependencies>- 注意: 如果你使用的是旧版的 Java EE (
javax.servlet), 请将jakarta.platform替换为javax.servlet。 - 添加后,IDE 会自动下载这些依赖库。
- 注意: 如果你使用的是旧版的 Java EE (
第 4 步:配置数据库连接信息
最佳实践:不要将数据库密码等敏感信息硬编码在 Java 代码中。 我们应该使用一个外部的配置文件。
-
创建配置文件 在
src/main/resources目录下创建一个文件,命名为db.properties。src/main/resources/db.properties:# 数据库连接信息 db.driverClassName=com.mysql.cj.jdbc.Driver db.jdbcUrl=jdbc:mysql://localhost:3306/javaweb_db?useSSL=false&serverTimezone=UTC&characterEncoding=UTF-8 db.username=javaweb_user db.password=your_strong_password # 连接池配置 (HikariCP) pool.maximumPoolSize=10 pool.connectionTimeout=30000 pool.idleTimeout=600000 pool.maxLifetime=1800000
jdbcUrl:localhost是 MySQL 服务器的地址,3306是默认端口。 后面是连接参数,非常重要:useSSL=false: 开发环境可以关闭 SSL,生产环境应开启。serverTimezone=UTC: 设置服务器时区,避免时区警告。characterEncoding=UTF-8: 确保字符编码正确。
pool.*: HikariCP 连接池的优化参数,可以根据你的应用负载调整。
第 5 步:编写数据库连接工具类
我们将创建一个工具类,负责在应用启动时初始化连接池,并提供获取连接的方法。
-
创建
DBUtil类 在src/main/java下创建你的包结构,com.example.util,然后创建DBUtil.java。src/main/java/com/example/util/DBUtil.java:package com.example.util; import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; import java.io.IOException; import java.io.InputStream; import java.sql.Connection; import java.sql.SQLException; import java.util.Properties; public class DBUtil { // 使用静态变量,确保整个应用只有一个数据源 private static HikariDataSource dataSource; // 静态代码块,在类加载时执行,只执行一次 static { try (InputStream input = DBUtil.class.getClassLoader().getResourceAsStream("db.properties")) { Properties props = new Properties(); props.load(input); // 创建 HikariConfig 配置对象 HikariConfig config = new HikariConfig(); config.setDriverClassName(props.getProperty("db.driverClassName")); config.setJdbcUrl(props.getProperty("db.jdbcUrl")); config.setUsername(props.getProperty("db.username")); config.setPassword(props.getProperty("db.password")); // 设置连接池参数 config.setMaximumPoolSize(Integer.parseInt(props.getProperty("pool.maximumPoolSize"))); config.setConnectionTimeout(Long.parseLong(props.getProperty("pool.connectionTimeout"))); config.setIdleTimeout(Long.parseLong(props.getProperty("pool.idleTimeout"))); config.setMaxLifetime(Long.parseLong(props.getProperty("pool.maxLifetime"))); // 使用配置创建数据源 dataSource = new HikariDataSource(config); } catch (IOException e) { throw new RuntimeException("Failed to load database properties file!", e); } } // 获取数据库连接 public static Connection getConnection() throws SQLException { if (dataSource == null) { throw new SQLException("Data source is not initialized!"); } return dataSource.getConnection(); } // 关闭数据源 (通常在应用关闭时调用) public static void closeDataSource() { if (dataSource != null && !dataSource.isClosed()) { dataSource.close(); } } }
第 6 步:在 Servlet 中使用连接
我们创建一个简单的 Servlet 来测试数据库连接和执行一个查询。
-
创建一个测试表
USE javaweb_db; CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50) NOT NULL, email VARCHAR(100) NOT NULL UNIQUE ); INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com'); INSERT INTO users (name, email) VALUES ('Bob', 'bob@example.com'); -
创建
UserServlet在src/main/java下创建你的包,com.example.servlet,然后创建UserServlet.java。src/main/java/com/example/servlet/UserServlet.java:package com.example.servlet; import com.example.util.DBUtil; import jakarta.servlet.ServletException; import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @WebServlet("/users") public class UserServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 设置响应内容类型和字符编码 resp.setContentType("text/html;charset=UTF-8"); PrintWriter out = resp.getWriter(); Connection conn = null; PreparedStatement pstmt = null; ResultSet rs = null; try { // 1. 从连接池获取连接 conn = DBUtil.getConnection(); // 2. 准备 SQL 语句 String sql = "SELECT id, name, email FROM users"; pstmt = conn.prepareStatement(sql); // 3. 执行查询 rs = pstmt.executeQuery(); // 4. 处理结果集 out.println("<h1>用户列表</h1>"); out.println("<table border=\"1\">"); out.println("<tr><th>ID</th><th>姓名</th><th>邮箱</th></tr>"); while (rs.next()) { int id = rs.getInt("id"); String name = rs.getString("name"); String email = rs.getString("email"); out.println("<tr>"); out.println("<td>" + id + "</td>"); out.println("<td>" + name + "</td>"); out.println("<td>" + email + "</td>"); out.println("</tr>"); } out.println("</table>"); } catch (SQLException e) { out.println("<h2>数据库错误!</h2>"); e.printStackTrace(out); // 在实际生产环境中,不要将堆栈信息直接输出给用户 } finally { // 5. 关闭资源 (顺序很重要: ResultSet -> Statement -> Connection) try { if (rs != null) rs.close(); if (pstmt != null) pstmt.close(); // 注意:这里不关闭 Connection,而是将其归还给连接池 // conn.close(); // 错误的做法! } catch (SQLException e) { e.printStackTrace(); } } } }
第 7 步:部署和运行
-
配置 Tomcat 在你的 IDE 中配置 Tomcat 服务器,将你的 Web 应用部署到 Tomcat 上。
-
启动 Tomcat 启动 Tomcat 服务器。
-
访问测试 打开你的浏览器,访问
http://localhost:8080/你的项目名/users(http://localhost:8080/JavaWebMySQLDemo/users)。
如果一切顺利,你应该能看到一个 HTML 表格,其中显示了 users 表中的数据。
总结与最佳实践
- 使用连接池: 绝对不要在每次请求时都创建和销毁连接,使用 HikariCP 这样的连接池可以极大地提升性能和稳定性。
- 配置文件外部化: 将数据库配置(如密码)放在
db.properties文件中,而不是硬编码在 Java 代码里,这提高了安全性和可维护性。 - 资源管理: 在
finally块中关闭ResultSet和PreparedStatement。不要手动关闭Connection,调用conn.close()实际上是将连接归还给连接池,而不是真正关闭物理连接。 - 异常处理: 对数据库操作进行适当的异常处理,在生产环境中,不应将详细的错误信息直接展示给用户。
- 现代框架: 对于大型项目,通常会使用更高级的框架,如 Spring Boot 或 Jakarta EE (如 Payara / WildFly),这些框架极大地简化了数据库连接和事务管理(通过 Spring Data JPA 或 JPA),但理解底层 JDBC 和连接池的原理对于成为一名优秀的 Java 开发者至关重要。
