简体中文 繁體中文 English 日本語 Deutsch 한국 사람 بالعربية TÜRKÇE português คนไทย Français

站内搜索

搜索

活动公告

11-02 12:46
10-23 09:32
通知:本站资源由网友上传分享,如有违规等问题请到版务模块进行投诉,将及时处理!
10-23 09:31
10-23 09:28
通知:签到时间调整为每日4:00(东八区)
10-23 09:26

JSP页面实现数据库信息动态显示的方法与实践 从基础连接到数据展示的全流程解析 助力开发者轻松掌握网页与数据库交互的核心技术

3万

主题

349

科技点

3万

积分

大区版主

木柜子打湿

积分
31898

三倍冰淇淋无人之境【一阶】财Doro小樱(小丑装)立华奏以外的星空【二阶】⑨的冰沙

发表于 2025-9-17 21:20:06 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
引言

JavaServer Pages(JSP)是一种用于创建动态Web内容的技术,它允许开发者在HTML页面中嵌入Java代码。在现代Web应用中,与数据库的交互是不可或缺的功能,无论是展示产品信息、用户数据还是其他动态内容,都需要从数据库中获取数据并在网页上展示。本文将详细介绍如何使用JSP技术实现数据库信息的动态显示,从基础的数据库连接到完整的数据展示流程,帮助开发者掌握这一核心技能。

环境准备

在开始之前,我们需要准备必要的开发环境和工具:

1. Java Development Kit (JDK):确保安装了JDK 8或更高版本。
2. Web服务器:Apache Tomcat是最常用的JSP容器,可从官网下载并安装。
3. IDE:Eclipse、IntelliJ IDEA等集成开发环境可以提高开发效率。
4. 数据库:MySQL、PostgreSQL或Oracle等关系型数据库。
5. JDBC驱动:对应数据库的JDBC驱动程序,用于Java程序与数据库的连接。

以MySQL为例,我们需要下载MySQL Connector/J驱动程序,并将其添加到项目的类路径中。

数据库基础连接

JDBC简介

Java Database Connectivity(JDBC)是Java语言中用于执行SQL语句的API,可以为多种关系数据库提供统一访问。JDBC提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序。

建立数据库连接

在JSP中连接数据库,通常使用JDBC。以下是一个基本的数据库连接示例:
  1. <%@ page import="java.sql.*" %>
  2. <%
  3.     Connection conn = null;
  4.     Statement stmt = null;
  5.     ResultSet rs = null;
  6.    
  7.     try {
  8.         // 1. 加载驱动
  9.         Class.forName("com.mysql.jdbc.Driver");
  10.         
  11.         // 2. 建立连接
  12.         String url = "jdbc:mysql://localhost:3306/mydatabase?useSSL=false&serverTimezone=UTC";
  13.         String username = "root";
  14.         String password = "password";
  15.         conn = DriverManager.getConnection(url, username, password);
  16.         
  17.         // 3. 创建Statement
  18.         stmt = conn.createStatement();
  19.         
  20.         // 4. 执行查询
  21.         String sql = "SELECT * FROM users";
  22.         rs = stmt.executeQuery(sql);
  23.         
  24.         // 5. 处理结果集
  25.         while (rs.next()) {
  26.             int id = rs.getInt("id");
  27.             String name = rs.getString("name");
  28.             String email = rs.getString("email");
  29.             out.println("ID: " + id + ", Name: " + name + ", Email: " + email + "<br>");
  30.         }
  31.     } catch (Exception e) {
  32.         e.printStackTrace();
  33.     } finally {
  34.         // 6. 关闭资源
  35.         try {
  36.             if (rs != null) rs.close();
  37.             if (stmt != null) stmt.close();
  38.             if (conn != null) conn.close();
  39.         } catch (SQLException e) {
  40.             e.printStackTrace();
  41.         }
  42.     }
  43. %>
复制代码

使用连接池

直接使用JDBC连接数据库在每次请求时都会创建新的连接,这在高并发环境下效率低下。连接池技术可以重用数据库连接,提高性能。以下是使用Apache DBCP连接池的示例:

首先,在项目中添加DBCP依赖。如果使用Maven,添加以下依赖:
  1. <dependency>
  2.     <groupId>org.apache.commons</groupId>
  3.     <artifactId>commons-dbcp2</artifactId>
  4.     <version>2.9.0</version>
  5. </dependency>
复制代码

然后,创建一个数据库连接池工具类:
  1. package util;
  2. import org.apache.commons.dbcp2.BasicDataSource;
  3. public class DataSourceUtil {
  4.     private static BasicDataSource dataSource = null;
  5.    
  6.     static {
  7.         dataSource = new BasicDataSource();
  8.         dataSource.setDriverClassName("com.mysql.jdbc.Driver");
  9.         dataSource.setUrl("jdbc:mysql://localhost:3306/mydatabase?useSSL=false&serverTimezone=UTC");
  10.         dataSource.setUsername("root");
  11.         dataSource.setPassword("password");
  12.         dataSource.setInitialSize(5);
  13.         dataSource.setMaxTotal(20);
  14.         dataSource.setMaxIdle(10);
  15.         dataSource.setMinIdle(5);
  16.         dataSource.setMaxWaitMillis(10000);
  17.     }
  18.    
  19.     public static BasicDataSource getDataSource() {
  20.         return dataSource;
  21.     }
  22. }
复制代码

在JSP页面中使用连接池:
  1. <%@ page import="java.sql.*" %>
  2. <%@ page import="javax.sql.DataSource" %>
  3. <%@ page import="util.DataSourceUtil" %>
  4. <%
  5.     Connection conn = null;
  6.     Statement stmt = null;
  7.     ResultSet rs = null;
  8.    
  9.     try {
  10.         // 从连接池获取连接
  11.         DataSource dataSource = DataSourceUtil.getDataSource();
  12.         conn = dataSource.getConnection();
  13.         
  14.         // 创建Statement并执行查询
  15.         stmt = conn.createStatement();
  16.         String sql = "SELECT * FROM users";
  17.         rs = stmt.executeQuery(sql);
  18.         
  19.         // 处理结果集
  20.         while (rs.next()) {
  21.             int id = rs.getInt("id");
  22.             String name = rs.getString("name");
  23.             String email = rs.getString("email");
  24.             out.println("ID: " + id + ", Name: " + name + ", Email: " + email + "<br>");
  25.         }
  26.     } catch (Exception e) {
  27.         e.printStackTrace();
  28.     } finally {
  29.         // 关闭资源
  30.         try {
  31.             if (rs != null) rs.close();
  32.             if (stmt != null) stmt.close();
  33.             if (conn != null) conn.close(); // 将连接返回给连接池
  34.         } catch (SQLException e) {
  35.             e.printStackTrace();
  36.         }
  37.     }
  38. %>
复制代码

JSP页面基础

JSP语法简介

JSP页面主要由HTML模板和JSP元素组成。JSP元素包括:

1. 脚本元素:<% %>:Java代码片段<%= %>:表达式,将结果输出到页面<%! %>:声明,用于定义成员变量和方法
2. <% %>:Java代码片段
3. <%= %>:表达式,将结果输出到页面
4. <%! %>:声明,用于定义成员变量和方法
5. 指令元素:<%@ page %>:页面指令<%@ include %>:包含指令<%@ taglib %>:标签库指令
6. <%@ page %>:页面指令
7. <%@ include %>:包含指令
8. <%@ taglib %>:标签库指令
9. 动作元素:<jsp:include>:包含其他资源<jsp:forward>:转发请求<jsp:useBean>:使用JavaBean<jsp:setProperty>和<jsp:getProperty>:设置和获取JavaBean属性
10. <jsp:include>:包含其他资源
11. <jsp:forward>:转发请求
12. <jsp:useBean>:使用JavaBean
13. <jsp:setProperty>和<jsp:getProperty>:设置和获取JavaBean属性

脚本元素:

• <% %>:Java代码片段
• <%= %>:表达式,将结果输出到页面
• <%! %>:声明,用于定义成员变量和方法

指令元素:

• <%@ page %>:页面指令
• <%@ include %>:包含指令
• <%@ taglib %>:标签库指令

动作元素:

• <jsp:include>:包含其他资源
• <jsp:forward>:转发请求
• <jsp:useBean>:使用JavaBean
• <jsp:setProperty>和<jsp:getProperty>:设置和获取JavaBean属性

JSP与JavaBean

使用JavaBean可以更好地组织代码,实现业务逻辑与表示的分离。以下是一个简单的JavaBean示例:
  1. package model;
  2. public class User {
  3.     private int id;
  4.     private String name;
  5.     private String email;
  6.    
  7.     // 无参构造方法
  8.     public User() {}
  9.    
  10.     // 带参构造方法
  11.     public User(int id, String name, String email) {
  12.         this.id = id;
  13.         this.name = name;
  14.         this.email = email;
  15.     }
  16.    
  17.     // getter和setter方法
  18.     public int getId() {
  19.         return id;
  20.     }
  21.    
  22.     public void setId(int id) {
  23.         this.id = id;
  24.     }
  25.    
  26.     public String getName() {
  27.         return name;
  28.     }
  29.    
  30.     public void setName(String name) {
  31.         this.name = name;
  32.     }
  33.    
  34.     public String getEmail() {
  35.         return email;
  36.     }
  37.    
  38.     public void setEmail(String email) {
  39.         this.email = email;
  40.     }
  41. }
复制代码

在JSP页面中使用JavaBean:
  1. <%@ page import="model.User" %>
  2. <%@ page import="java.util.List" %>
  3. <%
  4.     // 假设users是从数据库获取的用户列表
  5.     List<User> users = (List<User>) request.getAttribute("users");
  6.    
  7.     if (users != null) {
  8.         for (User user : users) {
  9. %>
  10.             <div class="user-card">
  11.                 <h3><%= user.getName() %></h3>
  12.                 <p>ID: <%= user.getId() %></p>
  13.                 <p>Email: <%= user.getEmail() %></p>
  14.             </div>
  15. <%
  16.         }
  17.     }
  18. %>
复制代码

数据库操作

数据查询

查询是数据库操作中最常用的功能。以下是使用PreparedStatement进行参数化查询的示例:
  1. <%@ page import="java.sql.*" %>
  2. <%@ page import="util.DataSourceUtil" %>
  3. <%@ page import="javax.sql.DataSource" %>
  4. <%
  5.     Connection conn = null;
  6.     PreparedStatement pstmt = null;
  7.     ResultSet rs = null;
  8.    
  9.     try {
  10.         DataSource dataSource = DataSourceUtil.getDataSource();
  11.         conn = dataSource.getConnection();
  12.         
  13.         // 参数化查询,防止SQL注入
  14.         String sql = "SELECT * FROM users WHERE age > ?";
  15.         pstmt = conn.prepareStatement(sql);
  16.         pstmt.setInt(1, 18); // 设置参数,年龄大于18
  17.         
  18.         rs = pstmt.executeQuery();
  19.         
  20.         // 处理结果集
  21.         while (rs.next()) {
  22.             int id = rs.getInt("id");
  23.             String name = rs.getString("name");
  24.             String email = rs.getString("email");
  25.             int age = rs.getInt("age");
  26.             out.println("ID: " + id + ", Name: " + name + ", Email: " + email + ", Age: " + age + "<br>");
  27.         }
  28.     } catch (Exception e) {
  29.         e.printStackTrace();
  30.     } finally {
  31.         // 关闭资源
  32.         try {
  33.             if (rs != null) rs.close();
  34.             if (pstmt != null) pstmt.close();
  35.             if (conn != null) conn.close();
  36.         } catch (SQLException e) {
  37.             e.printStackTrace();
  38.         }
  39.     }
  40. %>
复制代码

数据插入

插入数据的示例:
  1. <%@ page import="java.sql.*" %>
  2. <%@ page import="util.DataSourceUtil" %>
  3. <%@ page import="javax.sql.DataSource" %>
  4. <%
  5.     Connection conn = null;
  6.     PreparedStatement pstmt = null;
  7.    
  8.     try {
  9.         DataSource dataSource = DataSourceUtil.getDataSource();
  10.         conn = dataSource.getConnection();
  11.         
  12.         // 插入数据
  13.         String sql = "INSERT INTO users (name, email, age) VALUES (?, ?, ?)";
  14.         pstmt = conn.prepareStatement(sql);
  15.         pstmt.setString(1, "张三");
  16.         pstmt.setString(2, "zhangsan@example.com");
  17.         pstmt.setInt(3, 25);
  18.         
  19.         int result = pstmt.executeUpdate();
  20.         
  21.         if (result > 0) {
  22.             out.println("数据插入成功!");
  23.         } else {
  24.             out.println("数据插入失败!");
  25.         }
  26.     } catch (Exception e) {
  27.         e.printStackTrace();
  28.     } finally {
  29.         // 关闭资源
  30.         try {
  31.             if (pstmt != null) pstmt.close();
  32.             if (conn != null) conn.close();
  33.         } catch (SQLException e) {
  34.             e.printStackTrace();
  35.         }
  36.     }
  37. %>
复制代码

数据更新

更新数据的示例:
  1. <%@ page import="java.sql.*" %>
  2. <%@ page import="util.DataSourceUtil" %>
  3. <%@ page import="javax.sql.DataSource" %>
  4. <%
  5.     Connection conn = null;
  6.     PreparedStatement pstmt = null;
  7.    
  8.     try {
  9.         DataSource dataSource = DataSourceUtil.getDataSource();
  10.         conn = dataSource.getConnection();
  11.         
  12.         // 更新数据
  13.         String sql = "UPDATE users SET email = ? WHERE id = ?";
  14.         pstmt = conn.prepareStatement(sql);
  15.         pstmt.setString(1, "newemail@example.com");
  16.         pstmt.setInt(2, 1);
  17.         
  18.         int result = pstmt.executeUpdate();
  19.         
  20.         if (result > 0) {
  21.             out.println("数据更新成功!");
  22.         } else {
  23.             out.println("数据更新失败!");
  24.         }
  25.     } catch (Exception e) {
  26.         e.printStackTrace();
  27.     } finally {
  28.         // 关闭资源
  29.         try {
  30.             if (pstmt != null) pstmt.close();
  31.             if (conn != null) conn.close();
  32.         } catch (SQLException e) {
  33.             e.printStackTrace();
  34.         }
  35.     }
  36. %>
复制代码

数据删除

删除数据的示例:
  1. <%@ page import="java.sql.*" %>
  2. <%@ page import="util.DataSourceUtil" %>
  3. <%@ page import="javax.sql.DataSource" %>
  4. <%
  5.     Connection conn = null;
  6.     PreparedStatement pstmt = null;
  7.    
  8.     try {
  9.         DataSource dataSource = DataSourceUtil.getDataSource();
  10.         conn = dataSource.getConnection();
  11.         
  12.         // 删除数据
  13.         String sql = "DELETE FROM users WHERE id = ?";
  14.         pstmt = conn.prepareStatement(sql);
  15.         pstmt.setInt(1, 1);
  16.         
  17.         int result = pstmt.executeUpdate();
  18.         
  19.         if (result > 0) {
  20.             out.println("数据删除成功!");
  21.         } else {
  22.             out.println("数据删除失败!");
  23.         }
  24.     } catch (Exception e) {
  25.         e.printStackTrace();
  26.     } finally {
  27.         // 关闭资源
  28.         try {
  29.             if (pstmt != null) pstmt.close();
  30.             if (conn != null) conn.close();
  31.         } catch (SQLException e) {
  32.             e.printStackTrace();
  33.         }
  34.     }
  35. %>
复制代码

数据展示

基本表格展示

在JSP页面中使用HTML表格展示数据库数据是最常见的方式:
  1. <%@ page import="java.sql.*" %>
  2. <%@ page import="util.DataSourceUtil" %>
  3. <%@ page import="javax.sql.DataSource" %>
  4. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  5. <html>
  6. <head>
  7.     <title>用户列表</title>
  8.     <style>
  9.         table {
  10.             border-collapse: collapse;
  11.             width: 100%;
  12.         }
  13.         th, td {
  14.             border: 1px solid #ddd;
  15.             padding: 8px;
  16.             text-align: left;
  17.         }
  18.         th {
  19.             background-color: #f2f2f2;
  20.         }
  21.         tr:nth-child(even) {
  22.             background-color: #f9f9f9;
  23.         }
  24.     </style>
  25. </head>
  26. <body>
  27.     <h1>用户列表</h1>
  28.     <table>
  29.         <tr>
  30.             <th>ID</th>
  31.             <th>姓名</th>
  32.             <th>邮箱</th>
  33.             <th>年龄</th>
  34.         </tr>
  35.         <%
  36.             Connection conn = null;
  37.             Statement stmt = null;
  38.             ResultSet rs = null;
  39.             
  40.             try {
  41.                 DataSource dataSource = DataSourceUtil.getDataSource();
  42.                 conn = dataSource.getConnection();
  43.                 stmt = conn.createStatement();
  44.                 String sql = "SELECT * FROM users";
  45.                 rs = stmt.executeQuery(sql);
  46.                
  47.                 while (rs.next()) {
  48.                     int id = rs.getInt("id");
  49.                     String name = rs.getString("name");
  50.                     String email = rs.getString("email");
  51.                     int age = rs.getInt("age");
  52.         %>
  53.                     <tr>
  54.                         <td><%= id %></td>
  55.                         <td><%= name %></td>
  56.                         <td><%= email %></td>
  57.                         <td><%= age %></td>
  58.                     </tr>
  59.         <%
  60.                 }
  61.             } catch (Exception e) {
  62.                 e.printStackTrace();
  63.             } finally {
  64.                 try {
  65.                     if (rs != null) rs.close();
  66.                     if (stmt != null) stmt.close();
  67.                     if (conn != null) conn.close();
  68.                 } catch (SQLException e) {
  69.                     e.printStackTrace();
  70.                 }
  71.             }
  72.         %>
  73.     </table>
  74. </body>
  75. </html>
复制代码

使用JSTL和EL表达式

JavaServer Pages Standard Tag Library(JSTL)和Expression Language(EL)可以简化JSP页面的开发,使代码更加清晰。首先,确保项目中包含JSTL库。如果使用Maven,添加以下依赖:
  1. <dependency>
  2.     <groupId>javax.servlet</groupId>
  3.     <artifactId>jstl</artifactId>
  4.     <version>1.2</version>
  5. </dependency>
复制代码

然后,创建一个Servlet来处理数据库操作并将结果传递给JSP页面:
  1. package servlet;
  2. import model.User;
  3. import util.DataSourceUtil;
  4. import javax.servlet.ServletException;
  5. import javax.servlet.annotation.WebServlet;
  6. import javax.servlet.http.HttpServlet;
  7. import javax.servlet.http.HttpServletRequest;
  8. import javax.servlet.http.HttpServletResponse;
  9. import javax.sql.DataSource;
  10. import java.io.IOException;
  11. import java.sql.Connection;
  12. import java.sql.ResultSet;
  13. import java.sql.Statement;
  14. import java.util.ArrayList;
  15. import java.util.List;
  16. @WebServlet("/userList")
  17. public class UserListServlet extends HttpServlet {
  18.     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  19.         List<User> userList = new ArrayList<>();
  20.         Connection conn = null;
  21.         Statement stmt = null;
  22.         ResultSet rs = null;
  23.         
  24.         try {
  25.             DataSource dataSource = DataSourceUtil.getDataSource();
  26.             conn = dataSource.getConnection();
  27.             stmt = conn.createStatement();
  28.             String sql = "SELECT * FROM users";
  29.             rs = stmt.executeQuery(sql);
  30.             
  31.             while (rs.next()) {
  32.                 User user = new User();
  33.                 user.setId(rs.getInt("id"));
  34.                 user.setName(rs.getString("name"));
  35.                 user.setEmail(rs.getString("email"));
  36.                 userList.add(user);
  37.             }
  38.         } catch (Exception e) {
  39.             e.printStackTrace();
  40.         } finally {
  41.             try {
  42.                 if (rs != null) rs.close();
  43.                 if (stmt != null) stmt.close();
  44.                 if (conn != null) conn.close();
  45.             } catch (Exception e) {
  46.                 e.printStackTrace();
  47.             }
  48.         }
  49.         
  50.         request.setAttribute("userList", userList);
  51.         request.getRequestDispatcher("/userList.jsp").forward(request, response);
  52.     }
  53. }
复制代码

在JSP页面中使用JSTL和EL表达式:
  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
  3. <html>
  4. <head>
  5.     <title>用户列表</title>
  6.     <style>
  7.         table {
  8.             border-collapse: collapse;
  9.             width: 100%;
  10.         }
  11.         th, td {
  12.             border: 1px solid #ddd;
  13.             padding: 8px;
  14.             text-align: left;
  15.         }
  16.         th {
  17.             background-color: #f2f2f2;
  18.         }
  19.         tr:nth-child(even) {
  20.             background-color: #f9f9f9;
  21.         }
  22.     </style>
  23. </head>
  24. <body>
  25.     <h1>用户列表</h1>
  26.     <table>
  27.         <tr>
  28.             <th>ID</th>
  29.             <th>姓名</th>
  30.             <th>邮箱</th>
  31.         </tr>
  32.         <c:forEach items="${userList}" var="user">
  33.             <tr>
  34.                 <td>${user.id}</td>
  35.                 <td>${user.name}</td>
  36.                 <td>${user.email}</td>
  37.             </tr>
  38.         </c:forEach>
  39.     </table>
  40. </body>
  41. </html>
复制代码

分页显示

当数据量很大时,分页显示是必要的。以下是实现分页的示例:

首先,修改Servlet以支持分页:
  1. package servlet;
  2. import model.User;
  3. import util.DataSourceUtil;
  4. import javax.servlet.ServletException;
  5. import javax.servlet.annotation.WebServlet;
  6. import javax.servlet.http.HttpServlet;
  7. import javax.servlet.http.HttpServletRequest;
  8. import javax.servlet.http.HttpServletResponse;
  9. import javax.sql.DataSource;
  10. import java.io.IOException;
  11. import java.sql.Connection;
  12. import java.sql.PreparedStatement;
  13. import java.sql.ResultSet;
  14. import java.util.ArrayList;
  15. import java.util.List;
  16. @WebServlet("/userList")
  17. public class UserListServlet extends HttpServlet {
  18.     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  19.         int page = 1;
  20.         int recordsPerPage = 5;
  21.         
  22.         if (request.getParameter("page") != null) {
  23.             page = Integer.parseInt(request.getParameter("page"));
  24.         }
  25.         
  26.         List<User> userList = new ArrayList<>();
  27.         Connection conn = null;
  28.         PreparedStatement pstmt = null;
  29.         ResultSet rs = null;
  30.         
  31.         try {
  32.             DataSource dataSource = DataSourceUtil.getDataSource();
  33.             conn = dataSource.getConnection();
  34.             
  35.             // 计算总记录数
  36.             String countSql = "SELECT COUNT(*) FROM users";
  37.             pstmt = conn.prepareStatement(countSql);
  38.             rs = pstmt.executeQuery();
  39.             if (rs.next()) {
  40.                 int noOfRecords = rs.getInt(1);
  41.                 int noOfPages = (int) Math.ceil(noOfRecords * 1.0 / recordsPerPage);
  42.                 request.setAttribute("noOfPages", noOfPages);
  43.             }
  44.             rs.close();
  45.             pstmt.close();
  46.             
  47.             // 获取当前页的数据
  48.             String sql = "SELECT * FROM users LIMIT ?, ?";
  49.             pstmt = conn.prepareStatement(sql);
  50.             pstmt.setInt(1, (page - 1) * recordsPerPage);
  51.             pstmt.setInt(2, recordsPerPage);
  52.             rs = pstmt.executeQuery();
  53.             
  54.             while (rs.next()) {
  55.                 User user = new User();
  56.                 user.setId(rs.getInt("id"));
  57.                 user.setName(rs.getString("name"));
  58.                 user.setEmail(rs.getString("email"));
  59.                 userList.add(user);
  60.             }
  61.         } catch (Exception e) {
  62.             e.printStackTrace();
  63.         } finally {
  64.             try {
  65.                 if (rs != null) rs.close();
  66.                 if (pstmt != null) pstmt.close();
  67.                 if (conn != null) conn.close();
  68.             } catch (Exception e) {
  69.                 e.printStackTrace();
  70.             }
  71.         }
  72.         
  73.         request.setAttribute("userList", userList);
  74.         request.setAttribute("currentPage", page);
  75.         request.getRequestDispatcher("/userList.jsp").forward(request, response);
  76.     }
  77. }
复制代码

然后,在JSP页面中添加分页控件:
  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
  3. <html>
  4. <head>
  5.     <title>用户列表</title>
  6.     <style>
  7.         table {
  8.             border-collapse: collapse;
  9.             width: 100%;
  10.         }
  11.         th, td {
  12.             border: 1px solid #ddd;
  13.             padding: 8px;
  14.             text-align: left;
  15.         }
  16.         th {
  17.             background-color: #f2f2f2;
  18.         }
  19.         tr:nth-child(even) {
  20.             background-color: #f9f9f9;
  21.         }
  22.         .pagination {
  23.             display: inline-block;
  24.             margin-top: 20px;
  25.         }
  26.         .pagination a {
  27.             color: black;
  28.             float: left;
  29.             padding: 8px 16px;
  30.             text-decoration: none;
  31.             border: 1px solid #ddd;
  32.         }
  33.         .pagination a.active {
  34.             background-color: #4CAF50;
  35.             color: white;
  36.         }
  37.         .pagination a:hover:not(.active) {
  38.             background-color: #ddd;
  39.         }
  40.     </style>
  41. </head>
  42. <body>
  43.     <h1>用户列表</h1>
  44.     <table>
  45.         <tr>
  46.             <th>ID</th>
  47.             <th>姓名</th>
  48.             <th>邮箱</th>
  49.         </tr>
  50.         <c:forEach items="${userList}" var="user">
  51.             <tr>
  52.                 <td>${user.id}</td>
  53.                 <td>${user.name}</td>
  54.                 <td>${user.email}</td>
  55.             </tr>
  56.         </c:forEach>
  57.     </table>
  58.    
  59.     <div class="pagination">
  60.         <c:if test="${currentPage != 1}">
  61.             <a href="userList?page=${currentPage - 1}">上一页</a>
  62.         </c:if>
  63.         
  64.         <c:forEach begin="1" end="${noOfPages}" var="i">
  65.             <c:choose>
  66.                 <c:when test="${currentPage eq i}">
  67.                     <a href="#" class="active">${i}</a>
  68.                 </c:when>
  69.                 <c:otherwise>
  70.                     <a href="userList?page=${i}">${i}</a>
  71.                 </c:otherwise>
  72.             </c:choose>
  73.         </c:forEach>
  74.         
  75.         <c:if test="${currentPage lt noOfPages}">
  76.             <a href="userList?page=${currentPage + 1}">下一页</a>
  77.         </c:if>
  78.     </div>
  79. </body>
  80. </html>
复制代码

高级技巧

搜索功能

实现搜索功能需要修改Servlet和JSP页面。以下是实现搜索功能的示例:

修改Servlet以支持搜索:
  1. package servlet;
  2. import model.User;
  3. import util.DataSourceUtil;
  4. import javax.servlet.ServletException;
  5. import javax.servlet.annotation.WebServlet;
  6. import javax.servlet.http.HttpServlet;
  7. import javax.servlet.http.HttpServletRequest;
  8. import javax.servlet.http.HttpServletResponse;
  9. import javax.sql.DataSource;
  10. import java.io.IOException;
  11. import java.sql.Connection;
  12. import java.sql.PreparedStatement;
  13. import java.sql.ResultSet;
  14. import java.util.ArrayList;
  15. import java.util.List;
  16. @WebServlet("/userSearch")
  17. public class UserSearchServlet extends HttpServlet {
  18.     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  19.         String searchKeyword = request.getParameter("searchKeyword");
  20.         
  21.         List<User> userList = new ArrayList<>();
  22.         Connection conn = null;
  23.         PreparedStatement pstmt = null;
  24.         ResultSet rs = null;
  25.         
  26.         try {
  27.             DataSource dataSource = DataSourceUtil.getDataSource();
  28.             conn = dataSource.getConnection();
  29.             
  30.             String sql = "SELECT * FROM users WHERE name LIKE ? OR email LIKE ?";
  31.             pstmt = conn.prepareStatement(sql);
  32.             pstmt.setString(1, "%" + searchKeyword + "%");
  33.             pstmt.setString(2, "%" + searchKeyword + "%");
  34.             
  35.             rs = pstmt.executeQuery();
  36.             
  37.             while (rs.next()) {
  38.                 User user = new User();
  39.                 user.setId(rs.getInt("id"));
  40.                 user.setName(rs.getString("name"));
  41.                 user.setEmail(rs.getString("email"));
  42.                 userList.add(user);
  43.             }
  44.         } catch (Exception e) {
  45.             e.printStackTrace();
  46.         } finally {
  47.             try {
  48.                 if (rs != null) rs.close();
  49.                 if (pstmt != null) pstmt.close();
  50.                 if (conn != null) conn.close();
  51.             } catch (Exception e) {
  52.                 e.printStackTrace();
  53.             }
  54.         }
  55.         
  56.         request.setAttribute("userList", userList);
  57.         request.setAttribute("searchKeyword", searchKeyword);
  58.         request.getRequestDispatcher("/userSearch.jsp").forward(request, response);
  59.     }
  60. }
复制代码

在JSP页面中添加搜索表单:
  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
  3. <html>
  4. <head>
  5.     <title>用户搜索</title>
  6.     <style>
  7.         table {
  8.             border-collapse: collapse;
  9.             width: 100%;
  10.             margin-top: 20px;
  11.         }
  12.         th, td {
  13.             border: 1px solid #ddd;
  14.             padding: 8px;
  15.             text-align: left;
  16.         }
  17.         th {
  18.             background-color: #f2f2f2;
  19.         }
  20.         tr:nth-child(even) {
  21.             background-color: #f9f9f9;
  22.         }
  23.         .search-form {
  24.             margin-bottom: 20px;
  25.         }
  26.         .search-form input[type="text"] {
  27.             padding: 8px;
  28.             width: 300px;
  29.         }
  30.         .search-form input[type="submit"] {
  31.             padding: 8px 16px;
  32.             background-color: #4CAF50;
  33.             color: white;
  34.             border: none;
  35.             cursor: pointer;
  36.         }
  37.     </style>
  38. </head>
  39. <body>
  40.     <h1>用户搜索</h1>
  41.    
  42.     <form class="search-form" action="userSearch" method="post">
  43.         <input type="text" name="searchKeyword" value="${searchKeyword}" placeholder="输入姓名或邮箱">
  44.         <input type="submit" value="搜索">
  45.     </form>
  46.    
  47.     <c:if test="${not empty userList}">
  48.         <table>
  49.             <tr>
  50.                 <th>ID</th>
  51.                 <th>姓名</th>
  52.                 <th>邮箱</th>
  53.             </tr>
  54.             <c:forEach items="${userList}" var="user">
  55.                 <tr>
  56.                     <td>${user.id}</td>
  57.                     <td>${user.name}</td>
  58.                     <td>${user.email}</td>
  59.                 </tr>
  60.             </c:forEach>
  61.         </table>
  62.     </c:if>
  63.    
  64.     <c:if test="${empty userList and not empty searchKeyword}">
  65.         <p>没有找到包含 "${searchKeyword}" 的用户</p>
  66.     </c:if>
  67. </body>
  68. </html>
复制代码

排序功能

实现排序功能需要修改Servlet和JSP页面。以下是实现排序功能的示例:

修改Servlet以支持排序:
  1. package servlet;
  2. import model.User;
  3. import util.DataSourceUtil;
  4. import javax.servlet.ServletException;
  5. import javax.servlet.annotation.WebServlet;
  6. import javax.servlet.http.HttpServlet;
  7. import javax.servlet.http.HttpServletRequest;
  8. import javax.servlet.http.HttpServletResponse;
  9. import javax.sql.DataSource;
  10. import java.io.IOException;
  11. import java.sql.Connection;
  12. import java.sql.PreparedStatement;
  13. import java.sql.ResultSet;
  14. import java.util.ArrayList;
  15. import java.util.List;
  16. @WebServlet("/userSort")
  17. public class UserSortServlet extends HttpServlet {
  18.     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  19.         String sortField = request.getParameter("sortField");
  20.         String sortOrder = request.getParameter("sortOrder");
  21.         
  22.         if (sortField == null || sortField.isEmpty()) {
  23.             sortField = "id";
  24.         }
  25.         
  26.         if (sortOrder == null || sortOrder.isEmpty()) {
  27.             sortOrder = "ASC";
  28.         }
  29.         
  30.         List<User> userList = new ArrayList<>();
  31.         Connection conn = null;
  32.         PreparedStatement pstmt = null;
  33.         ResultSet rs = null;
  34.         
  35.         try {
  36.             DataSource dataSource = DataSourceUtil.getDataSource();
  37.             conn = dataSource.getConnection();
  38.             
  39.             String sql = "SELECT * FROM users ORDER BY " + sortField + " " + sortOrder;
  40.             pstmt = conn.prepareStatement(sql);
  41.             
  42.             rs = pstmt.executeQuery();
  43.             
  44.             while (rs.next()) {
  45.                 User user = new User();
  46.                 user.setId(rs.getInt("id"));
  47.                 user.setName(rs.getString("name"));
  48.                 user.setEmail(rs.getString("email"));
  49.                 userList.add(user);
  50.             }
  51.         } catch (Exception e) {
  52.             e.printStackTrace();
  53.         } finally {
  54.             try {
  55.                 if (rs != null) rs.close();
  56.                 if (pstmt != null) pstmt.close();
  57.                 if (conn != null) conn.close();
  58.             } catch (Exception e) {
  59.                 e.printStackTrace();
  60.             }
  61.         }
  62.         
  63.         request.setAttribute("userList", userList);
  64.         request.setAttribute("sortField", sortField);
  65.         request.setAttribute("sortOrder", sortOrder);
  66.         request.getRequestDispatcher("/userSort.jsp").forward(request, response);
  67.     }
  68. }
复制代码

在JSP页面中添加排序功能:
  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
  3. <html>
  4. <head>
  5.     <title>用户排序</title>
  6.     <style>
  7.         table {
  8.             border-collapse: collapse;
  9.             width: 100%;
  10.         }
  11.         th, td {
  12.             border: 1px solid #ddd;
  13.             padding: 8px;
  14.             text-align: left;
  15.         }
  16.         th {
  17.             background-color: #f2f2f2;
  18.             cursor: pointer;
  19.         }
  20.         tr:nth-child(even) {
  21.             background-color: #f9f9f9;
  22.         }
  23.         .sort-controls {
  24.             margin-bottom: 20px;
  25.         }
  26.     </style>
  27. </head>
  28. <body>
  29.     <h1>用户排序</h1>
  30.    
  31.     <div class="sort-controls">
  32.         <a href="userSort?sortField=id&sortOrder=${sortField eq 'id' and sortOrder eq 'ASC' ? 'DESC' : 'ASC'}">
  33.             按ID ${sortField eq 'id' and sortOrder eq 'ASC' ? '↓' : '↑'} 排序
  34.         </a>
  35.         |
  36.         <a href="userSort?sortField=name&sortOrder=${sortField eq 'name' and sortOrder eq 'ASC' ? 'DESC' : 'ASC'}">
  37.             按姓名 ${sortField eq 'name' and sortOrder eq 'ASC' ? '↓' : '↑'} 排序
  38.         </a>
  39.         |
  40.         <a href="userSort?sortField=email&sortOrder=${sortField eq 'email' and sortOrder eq 'ASC' ? 'DESC' : 'ASC'}">
  41.             按邮箱 ${sortField eq 'email' and sortOrder eq 'ASC' ? '↓' : '↑'} 排序
  42.         </a>
  43.     </div>
  44.    
  45.     <table>
  46.         <tr>
  47.             <th onclick="location.href='userSort?sortField=id&sortOrder=${sortField eq 'id' and sortOrder eq 'ASC' ? 'DESC' : 'ASC'}'">
  48.                 ID ${sortField eq 'id' and sortOrder eq 'ASC' ? '↑' : '↓'}
  49.             </th>
  50.             <th onclick="location.href='userSort?sortField=name&sortOrder=${sortField eq 'name' and sortOrder eq 'ASC' ? 'DESC' : 'ASC'}'">
  51.                 姓名 ${sortField eq 'name' and sortOrder eq 'ASC' ? '↑' : '↓'}
  52.             </th>
  53.             <th onclick="location.href='userSort?sortField=email&sortOrder=${sortField eq 'email' and sortOrder eq 'ASC' ? 'DESC' : 'ASC'}'">
  54.                 邮箱 ${sortField eq 'email' and sortOrder eq 'ASC' ? '↑' : '↓'}
  55.             </th>
  56.         </tr>
  57.         <c:forEach items="${userList}" var="user">
  58.             <tr>
  59.                 <td>${user.id}</td>
  60.                 <td>${user.name}</td>
  61.                 <td>${user.email}</td>
  62.             </tr>
  63.         </c:forEach>
  64.     </table>
  65. </body>
  66. </html>
复制代码

安全性考虑

SQL注入防护

SQL注入是一种常见的网络安全漏洞,攻击者可以通过在输入中插入恶意SQL代码来操纵数据库查询。使用PreparedStatement可以有效防止SQL注入:
  1. <%@ page import="java.sql.*" %>
  2. <%@ page import="util.DataSourceUtil" %>
  3. <%@ page import="javax.sql.DataSource" %>
  4. <%
  5.     String userId = request.getParameter("id");
  6.    
  7.     Connection conn = null;
  8.     PreparedStatement pstmt = null;
  9.     ResultSet rs = null;
  10.    
  11.     try {
  12.         DataSource dataSource = DataSourceUtil.getDataSource();
  13.         conn = dataSource.getConnection();
  14.         
  15.         // 使用PreparedStatement防止SQL注入
  16.         String sql = "SELECT * FROM users WHERE id = ?";
  17.         pstmt = conn.prepareStatement(sql);
  18.         pstmt.setString(1, userId);
  19.         
  20.         rs = pstmt.executeQuery();
  21.         
  22.         if (rs.next()) {
  23.             String name = rs.getString("name");
  24.             String email = rs.getString("email");
  25.             out.println("Name: " + name + ", Email: " + email);
  26.         } else {
  27.             out.println("User not found");
  28.         }
  29.     } catch (Exception e) {
  30.         e.printStackTrace();
  31.     } finally {
  32.         try {
  33.             if (rs != null) rs.close();
  34.             if (pstmt != null) pstmt.close();
  35.             if (conn != null) conn.close();
  36.         } catch (SQLException e) {
  37.             e.printStackTrace();
  38.         }
  39.     }
  40. %>
复制代码

输入验证

除了使用PreparedStatement,还应该对用户输入进行验证:
  1. <%@ page import="java.sql.*" %>
  2. <%@ page import="util.DataSourceUtil" %>
  3. <%@ page import="javax.sql.DataSource" %>
  4. <%@ page import="java.util.regex.Pattern" %>
  5. <%
  6.     String userId = request.getParameter("id");
  7.    
  8.     // 输入验证:确保ID是数字
  9.     if (userId == null || !Pattern.matches("\\d+", userId)) {
  10.         out.println("Invalid user ID");
  11.         return;
  12.     }
  13.    
  14.     Connection conn = null;
  15.     PreparedStatement pstmt = null;
  16.     ResultSet rs = null;
  17.    
  18.     try {
  19.         DataSource dataSource = DataSourceUtil.getDataSource();
  20.         conn = dataSource.getConnection();
  21.         
  22.         String sql = "SELECT * FROM users WHERE id = ?";
  23.         pstmt = conn.prepareStatement(sql);
  24.         pstmt.setInt(1, Integer.parseInt(userId));
  25.         
  26.         rs = pstmt.executeQuery();
  27.         
  28.         if (rs.next()) {
  29.             String name = rs.getString("name");
  30.             String email = rs.getString("email");
  31.             out.println("Name: " + name + ", Email: " + email);
  32.         } else {
  33.             out.println("User not found");
  34.         }
  35.     } catch (Exception e) {
  36.         e.printStackTrace();
  37.     } finally {
  38.         try {
  39.             if (rs != null) rs.close();
  40.             if (pstmt != null) pstmt.close();
  41.             if (conn != null) conn.close();
  42.         } catch (SQLException e) {
  43.             e.printStackTrace();
  44.         }
  45.     }
  46. %>
复制代码

输出编码

为了防止XSS(跨站脚本)攻击,应该对输出进行编码:
  1. <%@ page import="org.apache.commons.text.StringEscapeUtils" %>
  2. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  3. <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
  4. <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
  5. <html>
  6. <head>
  7.     <title>安全输出示例</title>
  8. </head>
  9. <body>
  10.     <h1>用户信息</h1>
  11.    
  12.     <%-- 使用JSTL的fn:escapeXml函数进行输出编码 --%>
  13.     <c:out value="${user.name}" escapeXml="true"/>
  14.    
  15.     <%-- 或者使用fn:escapeXml函数 --%>
  16.     ${fn:escapeXml(user.name)}
  17.    
  18.     <%-- 在脚本片段中使用StringEscapeUtils --%>
  19.     <%
  20.         String userInput = "<script>alert('XSS Attack');</script>";
  21.         String safeOutput = StringEscapeUtils.escapeHtml4(userInput);
  22.         out.println(safeOutput);
  23.     %>
  24. </body>
  25. </html>
复制代码

使用连接池

使用连接池不仅可以提高性能,还可以增强安全性。连接池可以限制最大连接数,防止数据库过载,并且可以管理连接的生命周期,确保连接正确关闭。

以下是使用Tomcat JDBC连接池的配置示例:

在context.xml中配置连接池:
  1. <Context>
  2.     <Resource name="jdbc/myDB"
  3.               auth="Container"
  4.               type="javax.sql.DataSource"
  5.               maxTotal="100"
  6.               maxIdle="30"
  7.               maxWaitMillis="10000"
  8.               username="root"
  9.               password="password"
  10.               driverClassName="com.mysql.jdbc.Driver"
  11.               url="jdbc:mysql://localhost:3306/mydatabase?useSSL=false&amp;serverTimezone=UTC"/>
  12. </Context>
复制代码

在web.xml中引用资源:
  1. <web-app>
  2.     <resource-ref>
  3.         <description>MySQL DataSource</description>
  4.         <res-ref-name>jdbc/myDB</res-ref-name>
  5.         <res-type>javax.sql.DataSource</res-type>
  6.         <res-auth>Container</res-auth>
  7.     </resource-ref>
  8. </web-app>
复制代码

在JSP页面中使用连接池:
  1. <%@ page import="javax.sql.DataSource" %>
  2. <%@ page import="javax.naming.InitialContext" %>
  3. <%@ page import="java.sql.*" %>
  4. <%
  5.     Connection conn = null;
  6.     Statement stmt = null;
  7.     ResultSet rs = null;
  8.    
  9.     try {
  10.         // 获取JNDI上下文
  11.         InitialContext ctx = new InitialContext();
  12.         
  13.         // 查找数据源
  14.         DataSource dataSource = (DataSource) ctx.lookup("java:comp/env/jdbc/myDB");
  15.         
  16.         // 获取连接
  17.         conn = dataSource.getConnection();
  18.         
  19.         // 创建Statement并执行查询
  20.         stmt = conn.createStatement();
  21.         String sql = "SELECT * FROM users";
  22.         rs = stmt.executeQuery(sql);
  23.         
  24.         // 处理结果集
  25.         while (rs.next()) {
  26.             int id = rs.getInt("id");
  27.             String name = rs.getString("name");
  28.             String email = rs.getString("email");
  29.             out.println("ID: " + id + ", Name: " + name + ", Email: " + email + "<br>");
  30.         }
  31.     } catch (Exception e) {
  32.         e.printStackTrace();
  33.     } finally {
  34.         // 关闭资源
  35.         try {
  36.             if (rs != null) rs.close();
  37.             if (stmt != null) stmt.close();
  38.             if (conn != null) conn.close();
  39.         } catch (SQLException e) {
  40.             e.printStackTrace();
  41.         }
  42.     }
  43. %>
复制代码

最佳实践和性能优化

MVC架构模式

在实际项目中,应该采用MVC(Model-View-Controller)架构模式,将业务逻辑、数据和表示分离。以下是一个简单的MVC示例:

1. Model(模型):JavaBean和DAO(Data Access Object)
  1. package model;
  2. public class User {
  3.     private int id;
  4.     private String name;
  5.     private String email;
  6.    
  7.     // 构造方法、getter和setter
  8.     // ...
  9. }
复制代码
  1. package dao;
  2. import model.User;
  3. import util.DataSourceUtil;
  4. import javax.sql.DataSource;
  5. import java.sql.*;
  6. import java.util.ArrayList;
  7. import java.util.List;
  8. public class UserDAO {
  9.     private DataSource dataSource;
  10.    
  11.     public UserDAO() {
  12.         this.dataSource = DataSourceUtil.getDataSource();
  13.     }
  14.    
  15.     public List<User> getAllUsers() {
  16.         List<User> users = new ArrayList<>();
  17.         String sql = "SELECT * FROM users";
  18.         
  19.         try (Connection conn = dataSource.getConnection();
  20.              Statement stmt = conn.createStatement();
  21.              ResultSet rs = stmt.executeQuery(sql)) {
  22.             
  23.             while (rs.next()) {
  24.                 User user = new User();
  25.                 user.setId(rs.getInt("id"));
  26.                 user.setName(rs.getString("name"));
  27.                 user.setEmail(rs.getString("email"));
  28.                 users.add(user);
  29.             }
  30.         } catch (SQLException e) {
  31.             e.printStackTrace();
  32.         }
  33.         
  34.         return users;
  35.     }
  36.    
  37.     public User getUserById(int id) {
  38.         User user = null;
  39.         String sql = "SELECT * FROM users WHERE id = ?";
  40.         
  41.         try (Connection conn = dataSource.getConnection();
  42.              PreparedStatement pstmt = conn.prepareStatement(sql)) {
  43.             
  44.             pstmt.setInt(1, id);
  45.             
  46.             try (ResultSet rs = pstmt.executeQuery()) {
  47.                 if (rs.next()) {
  48.                     user = new User();
  49.                     user.setId(rs.getInt("id"));
  50.                     user.setName(rs.getString("name"));
  51.                     user.setEmail(rs.getString("email"));
  52.                 }
  53.             }
  54.         } catch (SQLException e) {
  55.             e.printStackTrace();
  56.         }
  57.         
  58.         return user;
  59.     }
  60.    
  61.     public boolean addUser(User user) {
  62.         String sql = "INSERT INTO users (name, email) VALUES (?, ?)";
  63.         
  64.         try (Connection conn = dataSource.getConnection();
  65.              PreparedStatement pstmt = conn.prepareStatement(sql)) {
  66.             
  67.             pstmt.setString(1, user.getName());
  68.             pstmt.setString(2, user.getEmail());
  69.             
  70.             int rowsAffected = pstmt.executeUpdate();
  71.             return rowsAffected > 0;
  72.         } catch (SQLException e) {
  73.             e.printStackTrace();
  74.             return false;
  75.         }
  76.     }
  77.    
  78.     public boolean updateUser(User user) {
  79.         String sql = "UPDATE users SET name = ?, email = ? WHERE id = ?";
  80.         
  81.         try (Connection conn = dataSource.getConnection();
  82.              PreparedStatement pstmt = conn.prepareStatement(sql)) {
  83.             
  84.             pstmt.setString(1, user.getName());
  85.             pstmt.setString(2, user.getEmail());
  86.             pstmt.setInt(3, user.getId());
  87.             
  88.             int rowsAffected = pstmt.executeUpdate();
  89.             return rowsAffected > 0;
  90.         } catch (SQLException e) {
  91.             e.printStackTrace();
  92.             return false;
  93.         }
  94.     }
  95.    
  96.     public boolean deleteUser(int id) {
  97.         String sql = "DELETE FROM users WHERE id = ?";
  98.         
  99.         try (Connection conn = dataSource.getConnection();
  100.              PreparedStatement pstmt = conn.prepareStatement(sql)) {
  101.             
  102.             pstmt.setInt(1, id);
  103.             
  104.             int rowsAffected = pstmt.executeUpdate();
  105.             return rowsAffected > 0;
  106.         } catch (SQLException e) {
  107.             e.printStackTrace();
  108.             return false;
  109.         }
  110.     }
  111. }
复制代码

1. Controller(控制器):Servlet
  1. package servlet;
  2. import dao.UserDAO;
  3. import model.User;
  4. import javax.servlet.ServletException;
  5. import javax.servlet.annotation.WebServlet;
  6. import javax.servlet.http.HttpServlet;
  7. import javax.servlet.http.HttpServletRequest;
  8. import javax.servlet.http.HttpServletResponse;
  9. import java.io.IOException;
  10. import java.util.List;
  11. @WebServlet("/users")
  12. public class UserController extends HttpServlet {
  13.     private UserDAO userDAO;
  14.    
  15.     public void init() {
  16.         userDAO = new UserDAO();
  17.     }
  18.    
  19.     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  20.         String action = request.getParameter("action");
  21.         
  22.         if (action == null) {
  23.             action = "list";
  24.         }
  25.         
  26.         switch (action) {
  27.             case "edit":
  28.                 showEditForm(request, response);
  29.                 break;
  30.             case "delete":
  31.                 deleteUser(request, response);
  32.                 break;
  33.             case "view":
  34.                 viewUser(request, response);
  35.                 break;
  36.             default:
  37.                 listUsers(request, response);
  38.                 break;
  39.         }
  40.     }
  41.    
  42.     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  43.         String action = request.getParameter("action");
  44.         
  45.         if (action == null) {
  46.             action = "list";
  47.         }
  48.         
  49.         switch (action) {
  50.             case "add":
  51.                 addUser(request, response);
  52.                 break;
  53.             case "update":
  54.                 updateUser(request, response);
  55.                 break;
  56.             default:
  57.                 listUsers(request, response);
  58.                 break;
  59.         }
  60.     }
  61.    
  62.     private void listUsers(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  63.         List<User> userList = userDAO.getAllUsers();
  64.         request.setAttribute("userList", userList);
  65.         request.getRequestDispatcher("/userList.jsp").forward(request, response);
  66.     }
  67.    
  68.     private void showEditForm(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  69.         int id = Integer.parseInt(request.getParameter("id"));
  70.         User existingUser = userDAO.getUserById(id);
  71.         request.setAttribute("user", existingUser);
  72.         request.getRequestDispatcher("/userForm.jsp").forward(request, response);
  73.     }
  74.    
  75.     private void viewUser(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  76.         int id = Integer.parseInt(request.getParameter("id"));
  77.         User user = userDAO.getUserById(id);
  78.         request.setAttribute("user", user);
  79.         request.getRequestDispatcher("/userView.jsp").forward(request, response);
  80.     }
  81.    
  82.     private void addUser(HttpServletRequest request, HttpServletResponse response) throws IOException {
  83.         String name = request.getParameter("name");
  84.         String email = request.getParameter("email");
  85.         
  86.         User newUser = new User();
  87.         newUser.setName(name);
  88.         newUser.setEmail(email);
  89.         
  90.         userDAO.addUser(newUser);
  91.         response.sendRedirect("users?action=list");
  92.     }
  93.    
  94.     private void updateUser(HttpServletRequest request, HttpServletResponse response) throws IOException {
  95.         int id = Integer.parseInt(request.getParameter("id"));
  96.         String name = request.getParameter("name");
  97.         String email = request.getParameter("email");
  98.         
  99.         User user = new User();
  100.         user.setId(id);
  101.         user.setName(name);
  102.         user.setEmail(email);
  103.         
  104.         userDAO.updateUser(user);
  105.         response.sendRedirect("users?action=list");
  106.     }
  107.    
  108.     private void deleteUser(HttpServletRequest request, HttpServletResponse response) throws IOException {
  109.         int id = Integer.parseInt(request.getParameter("id"));
  110.         userDAO.deleteUser(id);
  111.         response.sendRedirect("users?action=list");
  112.     }
  113. }
复制代码

1. View(视图):JSP页面
  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
  3. <html>
  4. <head>
  5.     <title>用户列表</title>
  6.     <style>
  7.         table {
  8.             border-collapse: collapse;
  9.             width: 100%;
  10.         }
  11.         th, td {
  12.             border: 1px solid #ddd;
  13.             padding: 8px;
  14.             text-align: left;
  15.         }
  16.         th {
  17.             background-color: #f2f2f2;
  18.         }
  19.         tr:nth-child(even) {
  20.             background-color: #f9f9f9;
  21.         }
  22.         .actions a {
  23.             margin-right: 10px;
  24.         }
  25.     </style>
  26. </head>
  27. <body>
  28.     <h1>用户列表</h1>
  29.    
  30.     <p>
  31.         <a href="userForm.jsp?action=add">添加新用户</a>
  32.     </p>
  33.    
  34.     <table>
  35.         <tr>
  36.             <th>ID</th>
  37.             <th>姓名</th>
  38.             <th>邮箱</th>
  39.             <th>操作</th>
  40.         </tr>
  41.         <c:forEach items="${userList}" var="user">
  42.             <tr>
  43.                 <td>${user.id}</td>
  44.                 <td>${user.name}</td>
  45.                 <td>${user.email}</td>
  46.                 <td class="actions">
  47.                     <a href="users?action=view&id=${user.id}">查看</a>
  48.                     <a href="users?action=edit&id=${user.id}">编辑</a>
  49.                     <a href="users?action=delete&id=${user.id}" onclick="return confirm('确定要删除这个用户吗?')">删除</a>
  50.                 </td>
  51.             </tr>
  52.         </c:forEach>
  53.     </table>
  54. </body>
  55. </html>
复制代码

使用ORM框架

虽然直接使用JDBC可以完成数据库操作,但在大型项目中,使用ORM(Object-Relational Mapping)框架如Hibernate或MyBatis可以大大简化开发工作。以下是使用MyBatis的简单示例:

首先,添加MyBatis依赖:
  1. <dependency>
  2.     <groupId>org.mybatis</groupId>
  3.     <artifactId>mybatis</artifactId>
  4.     <version>3.5.7</version>
  5. </dependency>
  6. <dependency>
  7.     <groupId>org.mybatis</groupId>
  8.     <artifactId>mybatis-spring</artifactId>
  9.     <version>2.0.6</version>
  10. </dependency>
复制代码

创建MyBatis配置文件:
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE configuration
  3.         PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  4.         "http://mybatis.org/dtd/mybatis-3-config.dtd">
  5. <configuration>
  6.     <environments default="development">
  7.         <environment id="development">
  8.             <transactionManager type="JDBC"/>
  9.             <dataSource type="POOLED">
  10.                 <property name="driver" value="com.mysql.jdbc.Driver"/>
  11.                 <property name="url" value="jdbc:mysql://localhost:3306/mydatabase?useSSL=false&amp;serverTimezone=UTC"/>
  12.                 <property name="username" value="root"/>
  13.                 <property name="password" value="password"/>
  14.             </dataSource>
  15.         </environment>
  16.     </environments>
  17.     <mappers>
  18.         <mapper resource="mapper/UserMapper.xml"/>
  19.     </mappers>
  20. </configuration>
复制代码

创建Mapper接口:
  1. package mapper;
  2. import model.User;
  3. import java.util.List;
  4. public interface UserMapper {
  5.     List<User> getAllUsers();
  6.     User getUserById(int id);
  7.     void insertUser(User user);
  8.     void updateUser(User user);
  9.     void deleteUser(int id);
  10. }
复制代码

创建Mapper XML文件:
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3.         PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4.         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="mapper.UserMapper">
  6.     <select id="getAllUsers" resultType="model.User">
  7.         SELECT * FROM users
  8.     </select>
  9.    
  10.     <select id="getUserById" resultType="model.User" parameterType="int">
  11.         SELECT * FROM users WHERE id = #{id}
  12.     </select>
  13.    
  14.     <insert id="insertUser" parameterType="model.User">
  15.         INSERT INTO users (name, email) VALUES (#{name}, #{email})
  16.     </insert>
  17.    
  18.     <update id="updateUser" parameterType="model.User">
  19.         UPDATE users SET name = #{name}, email = #{email} WHERE id = #{id}
  20.     </update>
  21.    
  22.     <delete id="deleteUser" parameterType="int">
  23.         DELETE FROM users WHERE id = #{id}
  24.     </delete>
  25. </mapper>
复制代码

创建MyBatis工具类:
  1. package util;
  2. import org.apache.ibatis.io.Resources;
  3. import org.apache.ibatis.session.SqlSession;
  4. import org.apache.ibatis.session.SqlSessionFactory;
  5. import org.apache.ibatis.session.SqlSessionFactoryBuilder;
  6. import java.io.IOException;
  7. import java.io.Reader;
  8. public class MyBatisUtil {
  9.     private static SqlSessionFactory factory;
  10.    
  11.     static {
  12.         try {
  13.             Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
  14.             factory = new SqlSessionFactoryBuilder().build(reader);
  15.         } catch (IOException e) {
  16.             e.printStackTrace();
  17.         }
  18.     }
  19.    
  20.     public static SqlSession getSqlSession() {
  21.         return factory.openSession();
  22.     }
  23. }
复制代码

在Servlet中使用MyBatis:
  1. package servlet;
  2. import mapper.UserMapper;
  3. import model.User;
  4. import util.MyBatisUtil;
  5. import javax.servlet.ServletException;
  6. import javax.servlet.annotation.WebServlet;
  7. import javax.servlet.http.HttpServlet;
  8. import javax.servlet.http.HttpServletRequest;
  9. import javax.servlet.http.HttpServletResponse;
  10. import java.io.IOException;
  11. import java.util.List;
  12. @WebServlet("/mybatisUsers")
  13. public class MyBatisUserServlet extends HttpServlet {
  14.     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  15.         List<User> userList = null;
  16.         
  17.         try (SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
  18.             UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
  19.             userList = userMapper.getAllUsers();
  20.         } catch (Exception e) {
  21.             e.printStackTrace();
  22.         }
  23.         
  24.         request.setAttribute("userList", userList);
  25.         request.getRequestDispatcher("/userList.jsp").forward(request, response);
  26.     }
  27. }
复制代码

性能优化

1. 使用缓存

MyBatis提供了一级缓存和二级缓存。一级缓存是SqlSession级别的缓存,默认开启。二级缓存是Mapper级别的缓存,需要手动配置。

在Mapper XML文件中启用二级缓存:
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3.         PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4.         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="mapper.UserMapper">
  6.     <cache/>
  7.    
  8.     <select id="getAllUsers" resultType="model.User" useCache="true">
  9.         SELECT * FROM users
  10.     </select>
  11.    
  12.     <!-- 其他SQL语句 -->
  13. </mapper>
复制代码

1. 批量操作

对于大量数据的插入、更新或删除,使用批量操作可以显著提高性能:
  1. package dao;
  2. import model.User;
  3. import util.DataSourceUtil;
  4. import javax.sql.DataSource;
  5. import java.sql.Connection;
  6. import java.sql.PreparedStatement;
  7. import java.sql.SQLException;
  8. import java.util.List;
  9. public class UserBatchDAO {
  10.     private DataSource dataSource;
  11.    
  12.     public UserBatchDAO() {
  13.         this.dataSource = DataSourceUtil.getDataSource();
  14.     }
  15.    
  16.     public void batchInsertUsers(List<User> users) {
  17.         String sql = "INSERT INTO users (name, email) VALUES (?, ?)";
  18.         
  19.         try (Connection conn = dataSource.getConnection();
  20.              PreparedStatement pstmt = conn.prepareStatement(sql)) {
  21.             
  22.             // 关闭自动提交
  23.             conn.setAutoCommit(false);
  24.             
  25.             for (User user : users) {
  26.                 pstmt.setString(1, user.getName());
  27.                 pstmt.setString(2, user.getEmail());
  28.                 pstmt.addBatch();
  29.             }
  30.             
  31.             // 执行批量操作
  32.             int[] results = pstmt.executeBatch();
  33.             
  34.             // 提交事务
  35.             conn.commit();
  36.             
  37.             System.out.println("批量插入了 " + results.length + " 条记录");
  38.         } catch (SQLException e) {
  39.             e.printStackTrace();
  40.         }
  41.     }
  42. }
复制代码

1. 使用连接池

前面已经介绍了连接池的使用,这里再次强调其重要性。连接池可以重用数据库连接,减少创建和销毁连接的开销,提高系统性能。

1. 优化SQL查询

• 只查询需要的字段,避免使用SELECT *
• 使用索引提高查询速度
• 避免在循环中执行查询
• 使用JOIN代替多个查询
  1. // 不好的做法:N+1查询问题
  2. List<User> users = userDAO.getAllUsers();
  3. for (User user : users) {
  4.     List<Order> orders = orderDAO.getOrdersByUserId(user.getId());
  5.     user.setOrders(orders);
  6. }
  7. // 好的做法:使用JOIN一次性获取所有数据
  8. List<User> users = userDAO.getAllUsersWithOrders();
复制代码

总结与展望

本文详细介绍了JSP页面实现数据库信息动态显示的方法与实践,从基础的数据库连接到完整的数据展示流程。我们学习了如何使用JDBC连接数据库,如何在JSP页面中展示数据,以及如何实现分页、搜索和排序等高级功能。同时,我们也讨论了安全性考虑和性能优化的最佳实践。

在实际开发中,建议采用MVC架构模式,将业务逻辑、数据和表示分离。对于大型项目,可以考虑使用ORM框架如MyBatis或Hibernate来简化数据库操作。此外,还应该注意安全性问题,如SQL注入防护和XSS攻击防护,以及性能优化,如使用缓存和批量操作。

随着技术的发展,JSP技术已经逐渐被更现代的前端框架和后端技术所取代,如React、Vue.js、Angular等前端框架,以及Spring Boot、Spring MVC等后端框架。然而,理解JSP与数据库交互的基本原理对于学习这些现代技术仍然非常有帮助。

希望本文能够帮助开发者掌握网页与数据库交互的核心技术,为进一步学习和实践打下坚实的基础。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

频道订阅

频道订阅

加入社群

加入社群

联系我们|TG频道|RSS

Powered by Pixtech

© 2025 Pixtech Team.