我会从基础概念讲起,提供最主流、最推荐的实现方式(使用 JSP + Servlet + JDBC + 连接池),并给出一个完整、可运行的示例代码。

核心概念
在 JSP 中连接数据库,通常不直接在 JSP 页面里写数据库代码,而是遵循 MVC(Model-View-Controller)设计模式。
- View (视图层): JSP 文件,负责展示数据,也就是我们看到的网页界面,它只负责显示,不负责业务逻辑或数据库操作。
- Controller (控制层): Servlet,接收来自 JSP 页面的用户请求(如表单提交),调用 Model 层处理业务逻辑,然后根据处理结果选择将哪个 JSP 页面返回给用户。
- Model (模型层): JavaBean (POJO) 和 JDBC 代码,负责核心的业务逻辑和数据库交互,它包括:
- 实体类 (JavaBean): 与数据库表结构一一对应的 Java 类,用于封装数据。
- DAO (Data Access Object): 数据访问对象,专门负责执行增、删、改、查等数据库操作。
为什么这样设计? 因为直接在 JSP 里写 Java 代码(俗称 "Scriptlet")是一种非常糟糕的实践,会导致代码混乱、难以维护和重用,将代码分离到 Servlet 和 JavaBean 中,可以使项目结构清晰,职责分明,便于团队协作和后期维护。
准备工作
在开始编码前,请确保你已经准备好以下环境:
- JDK (Java Development Kit): 安装并配置好 Java 开发环境。
- Web 服务器: 如 Apache Tomcat。
- IDE (集成开发环境): 如 IntelliJ IDEA 或 Eclipse,它们能极大地简化 Web 项目的配置。
- 数据库: 如 MySQL,请确保你已经安装好 MySQL,并创建了一个数据库,以及一个可以访问该数据库的用户。
- 数据库驱动: JDBC Driver,这是 Java 程序与数据库通信的桥梁,你需要下载对应你数据库版本的 JDBC 驱动 JAR 包。
- MySQL 8.x:
mysql-connector-j-8.x.xx.jar - MySQL 5.x:
mysql-connector-java-5.x.xx.jar - 下载地址: MySQL Connector/J
- MySQL 8.x:
实现步骤(以 MySQL 为例)
我们将创建一个简单的用户管理应用,实现“添加用户”和“显示用户列表”的功能。

步骤 1:创建 Web 项目并配置环境
- 在你的 IDE(如 IDEA)中创建一个新的 Maven Web App 项目。
- 将下载好的 JDBC 驱动 JAR 包添加到项目中。
- Maven 方式(推荐): 在
pom.xml文件中添加依赖。<dependencies> <!-- JSP API --> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>2.3.3</version> <scope>provided</scope> </dependency> <!-- Servlet API --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency> <!-- JSTL (JSP Standard Tag Library) --> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <!-- MySQL Connector/J --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.28</version> <!-- 使用你下载的版本号 --> </dependency> </dependencies> - 手动方式: 将 JAR 包复制到项目的
WEB-INF/lib目录下。
- Maven 方式(推荐): 在
步骤 2:准备数据库
在你的 MySQL 数据库中执行以下 SQL 语句,创建 users 表。
CREATE DATABASE my_jsp_db; USE my_jsp_db; CREATE TABLE `users` ( `id` INT PRIMARY KEY AUTO_INCREMENT, `username` VARCHAR(50) NOT NULL, `password` VARCHAR(50) NOT NULL, `email` VARCHAR(100) );
步骤 3:创建 Model 层
实体类 (User.java)
创建一个 User 类,与 users 表对应。
// src/main/java/com/example/model/User.java
package com.example.model;
public class User {
private int id;
private String username;
private String password;
private String email;
// 构造方法、Getter 和 Setter
public User() {}
public User(String username, String password, String email) {
this.username = username;
this.password = password;
this.email = email;
}
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; }
}
数据库连接工具类 (DBUtil.java) 这是一个最佳实践,用于管理数据库连接,我们这里先使用最简单的方式,后面会升级到连接池。
// src/main/java/com/example/util/DBUtil.java
package com.example.util;
import java.sql.*;
public class DBUtil {
// 数据库连接信息
private static final String URL = "jdbc:mysql://localhost:3306/my_jsp_db?useSSL=false&serverTimezone=UTC";
private static final String USER = "root"; // 你的数据库用户名
private static final String PASSWORD = "your_password"; // 你的数据库密码
// 获取数据库连接
public static Connection getConnection() throws SQLException {
try {
// 加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
return DriverManager.getConnection(URL, USER, PASSWORD);
} catch (ClassNotFoundException e) {
throw new SQLException("MySQL JDBC Driver not found", e);
}
}
// 关闭资源
public static void closeAll(Connection conn, Statement stmt, ResultSet rs) {
if (rs != null) {
try { rs.close(); } catch (SQLException e) { /* ignored */ }
}
if (stmt != null) {
try { stmt.close(); } catch (SQLException e) { /* ignored */ }
}
if (conn != null) {
try { conn.close(); } catch (SQLException e) { /* ignored */ }
}
}
}
数据访问对象 (UserDAO.java) 这是与数据库交互的核心类。

// src/main/java/com/example/dao/UserDAO.java
package com.example.dao;
import com.example.model.User;
import com.example.util.DBUtil;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class UserDAO {
// 添加用户
public void addUser(User user) throws SQLException {
String sql = "INSERT INTO users (username, password, email) VALUES (?, ?, ?)";
Connection conn = null;
PreparedStatement pstmt = null;
try {
conn = DBUtil.getConnection();
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, user.getUsername());
pstmt.setString(2, user.getPassword());
pstmt.setString(3, user.getEmail());
pstmt.executeUpdate();
} finally {
DBUtil.closeAll(conn, pstmt, null);
}
}
// 获取所有用户
public List<User> getAllUsers() throws SQLException {
List<User> users = new ArrayList<>();
String sql = "SELECT * FROM users";
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
conn = DBUtil.getConnection();
stmt = conn.createStatement();
rs = stmt.executeQuery(sql);
while (rs.next()) {
User user = new User();
user.setId(rs.getInt("id"));
user.setUsername(rs.getString("username"));
user.setPassword(rs.getString("password"));
user.setEmail(rs.getString("email"));
users.add(user);
}
} finally {
DBUtil.closeAll(conn, stmt, rs);
}
return users;
}
}
步骤 4:创建 Controller 层 (Servlet)
创建一个 UserServlet 来处理用户请求。
// src/main/java/com/example/controller/UserServlet.java
package com.example.controller;
import com.example.dao.UserDAO;
import com.example.model.User;
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.util.List;
@WebServlet("/user") // 访问该 Servlet 的 URL
public class UserServlet extends HttpServlet {
private UserDAO userDAO = new UserDAO();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String action = req.getParameter("action");
if (action == null) {
action = "list"; // 默认显示用户列表
}
try {
switch (action) {
case "list":
listUsers(req, resp);
break;
case "addForm":
req.getRequestDispatcher("/addUser.jsp").forward(req, resp);
break;
default:
listUsers(req, resp);
}
} catch (Exception e) {
throw new ServletException(e);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8"); // 处理中文乱码
String action = req.getParameter("action");
try {
if ("add".equals(action)) {
addUser(req, resp);
}
} catch (Exception e) {
throw new ServletException(e);
}
}
private void listUsers(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException, SQLException {
List<User> userList = userDAO.getAllUsers();
req.setAttribute("userList", userList);
req.getRequestDispatcher("/userList.jsp").forward(req, resp);
}
private void addUser(HttpServletRequest req, HttpServletResponse resp) throws SQLException, IOException {
String username = req.getParameter("username");
String password = req.getParameter("password");
String email = req.getParameter("email");
User newUser = new User(username, password, email);
userDAO.addUser(newUser);
// 添加成功后,重定向到用户列表页面
resp.sendRedirect(req.getContextPath() + "/user?action=list");
}
}
步骤 5:创建 View 层 (JSP)
首页 (index.jsp) 一个简单的欢迎页面,提供导航链接。
<%-- webapp/index.jsp --%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>JSP 数据库连接示例</title>
</head>
<body>
<h1>欢迎使用 JSP 数据库示例</h1>
<p><a href="${pageContext.request.contextPath}/user?action=list">查看用户列表</a></p>
<p><a href="${pageContext.request.contextPath}/user?action=addForm">添加新用户</a></p>
</body>
</html>
添加用户页面 (addUser.jsp) 一个表单,用于输入新用户信息。
<%-- webapp/addUser.jsp --%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>添加用户</title>
</head>
<body>
<h2>添加新用户</h2>
<form action="${pageContext.request.contextPath}/user" method="post">
<input type="hidden" name="action" value="add">
<table>
<tr>
<td>用户名:</td>
<td><input type="text" name="username" required></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name="password" required></td>
</tr>
<tr>
<td>邮箱:</td>
<td><input type="email" name="email"></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="提交"></td>
</tr>
</table>
</form>
<p><a href="${pageContext.request.contextPath}/user?action=list">返回列表</a></p>
</body>
</html>
用户列表页面 (userList.jsp) 使用 JSTL 标签库来显示从 Servlet 传递过来的用户列表。
<%-- webapp/userList.jsp --%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>用户列表</title>
</head>
<body>
<h2>用户列表</h2>
<p><a href="${pageContext.request.contextPath}/user?action=addForm">添加新用户</a></p>
<table border="1" cellpadding="5">
<tr>
<th>ID</th>
<th>用户名</th>
<th>密码</th>
<th>邮箱</th>
</tr>
<c:forEach var="user" items="${userList}">
<tr>
<td>${user.id}</td>
<td>${user.username}</td>
<td>${user.password}</td>
<td>${user.email}</td>
</tr>
</c:forEach>
</table>
</body>
</html>
进阶:使用连接池 (Druid)
每次创建和关闭数据库连接都非常消耗资源,在生产环境中,我们使用 数据库连接池 来复用连接,提高性能。
Druid 是阿里巴巴开源的一款功能强大、性能优秀的数据库连接池。
添加 Druid 依赖
在 pom.xml 中添加 Druid 依赖。
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.8</version>
</dependency>
修改 DBUtil.java
使用 Druid 来管理连接。
// src/main/java/com/example/util/DBUtil.java
package com.example.util;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class DBUtil {
private static DataSource dataSource;
static {
try {
// 读取 druid.properties 配置文件
InputStream is = DBUtil.class.getClassLoader().getResourceAsStream("druid.properties");
Properties props = new Properties();
props.load(is);
// 创建 DruidDataSource 实例
dataSource = DruidDataSourceFactory.createDataSource(props);
} catch (Exception e) {
throw new RuntimeException("初始化连接池失败", e);
}
}
// 从连接池中获取连接
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
// 关闭资源 (连接会自动放回池中)
public static void closeAll(Connection conn, Statement stmt, ResultSet rs) {
if (rs != null) {
try { rs.close(); } catch (SQLException e) { /* ignored */ }
}
if (stmt != null) {
try { stmt.close(); } catch (SQLException e) { /* ignored */ }
}
if (conn != null) {
try { conn.close(); } catch (SQLException e) { /* ignored */ }
}
}
}
创建 druid.properties 配置文件
在 src/main/resources 目录下创建 druid.properties 文件。
# druid.properties driverClassName=com.mysql.cj.jdbc.Driver url=jdbc:mysql://localhost:3306/my_jsp_db?useSSL=false&serverTimezone=UTC username=root password=your_password # 初始连接数 initialSize=5 # 最小空闲连接数 minIdle=5 # 最大连接数 maxActive=20 # 获取连接等待超时的时间 maxWait=60000
- 不要在 JSP 中写 Java 代码:遵循 MVC 模式,将 JSP 作为视图,Servlet 作为控制器,JavaBean 和 DAO 作为模型。
- 使用
PreparedStatement:它可以有效防止 SQL 注入攻击,并且性能通常比Statement更好。 - 使用连接池:对于任何生产环境,使用像 Druid 或 HikariCP 这样的连接池是必须的,它能显著提升应用性能和稳定性。
- 处理中文乱码:在
doPost方法开始时调用req.setCharacterEncoding("UTF-8");,并确保 JSP 页面设置了<%@ page contentType="text/html;charset=UTF-8" language="java" %>。 - 使用 JSTL:在 JSP 中使用 JSTL 和 EL 表达式 来替代传统的脚本,使页面更整洁。
遵循以上步骤和最佳实践,你就可以构建一个健壮、可维护的 JSP 数据库应用了。
