|
|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
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。以下是一个基本的数据库连接示例:
- <%@ page import="java.sql.*" %>
- <%
- Connection conn = null;
- Statement stmt = null;
- ResultSet rs = null;
-
- try {
- // 1. 加载驱动
- Class.forName("com.mysql.jdbc.Driver");
-
- // 2. 建立连接
- String url = "jdbc:mysql://localhost:3306/mydatabase?useSSL=false&serverTimezone=UTC";
- String username = "root";
- String password = "password";
- conn = DriverManager.getConnection(url, username, password);
-
- // 3. 创建Statement
- stmt = conn.createStatement();
-
- // 4. 执行查询
- String sql = "SELECT * FROM users";
- rs = stmt.executeQuery(sql);
-
- // 5. 处理结果集
- while (rs.next()) {
- int id = rs.getInt("id");
- String name = rs.getString("name");
- String email = rs.getString("email");
- out.println("ID: " + id + ", Name: " + name + ", Email: " + email + "<br>");
- }
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- // 6. 关闭资源
- try {
- if (rs != null) rs.close();
- if (stmt != null) stmt.close();
- if (conn != null) conn.close();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- %>
复制代码
使用连接池
直接使用JDBC连接数据库在每次请求时都会创建新的连接,这在高并发环境下效率低下。连接池技术可以重用数据库连接,提高性能。以下是使用Apache DBCP连接池的示例:
首先,在项目中添加DBCP依赖。如果使用Maven,添加以下依赖:
- <dependency>
- <groupId>org.apache.commons</groupId>
- <artifactId>commons-dbcp2</artifactId>
- <version>2.9.0</version>
- </dependency>
复制代码
然后,创建一个数据库连接池工具类:
- package util;
- import org.apache.commons.dbcp2.BasicDataSource;
- public class DataSourceUtil {
- private static BasicDataSource dataSource = null;
-
- static {
- dataSource = new BasicDataSource();
- dataSource.setDriverClassName("com.mysql.jdbc.Driver");
- dataSource.setUrl("jdbc:mysql://localhost:3306/mydatabase?useSSL=false&serverTimezone=UTC");
- dataSource.setUsername("root");
- dataSource.setPassword("password");
- dataSource.setInitialSize(5);
- dataSource.setMaxTotal(20);
- dataSource.setMaxIdle(10);
- dataSource.setMinIdle(5);
- dataSource.setMaxWaitMillis(10000);
- }
-
- public static BasicDataSource getDataSource() {
- return dataSource;
- }
- }
复制代码
在JSP页面中使用连接池:
- <%@ page import="java.sql.*" %>
- <%@ page import="javax.sql.DataSource" %>
- <%@ page import="util.DataSourceUtil" %>
- <%
- Connection conn = null;
- Statement stmt = null;
- ResultSet rs = null;
-
- try {
- // 从连接池获取连接
- DataSource dataSource = DataSourceUtil.getDataSource();
- conn = dataSource.getConnection();
-
- // 创建Statement并执行查询
- stmt = conn.createStatement();
- String sql = "SELECT * FROM users";
- rs = stmt.executeQuery(sql);
-
- // 处理结果集
- while (rs.next()) {
- int id = rs.getInt("id");
- String name = rs.getString("name");
- String email = rs.getString("email");
- out.println("ID: " + id + ", Name: " + name + ", Email: " + email + "<br>");
- }
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- // 关闭资源
- try {
- if (rs != null) rs.close();
- if (stmt != null) stmt.close();
- if (conn != null) conn.close(); // 将连接返回给连接池
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- %>
复制代码
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示例:
- package model;
- public class User {
- private int id;
- private String name;
- private String email;
-
- // 无参构造方法
- public User() {}
-
- // 带参构造方法
- public User(int id, String name, String email) {
- this.id = id;
- this.name = name;
- this.email = email;
- }
-
- // getter和setter方法
- public int getId() {
- return id;
- }
-
- public void setId(int id) {
- this.id = id;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public String getEmail() {
- return email;
- }
-
- public void setEmail(String email) {
- this.email = email;
- }
- }
复制代码
在JSP页面中使用JavaBean:
- <%@ page import="model.User" %>
- <%@ page import="java.util.List" %>
- <%
- // 假设users是从数据库获取的用户列表
- List<User> users = (List<User>) request.getAttribute("users");
-
- if (users != null) {
- for (User user : users) {
- %>
- <div class="user-card">
- <h3><%= user.getName() %></h3>
- <p>ID: <%= user.getId() %></p>
- <p>Email: <%= user.getEmail() %></p>
- </div>
- <%
- }
- }
- %>
复制代码
数据库操作
数据查询
查询是数据库操作中最常用的功能。以下是使用PreparedStatement进行参数化查询的示例:
- <%@ page import="java.sql.*" %>
- <%@ page import="util.DataSourceUtil" %>
- <%@ page import="javax.sql.DataSource" %>
- <%
- Connection conn = null;
- PreparedStatement pstmt = null;
- ResultSet rs = null;
-
- try {
- DataSource dataSource = DataSourceUtil.getDataSource();
- conn = dataSource.getConnection();
-
- // 参数化查询,防止SQL注入
- String sql = "SELECT * FROM users WHERE age > ?";
- pstmt = conn.prepareStatement(sql);
- pstmt.setInt(1, 18); // 设置参数,年龄大于18
-
- rs = pstmt.executeQuery();
-
- // 处理结果集
- while (rs.next()) {
- int id = rs.getInt("id");
- String name = rs.getString("name");
- String email = rs.getString("email");
- int age = rs.getInt("age");
- out.println("ID: " + id + ", Name: " + name + ", Email: " + email + ", Age: " + age + "<br>");
- }
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- // 关闭资源
- try {
- if (rs != null) rs.close();
- if (pstmt != null) pstmt.close();
- if (conn != null) conn.close();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- %>
复制代码
数据插入
插入数据的示例:
- <%@ page import="java.sql.*" %>
- <%@ page import="util.DataSourceUtil" %>
- <%@ page import="javax.sql.DataSource" %>
- <%
- Connection conn = null;
- PreparedStatement pstmt = null;
-
- try {
- DataSource dataSource = DataSourceUtil.getDataSource();
- conn = dataSource.getConnection();
-
- // 插入数据
- String sql = "INSERT INTO users (name, email, age) VALUES (?, ?, ?)";
- pstmt = conn.prepareStatement(sql);
- pstmt.setString(1, "张三");
- pstmt.setString(2, "zhangsan@example.com");
- pstmt.setInt(3, 25);
-
- int result = pstmt.executeUpdate();
-
- if (result > 0) {
- out.println("数据插入成功!");
- } else {
- out.println("数据插入失败!");
- }
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- // 关闭资源
- try {
- if (pstmt != null) pstmt.close();
- if (conn != null) conn.close();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- %>
复制代码
数据更新
更新数据的示例:
- <%@ page import="java.sql.*" %>
- <%@ page import="util.DataSourceUtil" %>
- <%@ page import="javax.sql.DataSource" %>
- <%
- Connection conn = null;
- PreparedStatement pstmt = null;
-
- try {
- DataSource dataSource = DataSourceUtil.getDataSource();
- conn = dataSource.getConnection();
-
- // 更新数据
- String sql = "UPDATE users SET email = ? WHERE id = ?";
- pstmt = conn.prepareStatement(sql);
- pstmt.setString(1, "newemail@example.com");
- pstmt.setInt(2, 1);
-
- int result = pstmt.executeUpdate();
-
- if (result > 0) {
- out.println("数据更新成功!");
- } else {
- out.println("数据更新失败!");
- }
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- // 关闭资源
- try {
- if (pstmt != null) pstmt.close();
- if (conn != null) conn.close();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- %>
复制代码
数据删除
删除数据的示例:
- <%@ page import="java.sql.*" %>
- <%@ page import="util.DataSourceUtil" %>
- <%@ page import="javax.sql.DataSource" %>
- <%
- Connection conn = null;
- PreparedStatement pstmt = null;
-
- try {
- DataSource dataSource = DataSourceUtil.getDataSource();
- conn = dataSource.getConnection();
-
- // 删除数据
- String sql = "DELETE FROM users WHERE id = ?";
- pstmt = conn.prepareStatement(sql);
- pstmt.setInt(1, 1);
-
- int result = pstmt.executeUpdate();
-
- if (result > 0) {
- out.println("数据删除成功!");
- } else {
- out.println("数据删除失败!");
- }
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- // 关闭资源
- try {
- if (pstmt != null) pstmt.close();
- if (conn != null) conn.close();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- %>
复制代码
数据展示
基本表格展示
在JSP页面中使用HTML表格展示数据库数据是最常见的方式:
- <%@ page import="java.sql.*" %>
- <%@ page import="util.DataSourceUtil" %>
- <%@ page import="javax.sql.DataSource" %>
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title>用户列表</title>
- <style>
- table {
- border-collapse: collapse;
- width: 100%;
- }
- th, td {
- border: 1px solid #ddd;
- padding: 8px;
- text-align: left;
- }
- th {
- background-color: #f2f2f2;
- }
- tr:nth-child(even) {
- background-color: #f9f9f9;
- }
- </style>
- </head>
- <body>
- <h1>用户列表</h1>
- <table>
- <tr>
- <th>ID</th>
- <th>姓名</th>
- <th>邮箱</th>
- <th>年龄</th>
- </tr>
- <%
- Connection conn = null;
- Statement stmt = null;
- ResultSet rs = null;
-
- try {
- DataSource dataSource = DataSourceUtil.getDataSource();
- conn = dataSource.getConnection();
- stmt = conn.createStatement();
- String sql = "SELECT * FROM users";
- rs = stmt.executeQuery(sql);
-
- while (rs.next()) {
- int id = rs.getInt("id");
- String name = rs.getString("name");
- String email = rs.getString("email");
- int age = rs.getInt("age");
- %>
- <tr>
- <td><%= id %></td>
- <td><%= name %></td>
- <td><%= email %></td>
- <td><%= age %></td>
- </tr>
- <%
- }
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- try {
- if (rs != null) rs.close();
- if (stmt != null) stmt.close();
- if (conn != null) conn.close();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- %>
- </table>
- </body>
- </html>
复制代码
使用JSTL和EL表达式
JavaServer Pages Standard Tag Library(JSTL)和Expression Language(EL)可以简化JSP页面的开发,使代码更加清晰。首先,确保项目中包含JSTL库。如果使用Maven,添加以下依赖:
- <dependency>
- <groupId>javax.servlet</groupId>
- <artifactId>jstl</artifactId>
- <version>1.2</version>
- </dependency>
复制代码
然后,创建一个Servlet来处理数据库操作并将结果传递给JSP页面:
- package servlet;
- import model.User;
- import util.DataSourceUtil;
- 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 javax.sql.DataSource;
- import java.io.IOException;
- import java.sql.Connection;
- import java.sql.ResultSet;
- import java.sql.Statement;
- import java.util.ArrayList;
- import java.util.List;
- @WebServlet("/userList")
- public class UserListServlet extends HttpServlet {
- protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- List<User> userList = new ArrayList<>();
- Connection conn = null;
- Statement stmt = null;
- ResultSet rs = null;
-
- try {
- DataSource dataSource = DataSourceUtil.getDataSource();
- conn = dataSource.getConnection();
- stmt = conn.createStatement();
- String sql = "SELECT * FROM users";
- rs = stmt.executeQuery(sql);
-
- while (rs.next()) {
- User user = new User();
- user.setId(rs.getInt("id"));
- user.setName(rs.getString("name"));
- user.setEmail(rs.getString("email"));
- userList.add(user);
- }
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- try {
- if (rs != null) rs.close();
- if (stmt != null) stmt.close();
- if (conn != null) conn.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- request.setAttribute("userList", userList);
- request.getRequestDispatcher("/userList.jsp").forward(request, response);
- }
- }
复制代码
在JSP页面中使用JSTL和EL表达式:
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
- <html>
- <head>
- <title>用户列表</title>
- <style>
- table {
- border-collapse: collapse;
- width: 100%;
- }
- th, td {
- border: 1px solid #ddd;
- padding: 8px;
- text-align: left;
- }
- th {
- background-color: #f2f2f2;
- }
- tr:nth-child(even) {
- background-color: #f9f9f9;
- }
- </style>
- </head>
- <body>
- <h1>用户列表</h1>
- <table>
- <tr>
- <th>ID</th>
- <th>姓名</th>
- <th>邮箱</th>
- </tr>
- <c:forEach items="${userList}" var="user">
- <tr>
- <td>${user.id}</td>
- <td>${user.name}</td>
- <td>${user.email}</td>
- </tr>
- </c:forEach>
- </table>
- </body>
- </html>
复制代码
分页显示
当数据量很大时,分页显示是必要的。以下是实现分页的示例:
首先,修改Servlet以支持分页:
- package servlet;
- import model.User;
- import util.DataSourceUtil;
- 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 javax.sql.DataSource;
- import java.io.IOException;
- import java.sql.Connection;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- import java.util.ArrayList;
- import java.util.List;
- @WebServlet("/userList")
- public class UserListServlet extends HttpServlet {
- protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- int page = 1;
- int recordsPerPage = 5;
-
- if (request.getParameter("page") != null) {
- page = Integer.parseInt(request.getParameter("page"));
- }
-
- List<User> userList = new ArrayList<>();
- Connection conn = null;
- PreparedStatement pstmt = null;
- ResultSet rs = null;
-
- try {
- DataSource dataSource = DataSourceUtil.getDataSource();
- conn = dataSource.getConnection();
-
- // 计算总记录数
- String countSql = "SELECT COUNT(*) FROM users";
- pstmt = conn.prepareStatement(countSql);
- rs = pstmt.executeQuery();
- if (rs.next()) {
- int noOfRecords = rs.getInt(1);
- int noOfPages = (int) Math.ceil(noOfRecords * 1.0 / recordsPerPage);
- request.setAttribute("noOfPages", noOfPages);
- }
- rs.close();
- pstmt.close();
-
- // 获取当前页的数据
- String sql = "SELECT * FROM users LIMIT ?, ?";
- pstmt = conn.prepareStatement(sql);
- pstmt.setInt(1, (page - 1) * recordsPerPage);
- pstmt.setInt(2, recordsPerPage);
- rs = pstmt.executeQuery();
-
- while (rs.next()) {
- User user = new User();
- user.setId(rs.getInt("id"));
- user.setName(rs.getString("name"));
- user.setEmail(rs.getString("email"));
- userList.add(user);
- }
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- try {
- if (rs != null) rs.close();
- if (pstmt != null) pstmt.close();
- if (conn != null) conn.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- request.setAttribute("userList", userList);
- request.setAttribute("currentPage", page);
- request.getRequestDispatcher("/userList.jsp").forward(request, response);
- }
- }
复制代码
然后,在JSP页面中添加分页控件:
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
- <html>
- <head>
- <title>用户列表</title>
- <style>
- table {
- border-collapse: collapse;
- width: 100%;
- }
- th, td {
- border: 1px solid #ddd;
- padding: 8px;
- text-align: left;
- }
- th {
- background-color: #f2f2f2;
- }
- tr:nth-child(even) {
- background-color: #f9f9f9;
- }
- .pagination {
- display: inline-block;
- margin-top: 20px;
- }
- .pagination a {
- color: black;
- float: left;
- padding: 8px 16px;
- text-decoration: none;
- border: 1px solid #ddd;
- }
- .pagination a.active {
- background-color: #4CAF50;
- color: white;
- }
- .pagination a:hover:not(.active) {
- background-color: #ddd;
- }
- </style>
- </head>
- <body>
- <h1>用户列表</h1>
- <table>
- <tr>
- <th>ID</th>
- <th>姓名</th>
- <th>邮箱</th>
- </tr>
- <c:forEach items="${userList}" var="user">
- <tr>
- <td>${user.id}</td>
- <td>${user.name}</td>
- <td>${user.email}</td>
- </tr>
- </c:forEach>
- </table>
-
- <div class="pagination">
- <c:if test="${currentPage != 1}">
- <a href="userList?page=${currentPage - 1}">上一页</a>
- </c:if>
-
- <c:forEach begin="1" end="${noOfPages}" var="i">
- <c:choose>
- <c:when test="${currentPage eq i}">
- <a href="#" class="active">${i}</a>
- </c:when>
- <c:otherwise>
- <a href="userList?page=${i}">${i}</a>
- </c:otherwise>
- </c:choose>
- </c:forEach>
-
- <c:if test="${currentPage lt noOfPages}">
- <a href="userList?page=${currentPage + 1}">下一页</a>
- </c:if>
- </div>
- </body>
- </html>
复制代码
高级技巧
搜索功能
实现搜索功能需要修改Servlet和JSP页面。以下是实现搜索功能的示例:
修改Servlet以支持搜索:
- package servlet;
- import model.User;
- import util.DataSourceUtil;
- 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 javax.sql.DataSource;
- import java.io.IOException;
- import java.sql.Connection;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- import java.util.ArrayList;
- import java.util.List;
- @WebServlet("/userSearch")
- public class UserSearchServlet extends HttpServlet {
- protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- String searchKeyword = request.getParameter("searchKeyword");
-
- List<User> userList = new ArrayList<>();
- Connection conn = null;
- PreparedStatement pstmt = null;
- ResultSet rs = null;
-
- try {
- DataSource dataSource = DataSourceUtil.getDataSource();
- conn = dataSource.getConnection();
-
- String sql = "SELECT * FROM users WHERE name LIKE ? OR email LIKE ?";
- pstmt = conn.prepareStatement(sql);
- pstmt.setString(1, "%" + searchKeyword + "%");
- pstmt.setString(2, "%" + searchKeyword + "%");
-
- rs = pstmt.executeQuery();
-
- while (rs.next()) {
- User user = new User();
- user.setId(rs.getInt("id"));
- user.setName(rs.getString("name"));
- user.setEmail(rs.getString("email"));
- userList.add(user);
- }
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- try {
- if (rs != null) rs.close();
- if (pstmt != null) pstmt.close();
- if (conn != null) conn.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- request.setAttribute("userList", userList);
- request.setAttribute("searchKeyword", searchKeyword);
- request.getRequestDispatcher("/userSearch.jsp").forward(request, response);
- }
- }
复制代码
在JSP页面中添加搜索表单:
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
- <html>
- <head>
- <title>用户搜索</title>
- <style>
- table {
- border-collapse: collapse;
- width: 100%;
- margin-top: 20px;
- }
- th, td {
- border: 1px solid #ddd;
- padding: 8px;
- text-align: left;
- }
- th {
- background-color: #f2f2f2;
- }
- tr:nth-child(even) {
- background-color: #f9f9f9;
- }
- .search-form {
- margin-bottom: 20px;
- }
- .search-form input[type="text"] {
- padding: 8px;
- width: 300px;
- }
- .search-form input[type="submit"] {
- padding: 8px 16px;
- background-color: #4CAF50;
- color: white;
- border: none;
- cursor: pointer;
- }
- </style>
- </head>
- <body>
- <h1>用户搜索</h1>
-
- <form class="search-form" action="userSearch" method="post">
- <input type="text" name="searchKeyword" value="${searchKeyword}" placeholder="输入姓名或邮箱">
- <input type="submit" value="搜索">
- </form>
-
- <c:if test="${not empty userList}">
- <table>
- <tr>
- <th>ID</th>
- <th>姓名</th>
- <th>邮箱</th>
- </tr>
- <c:forEach items="${userList}" var="user">
- <tr>
- <td>${user.id}</td>
- <td>${user.name}</td>
- <td>${user.email}</td>
- </tr>
- </c:forEach>
- </table>
- </c:if>
-
- <c:if test="${empty userList and not empty searchKeyword}">
- <p>没有找到包含 "${searchKeyword}" 的用户</p>
- </c:if>
- </body>
- </html>
复制代码
排序功能
实现排序功能需要修改Servlet和JSP页面。以下是实现排序功能的示例:
修改Servlet以支持排序:
- package servlet;
- import model.User;
- import util.DataSourceUtil;
- 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 javax.sql.DataSource;
- import java.io.IOException;
- import java.sql.Connection;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- import java.util.ArrayList;
- import java.util.List;
- @WebServlet("/userSort")
- public class UserSortServlet extends HttpServlet {
- protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- String sortField = request.getParameter("sortField");
- String sortOrder = request.getParameter("sortOrder");
-
- if (sortField == null || sortField.isEmpty()) {
- sortField = "id";
- }
-
- if (sortOrder == null || sortOrder.isEmpty()) {
- sortOrder = "ASC";
- }
-
- List<User> userList = new ArrayList<>();
- Connection conn = null;
- PreparedStatement pstmt = null;
- ResultSet rs = null;
-
- try {
- DataSource dataSource = DataSourceUtil.getDataSource();
- conn = dataSource.getConnection();
-
- String sql = "SELECT * FROM users ORDER BY " + sortField + " " + sortOrder;
- pstmt = conn.prepareStatement(sql);
-
- rs = pstmt.executeQuery();
-
- while (rs.next()) {
- User user = new User();
- user.setId(rs.getInt("id"));
- user.setName(rs.getString("name"));
- user.setEmail(rs.getString("email"));
- userList.add(user);
- }
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- try {
- if (rs != null) rs.close();
- if (pstmt != null) pstmt.close();
- if (conn != null) conn.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- request.setAttribute("userList", userList);
- request.setAttribute("sortField", sortField);
- request.setAttribute("sortOrder", sortOrder);
- request.getRequestDispatcher("/userSort.jsp").forward(request, response);
- }
- }
复制代码
在JSP页面中添加排序功能:
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
- <html>
- <head>
- <title>用户排序</title>
- <style>
- table {
- border-collapse: collapse;
- width: 100%;
- }
- th, td {
- border: 1px solid #ddd;
- padding: 8px;
- text-align: left;
- }
- th {
- background-color: #f2f2f2;
- cursor: pointer;
- }
- tr:nth-child(even) {
- background-color: #f9f9f9;
- }
- .sort-controls {
- margin-bottom: 20px;
- }
- </style>
- </head>
- <body>
- <h1>用户排序</h1>
-
- <div class="sort-controls">
- <a href="userSort?sortField=id&sortOrder=${sortField eq 'id' and sortOrder eq 'ASC' ? 'DESC' : 'ASC'}">
- 按ID ${sortField eq 'id' and sortOrder eq 'ASC' ? '↓' : '↑'} 排序
- </a>
- |
- <a href="userSort?sortField=name&sortOrder=${sortField eq 'name' and sortOrder eq 'ASC' ? 'DESC' : 'ASC'}">
- 按姓名 ${sortField eq 'name' and sortOrder eq 'ASC' ? '↓' : '↑'} 排序
- </a>
- |
- <a href="userSort?sortField=email&sortOrder=${sortField eq 'email' and sortOrder eq 'ASC' ? 'DESC' : 'ASC'}">
- 按邮箱 ${sortField eq 'email' and sortOrder eq 'ASC' ? '↓' : '↑'} 排序
- </a>
- </div>
-
- <table>
- <tr>
- <th onclick="location.href='userSort?sortField=id&sortOrder=${sortField eq 'id' and sortOrder eq 'ASC' ? 'DESC' : 'ASC'}'">
- ID ${sortField eq 'id' and sortOrder eq 'ASC' ? '↑' : '↓'}
- </th>
- <th onclick="location.href='userSort?sortField=name&sortOrder=${sortField eq 'name' and sortOrder eq 'ASC' ? 'DESC' : 'ASC'}'">
- 姓名 ${sortField eq 'name' and sortOrder eq 'ASC' ? '↑' : '↓'}
- </th>
- <th onclick="location.href='userSort?sortField=email&sortOrder=${sortField eq 'email' and sortOrder eq 'ASC' ? 'DESC' : 'ASC'}'">
- 邮箱 ${sortField eq 'email' and sortOrder eq 'ASC' ? '↑' : '↓'}
- </th>
- </tr>
- <c:forEach items="${userList}" var="user">
- <tr>
- <td>${user.id}</td>
- <td>${user.name}</td>
- <td>${user.email}</td>
- </tr>
- </c:forEach>
- </table>
- </body>
- </html>
复制代码
安全性考虑
SQL注入防护
SQL注入是一种常见的网络安全漏洞,攻击者可以通过在输入中插入恶意SQL代码来操纵数据库查询。使用PreparedStatement可以有效防止SQL注入:
- <%@ page import="java.sql.*" %>
- <%@ page import="util.DataSourceUtil" %>
- <%@ page import="javax.sql.DataSource" %>
- <%
- String userId = request.getParameter("id");
-
- Connection conn = null;
- PreparedStatement pstmt = null;
- ResultSet rs = null;
-
- try {
- DataSource dataSource = DataSourceUtil.getDataSource();
- conn = dataSource.getConnection();
-
- // 使用PreparedStatement防止SQL注入
- String sql = "SELECT * FROM users WHERE id = ?";
- pstmt = conn.prepareStatement(sql);
- pstmt.setString(1, userId);
-
- rs = pstmt.executeQuery();
-
- if (rs.next()) {
- String name = rs.getString("name");
- String email = rs.getString("email");
- out.println("Name: " + name + ", Email: " + email);
- } else {
- out.println("User not found");
- }
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- try {
- if (rs != null) rs.close();
- if (pstmt != null) pstmt.close();
- if (conn != null) conn.close();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- %>
复制代码
输入验证
除了使用PreparedStatement,还应该对用户输入进行验证:
- <%@ page import="java.sql.*" %>
- <%@ page import="util.DataSourceUtil" %>
- <%@ page import="javax.sql.DataSource" %>
- <%@ page import="java.util.regex.Pattern" %>
- <%
- String userId = request.getParameter("id");
-
- // 输入验证:确保ID是数字
- if (userId == null || !Pattern.matches("\\d+", userId)) {
- out.println("Invalid user ID");
- return;
- }
-
- Connection conn = null;
- PreparedStatement pstmt = null;
- ResultSet rs = null;
-
- try {
- DataSource dataSource = DataSourceUtil.getDataSource();
- conn = dataSource.getConnection();
-
- String sql = "SELECT * FROM users WHERE id = ?";
- pstmt = conn.prepareStatement(sql);
- pstmt.setInt(1, Integer.parseInt(userId));
-
- rs = pstmt.executeQuery();
-
- if (rs.next()) {
- String name = rs.getString("name");
- String email = rs.getString("email");
- out.println("Name: " + name + ", Email: " + email);
- } else {
- out.println("User not found");
- }
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- try {
- if (rs != null) rs.close();
- if (pstmt != null) pstmt.close();
- if (conn != null) conn.close();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- %>
复制代码
输出编码
为了防止XSS(跨站脚本)攻击,应该对输出进行编码:
- <%@ page import="org.apache.commons.text.StringEscapeUtils" %>
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
- <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
- <html>
- <head>
- <title>安全输出示例</title>
- </head>
- <body>
- <h1>用户信息</h1>
-
- <%-- 使用JSTL的fn:escapeXml函数进行输出编码 --%>
- <c:out value="${user.name}" escapeXml="true"/>
-
- <%-- 或者使用fn:escapeXml函数 --%>
- ${fn:escapeXml(user.name)}
-
- <%-- 在脚本片段中使用StringEscapeUtils --%>
- <%
- String userInput = "<script>alert('XSS Attack');</script>";
- String safeOutput = StringEscapeUtils.escapeHtml4(userInput);
- out.println(safeOutput);
- %>
- </body>
- </html>
复制代码
使用连接池
使用连接池不仅可以提高性能,还可以增强安全性。连接池可以限制最大连接数,防止数据库过载,并且可以管理连接的生命周期,确保连接正确关闭。
以下是使用Tomcat JDBC连接池的配置示例:
在context.xml中配置连接池:
- <Context>
- <Resource name="jdbc/myDB"
- auth="Container"
- type="javax.sql.DataSource"
- maxTotal="100"
- maxIdle="30"
- maxWaitMillis="10000"
- username="root"
- password="password"
- driverClassName="com.mysql.jdbc.Driver"
- url="jdbc:mysql://localhost:3306/mydatabase?useSSL=false&serverTimezone=UTC"/>
- </Context>
复制代码
在web.xml中引用资源:
- <web-app>
- <resource-ref>
- <description>MySQL DataSource</description>
- <res-ref-name>jdbc/myDB</res-ref-name>
- <res-type>javax.sql.DataSource</res-type>
- <res-auth>Container</res-auth>
- </resource-ref>
- </web-app>
复制代码
在JSP页面中使用连接池:
- <%@ page import="javax.sql.DataSource" %>
- <%@ page import="javax.naming.InitialContext" %>
- <%@ page import="java.sql.*" %>
- <%
- Connection conn = null;
- Statement stmt = null;
- ResultSet rs = null;
-
- try {
- // 获取JNDI上下文
- InitialContext ctx = new InitialContext();
-
- // 查找数据源
- DataSource dataSource = (DataSource) ctx.lookup("java:comp/env/jdbc/myDB");
-
- // 获取连接
- conn = dataSource.getConnection();
-
- // 创建Statement并执行查询
- stmt = conn.createStatement();
- String sql = "SELECT * FROM users";
- rs = stmt.executeQuery(sql);
-
- // 处理结果集
- while (rs.next()) {
- int id = rs.getInt("id");
- String name = rs.getString("name");
- String email = rs.getString("email");
- out.println("ID: " + id + ", Name: " + name + ", Email: " + email + "<br>");
- }
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- // 关闭资源
- try {
- if (rs != null) rs.close();
- if (stmt != null) stmt.close();
- if (conn != null) conn.close();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- %>
复制代码
最佳实践和性能优化
MVC架构模式
在实际项目中,应该采用MVC(Model-View-Controller)架构模式,将业务逻辑、数据和表示分离。以下是一个简单的MVC示例:
1. Model(模型):JavaBean和DAO(Data Access Object)
- package model;
- public class User {
- private int id;
- private String name;
- private String email;
-
- // 构造方法、getter和setter
- // ...
- }
复制代码- package dao;
- import model.User;
- import util.DataSourceUtil;
- import javax.sql.DataSource;
- import java.sql.*;
- import java.util.ArrayList;
- import java.util.List;
- public class UserDAO {
- private DataSource dataSource;
-
- public UserDAO() {
- this.dataSource = DataSourceUtil.getDataSource();
- }
-
- public List<User> getAllUsers() {
- List<User> users = new ArrayList<>();
- String sql = "SELECT * FROM users";
-
- try (Connection conn = dataSource.getConnection();
- Statement stmt = conn.createStatement();
- ResultSet rs = stmt.executeQuery(sql)) {
-
- while (rs.next()) {
- User user = new User();
- user.setId(rs.getInt("id"));
- user.setName(rs.getString("name"));
- user.setEmail(rs.getString("email"));
- users.add(user);
- }
- } catch (SQLException e) {
- e.printStackTrace();
- }
-
- return users;
- }
-
- public User getUserById(int id) {
- User user = null;
- String sql = "SELECT * FROM users WHERE id = ?";
-
- try (Connection conn = dataSource.getConnection();
- PreparedStatement pstmt = conn.prepareStatement(sql)) {
-
- pstmt.setInt(1, id);
-
- try (ResultSet rs = pstmt.executeQuery()) {
- if (rs.next()) {
- user = new User();
- user.setId(rs.getInt("id"));
- user.setName(rs.getString("name"));
- user.setEmail(rs.getString("email"));
- }
- }
- } catch (SQLException e) {
- e.printStackTrace();
- }
-
- return user;
- }
-
- public boolean addUser(User user) {
- String sql = "INSERT INTO users (name, email) VALUES (?, ?)";
-
- try (Connection conn = dataSource.getConnection();
- PreparedStatement pstmt = conn.prepareStatement(sql)) {
-
- pstmt.setString(1, user.getName());
- pstmt.setString(2, user.getEmail());
-
- int rowsAffected = pstmt.executeUpdate();
- return rowsAffected > 0;
- } catch (SQLException e) {
- e.printStackTrace();
- return false;
- }
- }
-
- public boolean updateUser(User user) {
- String sql = "UPDATE users SET name = ?, email = ? WHERE id = ?";
-
- try (Connection conn = dataSource.getConnection();
- PreparedStatement pstmt = conn.prepareStatement(sql)) {
-
- pstmt.setString(1, user.getName());
- pstmt.setString(2, user.getEmail());
- pstmt.setInt(3, user.getId());
-
- int rowsAffected = pstmt.executeUpdate();
- return rowsAffected > 0;
- } catch (SQLException e) {
- e.printStackTrace();
- return false;
- }
- }
-
- public boolean deleteUser(int id) {
- String sql = "DELETE FROM users WHERE id = ?";
-
- try (Connection conn = dataSource.getConnection();
- PreparedStatement pstmt = conn.prepareStatement(sql)) {
-
- pstmt.setInt(1, id);
-
- int rowsAffected = pstmt.executeUpdate();
- return rowsAffected > 0;
- } catch (SQLException e) {
- e.printStackTrace();
- return false;
- }
- }
- }
复制代码
1. Controller(控制器):Servlet
- package servlet;
- import dao.UserDAO;
- import 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("/users")
- public class UserController extends HttpServlet {
- private UserDAO userDAO;
-
- public void init() {
- userDAO = new UserDAO();
- }
-
- protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- String action = request.getParameter("action");
-
- if (action == null) {
- action = "list";
- }
-
- switch (action) {
- case "edit":
- showEditForm(request, response);
- break;
- case "delete":
- deleteUser(request, response);
- break;
- case "view":
- viewUser(request, response);
- break;
- default:
- listUsers(request, response);
- break;
- }
- }
-
- protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- String action = request.getParameter("action");
-
- if (action == null) {
- action = "list";
- }
-
- switch (action) {
- case "add":
- addUser(request, response);
- break;
- case "update":
- updateUser(request, response);
- break;
- default:
- listUsers(request, response);
- break;
- }
- }
-
- private void listUsers(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- List<User> userList = userDAO.getAllUsers();
- request.setAttribute("userList", userList);
- request.getRequestDispatcher("/userList.jsp").forward(request, response);
- }
-
- private void showEditForm(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- int id = Integer.parseInt(request.getParameter("id"));
- User existingUser = userDAO.getUserById(id);
- request.setAttribute("user", existingUser);
- request.getRequestDispatcher("/userForm.jsp").forward(request, response);
- }
-
- private void viewUser(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- int id = Integer.parseInt(request.getParameter("id"));
- User user = userDAO.getUserById(id);
- request.setAttribute("user", user);
- request.getRequestDispatcher("/userView.jsp").forward(request, response);
- }
-
- private void addUser(HttpServletRequest request, HttpServletResponse response) throws IOException {
- String name = request.getParameter("name");
- String email = request.getParameter("email");
-
- User newUser = new User();
- newUser.setName(name);
- newUser.setEmail(email);
-
- userDAO.addUser(newUser);
- response.sendRedirect("users?action=list");
- }
-
- private void updateUser(HttpServletRequest request, HttpServletResponse response) throws IOException {
- int id = Integer.parseInt(request.getParameter("id"));
- String name = request.getParameter("name");
- String email = request.getParameter("email");
-
- User user = new User();
- user.setId(id);
- user.setName(name);
- user.setEmail(email);
-
- userDAO.updateUser(user);
- response.sendRedirect("users?action=list");
- }
-
- private void deleteUser(HttpServletRequest request, HttpServletResponse response) throws IOException {
- int id = Integer.parseInt(request.getParameter("id"));
- userDAO.deleteUser(id);
- response.sendRedirect("users?action=list");
- }
- }
复制代码
1. View(视图):JSP页面
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
- <html>
- <head>
- <title>用户列表</title>
- <style>
- table {
- border-collapse: collapse;
- width: 100%;
- }
- th, td {
- border: 1px solid #ddd;
- padding: 8px;
- text-align: left;
- }
- th {
- background-color: #f2f2f2;
- }
- tr:nth-child(even) {
- background-color: #f9f9f9;
- }
- .actions a {
- margin-right: 10px;
- }
- </style>
- </head>
- <body>
- <h1>用户列表</h1>
-
- <p>
- <a href="userForm.jsp?action=add">添加新用户</a>
- </p>
-
- <table>
- <tr>
- <th>ID</th>
- <th>姓名</th>
- <th>邮箱</th>
- <th>操作</th>
- </tr>
- <c:forEach items="${userList}" var="user">
- <tr>
- <td>${user.id}</td>
- <td>${user.name}</td>
- <td>${user.email}</td>
- <td class="actions">
- <a href="users?action=view&id=${user.id}">查看</a>
- <a href="users?action=edit&id=${user.id}">编辑</a>
- <a href="users?action=delete&id=${user.id}" onclick="return confirm('确定要删除这个用户吗?')">删除</a>
- </td>
- </tr>
- </c:forEach>
- </table>
- </body>
- </html>
复制代码
使用ORM框架
虽然直接使用JDBC可以完成数据库操作,但在大型项目中,使用ORM(Object-Relational Mapping)框架如Hibernate或MyBatis可以大大简化开发工作。以下是使用MyBatis的简单示例:
首先,添加MyBatis依赖:
- <dependency>
- <groupId>org.mybatis</groupId>
- <artifactId>mybatis</artifactId>
- <version>3.5.7</version>
- </dependency>
- <dependency>
- <groupId>org.mybatis</groupId>
- <artifactId>mybatis-spring</artifactId>
- <version>2.0.6</version>
- </dependency>
复制代码
创建MyBatis配置文件:
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE configuration
- PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-config.dtd">
- <configuration>
- <environments default="development">
- <environment id="development">
- <transactionManager type="JDBC"/>
- <dataSource type="POOLED">
- <property name="driver" value="com.mysql.jdbc.Driver"/>
- <property name="url" value="jdbc:mysql://localhost:3306/mydatabase?useSSL=false&serverTimezone=UTC"/>
- <property name="username" value="root"/>
- <property name="password" value="password"/>
- </dataSource>
- </environment>
- </environments>
- <mappers>
- <mapper resource="mapper/UserMapper.xml"/>
- </mappers>
- </configuration>
复制代码
创建Mapper接口:
- package mapper;
- import model.User;
- import java.util.List;
- public interface UserMapper {
- List<User> getAllUsers();
- User getUserById(int id);
- void insertUser(User user);
- void updateUser(User user);
- void deleteUser(int id);
- }
复制代码
创建Mapper XML文件:
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE mapper
- PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <mapper namespace="mapper.UserMapper">
- <select id="getAllUsers" resultType="model.User">
- SELECT * FROM users
- </select>
-
- <select id="getUserById" resultType="model.User" parameterType="int">
- SELECT * FROM users WHERE id = #{id}
- </select>
-
- <insert id="insertUser" parameterType="model.User">
- INSERT INTO users (name, email) VALUES (#{name}, #{email})
- </insert>
-
- <update id="updateUser" parameterType="model.User">
- UPDATE users SET name = #{name}, email = #{email} WHERE id = #{id}
- </update>
-
- <delete id="deleteUser" parameterType="int">
- DELETE FROM users WHERE id = #{id}
- </delete>
- </mapper>
复制代码
创建MyBatis工具类:
- package util;
- import org.apache.ibatis.io.Resources;
- import org.apache.ibatis.session.SqlSession;
- import org.apache.ibatis.session.SqlSessionFactory;
- import org.apache.ibatis.session.SqlSessionFactoryBuilder;
- import java.io.IOException;
- import java.io.Reader;
- public class MyBatisUtil {
- private static SqlSessionFactory factory;
-
- static {
- try {
- Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
- factory = new SqlSessionFactoryBuilder().build(reader);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- public static SqlSession getSqlSession() {
- return factory.openSession();
- }
- }
复制代码
在Servlet中使用MyBatis:
- package servlet;
- import mapper.UserMapper;
- import model.User;
- import util.MyBatisUtil;
- 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("/mybatisUsers")
- public class MyBatisUserServlet extends HttpServlet {
- protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- List<User> userList = null;
-
- try (SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
- UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
- userList = userMapper.getAllUsers();
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- request.setAttribute("userList", userList);
- request.getRequestDispatcher("/userList.jsp").forward(request, response);
- }
- }
复制代码
性能优化
1. 使用缓存
MyBatis提供了一级缓存和二级缓存。一级缓存是SqlSession级别的缓存,默认开启。二级缓存是Mapper级别的缓存,需要手动配置。
在Mapper XML文件中启用二级缓存:
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE mapper
- PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <mapper namespace="mapper.UserMapper">
- <cache/>
-
- <select id="getAllUsers" resultType="model.User" useCache="true">
- SELECT * FROM users
- </select>
-
- <!-- 其他SQL语句 -->
- </mapper>
复制代码
1. 批量操作
对于大量数据的插入、更新或删除,使用批量操作可以显著提高性能:
- package dao;
- import model.User;
- import util.DataSourceUtil;
- import javax.sql.DataSource;
- import java.sql.Connection;
- import java.sql.PreparedStatement;
- import java.sql.SQLException;
- import java.util.List;
- public class UserBatchDAO {
- private DataSource dataSource;
-
- public UserBatchDAO() {
- this.dataSource = DataSourceUtil.getDataSource();
- }
-
- public void batchInsertUsers(List<User> users) {
- String sql = "INSERT INTO users (name, email) VALUES (?, ?)";
-
- try (Connection conn = dataSource.getConnection();
- PreparedStatement pstmt = conn.prepareStatement(sql)) {
-
- // 关闭自动提交
- conn.setAutoCommit(false);
-
- for (User user : users) {
- pstmt.setString(1, user.getName());
- pstmt.setString(2, user.getEmail());
- pstmt.addBatch();
- }
-
- // 执行批量操作
- int[] results = pstmt.executeBatch();
-
- // 提交事务
- conn.commit();
-
- System.out.println("批量插入了 " + results.length + " 条记录");
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- }
复制代码
1. 使用连接池
前面已经介绍了连接池的使用,这里再次强调其重要性。连接池可以重用数据库连接,减少创建和销毁连接的开销,提高系统性能。
1. 优化SQL查询
• 只查询需要的字段,避免使用SELECT *
• 使用索引提高查询速度
• 避免在循环中执行查询
• 使用JOIN代替多个查询
- // 不好的做法:N+1查询问题
- List<User> users = userDAO.getAllUsers();
- for (User user : users) {
- List<Order> orders = orderDAO.getOrdersByUserId(user.getId());
- user.setOrders(orders);
- }
- // 好的做法:使用JOIN一次性获取所有数据
- List<User> users = userDAO.getAllUsersWithOrders();
复制代码
总结与展望
本文详细介绍了JSP页面实现数据库信息动态显示的方法与实践,从基础的数据库连接到完整的数据展示流程。我们学习了如何使用JDBC连接数据库,如何在JSP页面中展示数据,以及如何实现分页、搜索和排序等高级功能。同时,我们也讨论了安全性考虑和性能优化的最佳实践。
在实际开发中,建议采用MVC架构模式,将业务逻辑、数据和表示分离。对于大型项目,可以考虑使用ORM框架如MyBatis或Hibernate来简化数据库操作。此外,还应该注意安全性问题,如SQL注入防护和XSS攻击防护,以及性能优化,如使用缓存和批量操作。
随着技术的发展,JSP技术已经逐渐被更现代的前端框架和后端技术所取代,如React、Vue.js、Angular等前端框架,以及Spring Boot、Spring MVC等后端框架。然而,理解JSP与数据库交互的基本原理对于学习这些现代技术仍然非常有帮助。
希望本文能够帮助开发者掌握网页与数据库交互的核心技术,为进一步学习和实践打下坚实的基础。
版权声明
1、转载或引用本网站内容(JSP页面实现数据库信息动态显示的方法与实践 从基础连接到数据展示的全流程解析 助力开发者轻松掌握网页与数据库交互的核心技术)须注明原网址及作者(威震华夏关云长),并标明本网站网址(https://www.pixtech.cc/)。
2、对于不当转载或引用本网站内容而引起的民事纷争、行政处理或其他损失,本网站不承担责任。
3、对不遵守本声明或其他违法、恶意使用本网站内容者,本网站保留追究其法律责任的权利。
本文地址: https://www.pixtech.cc/thread-36772-1-1.html
|
|