Servlet 数据库访问

一、什么是 Servlet 数据库访问?

Servlet 数据库访问是指在 Servlet 中通过 Java Database Connectivity (JDBC) API 连接和操作数据库,实现数据的增删改查(CRUD)。这在 Web 应用中非常常见,例如用户注册、登录验证或数据查询。JDBC 是 Java 连接数据库的标准接口,支持多种数据库如 MySQL、Oracle 等。

本教程假设您已了解 JDBC 基础,并配置好数据库驱动(如 MySQL 的 mysql-connector-java.jar)。如果未配置,请先下载驱动并添加到项目 classpath 中。


二、JDBC 在 Servlet 中的基本流程

Servlet 访问数据库的典型流程包括:

  1. 加载驱动:使用 Class.forName() 加载 JDBC 驱动。
  2. 建立连接:通过 DriverManager.getConnection() 获取数据库连接。
  3. 创建语句:使用 Connection 创建 StatementPreparedStatement 执行 SQL。
  4. 执行操作:查询(executeQuery())或更新(executeUpdate())。
  5. 处理结果:对于查询,使用 ResultSet 读取数据。
  6. 关闭资源:关闭 ResultSetStatementConnection 以释放资源。

这些步骤需要在 Servlet 的 doGet()doPost() 方法中实现。


三、Servlet 数据库访问的操作示例

以下以 MySQL 数据库为例,演示如何在 Servlet 中连接数据库并进行查询和插入操作。假设数据库名为 test,表名为 users(字段:id、name、age)。

1. 配置数据库驱动

  • 下载 MySQL Connector/J(例如 mysql-connector-java-8.0.x.jar)。
  • 在 Eclipse 或 IntelliJ 中,将 jar 包添加到项目的 Build Path 或 lib 目录。

2. 查询操作示例

创建一个 Servlet 来查询用户列表。

代码示例

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

public class QueryServlet extends HttpServlet {
    // 数据库连接信息
    private static final String URL = "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8";
    private static final String USER = "root";
    private static final String PASSWORD = "your_password";

    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();

        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;

        try {
            // 加载驱动
            Class.forName("com.mysql.cj.jdbc.Driver");

            // 建立连接
            conn = DriverManager.getConnection(URL, USER, PASSWORD);

            // 创建语句
            stmt = conn.createStatement();

            // 执行查询
            String sql = "SELECT * FROM users";
            rs = stmt.executeQuery(sql);

            // 处理结果
            out.println("<h1>用户列表</h1><ul>");
            while (rs.next()) {
                int id = rs.getInt("id");
                String name = rs.getString("name");
                int age = rs.getInt("age");
                out.println("<li>ID: " + id + ", Name: " + name + ", Age: " + age + "</li>");
            }
            out.println("</ul>");
        } catch (Exception e) {
            out.println("错误: " + e.getMessage());
        } finally {
            // 关闭资源
            try {
                if (rs != null) rs.close();
                if (stmt != null) stmt.close();
                if (conn != null) conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

说明

  • Class.forName("com.mysql.cj.jdbc.Driver"):加载 MySQL 驱动(适用于 MySQL 8+)。
  • DriverManager.getConnection():连接数据库,URL 中添加 useUnicode=true&characterEncoding=UTF-8 支持中文。
  • 使用 try-catch-finally 处理异常和关闭资源。

3. 插入操作示例

使用 PreparedStatement 防止 SQL 注入。

代码示例

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

public class InsertServlet extends HttpServlet {
    private static final String URL = "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8";
    private static final String USER = "root";
    private static final String PASSWORD = "your_password";

    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();

        String name = request.getParameter("name");
        int age = Integer.parseInt(request.getParameter("age"));

        Connection conn = null;
        PreparedStatement pstmt = null;

        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection(URL, USER, PASSWORD);

            String sql = "INSERT INTO users (name, age) VALUES (?, ?)";
            pstmt = conn.prepareStatement(sql);
            pstmt.setString(1, name);
            pstmt.setInt(2, age);

            int rows = pstmt.executeUpdate();
            out.println("插入成功,影响行数: " + rows);
        } catch (Exception e) {
            out.println("错误: " + e.getMessage());
        } finally {
            try {
                if (pstmt != null) pstmt.close();
                if (conn != null) conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

说明

  • PreparedStatement 使用占位符 ? 预编译 SQL,提高安全性和效率。
  • request.setCharacterEncoding("UTF-8"):处理 POST 请求中的中文参数。

四、处理中文数据库访问

在 Servlet 中访问数据库时,中文可能出现乱码问题。解决方案:

  1. 数据库配置:确保数据库和表使用 UTF-8 编码(例如 CREATE DATABASE test CHARACTER SET utf8mb4;)。
  2. 连接 URL:添加 ?useUnicode=true&characterEncoding=UTF-8
  3. 请求/响应编码request.setCharacterEncoding("UTF-8")response.setContentType("text/html;charset=UTF-8")
  4. 读取数据rs.getString("name") 时,如果数据库编码正确,无需额外处理。

示例:在插入中文姓名时,确保参数正确编码,即可避免乱码。


五、注意事项

  1. 安全性
  • 始终使用 PreparedStatement 防止 SQL 注入。
  • 不要在代码中硬编码密码;使用配置文件或环境变量。
  1. 性能优化
  • 使用连接池(如 HikariCP 或 Tomcat JDBC Pool)代替每次创建连接,提高效率。
  • 在 web.xml 或代码中配置数据源。
  1. 异常处理
  • 捕获 SQLExceptionClassNotFoundException
  • 确保 finally 块关闭资源,避免连接泄漏。
  1. 数据库兼容
  • 不同数据库驱动不同(如 Oracle 使用 “oracle.jdbc.OracleDriver”)。
  • 测试环境:本地 MySQL,生产环境可能使用云数据库(如 Google Cloud SQL)。
  1. 部署
  • 在 Tomcat 等容器中,确保驱动 jar 在 lib 目录。
  • 对于大型应用,考虑使用 ORM 框架如 Hibernate 代替纯 JDBC。

六、常见问题与解决方案

  1. 问题:ClassNotFoundException: com.mysql.cj.jdbc.Driver。
  • 解决:检查驱动 jar 是否添加到 classpath。
  1. 问题:中文乱码。
  • 解决:检查连接 URL、请求编码和数据库字符集。
  1. 问题:连接超时。
  • 解决:使用连接池,并设置超时参数。

七、总结

Servlet 通过 JDBC 实现数据库访问是 Web 开发的核心技能。从连接到执行 SQL,再到结果处理,整个过程需注重安全和效率。使用 PreparedStatement 和连接池可以显著提升应用质量。实际开发中,可结合 JSP 或框架如 Spring 来构建完整应用。

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注