Class.forName()
注册驱动,通过DriverManager.getConnection()
获取连接,创建Statement执行SQL,ResultSet处理结果,完毕以下是关于 JSP 链接数据库并实现页面跳转 的完整技术方案及实现细节,包含核心代码、注意事项、典型场景示例以及常见问题解答:
整体实现思路
JSP 通过 JDBC 技术与数据库交互的核心流程可分为以下阶段:
- 加载驱动 & 建立连接 → 2. 创建 SQL 语句对象 → 3. 执行 SQL 并获取结果 → 4. 处理结果集/更新计数 → 5. 关闭资源 → 6. 根据业务逻辑跳转页面
⚠️ 关键原则:所有数据库操作必须在
try-finally
块中完成,确保资源释放;推荐使用PreparedStatement
替代Statement
防止 SQL 注入。
详细实现步骤与代码示例
准备工作
项目 | 说明 | 示例值 |
---|---|---|
数据库类型 | MySQL/Oracle/SQL Server 等 | MySQL 8.0 |
JDBC 驱动包 | 需放入 WEB-INF/lib 目录 |
mysql-connector-java-8.0.xx.jar |
数据库连接信息 | URL/用户名/密码 | jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=UTC root password |
JSP 文件位置 | WebContent 目录下 | login.jsp , welcome.jsp |
基础代码结构(以用户登录为例)
前端表单 (login.jsp
)
<%@ page language="java" contentType="text/html; charset=UTF-8" %> <html> <head><title>登录</title></head> <body> <form action="checkLogin.jsp" method="post"> 用户名: <input type="text" name="username"><br> 密码: <input type="password" name="password"><br> <input type="submit" value="登录"> </form> </body> </html>
后端处理 (checkLogin.jsp
)
<%@ page import="java.sql.;" %> <%! // 全局变量定义(仅演示用途,实际建议封装为工具类) String driverClass = "com.mysql.cj.jdbc.Driver"; String dbURL = "jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=UTC"; String dbUser = "root"; String dbPass = "password"; %> <% // 1. 接收请求参数 String userName = request.getParameter("username"); String userPwd = request.getParameter("password"); Connection conn = null; PreparedStatement pstmt = null; ResultSet rs = null; int validUserCount = 0; // 用于判断是否存在有效用户 try { // 2. 加载驱动 & 建立连接 Class.forName(driverClass); conn = DriverManager.getConnection(dbURL, dbUser, dbPass); // 3. 编写 SQL 并预编译 String sql = "SELECT COUNT() FROM users WHERE username=? AND password=?"; pstmt = conn.prepareStatement(sql); pstmt.setString(1, userName); pstmt.setString(2, userPwd); // ✅ 自动转义特殊字符,防SQL注入 // 4. 执行查询 rs = pstmt.executeQuery(); if (rs.next()) { validUserCount = rs.getInt(1); } // 5. 根据结果跳转 if (validUserCount > 0) { // ✅ 方法一:转发请求(保持同一请求周期) request.setAttribute("username", userName); request.getRequestDispatcher("/welcome.jsp").forward(request, response); } else { // ✅ 方法二:重定向(生成新请求) response.sendRedirect("loginFailed.jsp?error=用户名或密码错误"); } } catch (Exception e) { e.printStackTrace(); out.println("系统错误:" + e.getMessage()); } finally { // 6. 关闭资源(逆序关闭) try { if (rs != null) rs.close(); } catch (Exception ignored) {} try { if (pstmt != null) pstmt.close(); } catch (Exception ignored) {} try { if (conn != null) conn.close(); } catch (Exception ignored) {} } %>
成功跳转页 (welcome.jsp
)
<%@ page contentType="text/html; charset=UTF-8" %> <html> <head><title>欢迎</title></head> <body> <h2>欢迎回来,<%= request.getAttribute("username") %>!</h2> <a href="logout.jsp">退出登录</a> </body> </html>
两种跳转方式对比表
特性 | RequestDispatcher.forward() |
HttpServletResponse.sendRedirect() |
---|---|---|
请求次数 | 1 次(同一请求周期) | 2 次(客户端发起新请求) |
数据共享 | 可通过 request 对象传递 |
只能通过 URL 参数或 Cookie 传递 |
URL 可见性 | 浏览器地址栏不变 | 浏览器地址栏变为新 URL |
适用场景 | 同一应用内的页面流转 | 跨应用跳转或需要刷新页面的场景 |
性能 | 更快(无需客户端重新请求) | 稍慢(需客户端响应) |
示例用法 | request.getRequestDispatcher("/b.jsp").forward(request, response); |
response.sendRedirect("c.jsp"); |
高级优化建议
-
连接池管理:生产环境应使用 DBCP/C3P0/HikariCP 等连接池替代手动开闭连接,提升性能。
示例(HikariCP):// Maven依赖:com.zaxxer:HikariCP:5.0.1+ HikariConfig config = new HikariConfig(); config.setJdbcUrl(dbURL); config.setUsername(dbUser); config.setPassword(dbPass); HikariDataSource ds = new HikariDataSource(config); Connection conn = ds.getConnection(); // 从连接池获取连接
-
MVC 分层:将数据库操作移至 Servlet,JSP 仅负责视图渲染,符合 MVC 架构。
示例结构:├── src/main/java/com/example/controller/LoginServlet.java └── webapp/ ├── login.jsp ├── welcome.jsp └── WEB-INF/web.xml (配置Servlet映射)
-
字符编码处理:若出现中文乱码,需在连接字符串中添加
&characterEncoding=UTF-8
,并在 JSP 顶部声明<%@ page pageEncoding="UTF-8" %>
。 -
事务控制:涉及多条 SQL 操作时,需手动管理事务(
conn.setAutoCommit(false)
),并在最终提交或回滚。
相关问答 FAQs
Q1: JSP 连接数据库时报 “ClassNotFoundException: com.mysql.cj.jdbc.Driver” 怎么办?
A: 这是由于未正确引入 JDBC 驱动包导致的,解决方法:
- 下载对应数据库的 JDBC 驱动 JAR 文件(如 MySQL 的
mysql-connector-java-8.0.xx.jar
); - 将 JAR 文件复制到项目的
WEB-INF/lib
目录下; - 确保
Class.forName()
中的驱动类名与 JAR 包中的完全一致(注意大小写)。
注:部分旧版驱动类名为com.mysql.jdbc.Driver
,新版已变更为com.mysql.cj.jdbc.Driver
。
Q2: 为什么使用 PreparedStatement
而不是 Statement
?
A: PreparedStatement
有以下优势:
- 防止 SQL 注入:通过预编译 SQL 语句,将用户输入作为参数绑定(而非字符串拼接),可自动转义特殊字符(如单引号);
- 提高性能:数据库会对预编译的 SQL 进行缓存,重复执行时无需再次解析;
- 代码可读性更好:通过 占位符明确区分 SQL 结构和参数,避免复杂的字符串拼接。
示例对比:
错误写法(易受攻击):String sql = "SELECT FROM users WHERE username='" + userName + "'";
正确写法(安全):`String sql = “SELECT FROM users WHERE username=?”; pstmt.setString(1
原创文章,发布者:酷盾叔,转转请注明出处:https://www.kd.cn/ask/100610.html