JSP如何将数据库数据传递并展示到前台页面?

在现代Web开发中,将后台数据库中的数据动态地展示给用户,是一项核心且基础的任务,对于使用Java技术栈的开发者而言,JSP(JavaServer Pages)与Servlet的组合是经典的解决方案,理解如何将从数据库中查询到的数据高效、安全地传递到JSP前台页面进行渲染,是掌握Java Web开发的关键一环,本文将详细拆解这一过程,遵循MVC(Model-View-Controller)设计模式,阐述其核心思想与实现步骤。

JSP如何将数据库数据传递并展示到前台页面?

核心思想:分离关注点,遵循MVC模式

在讨论具体技术之前,我们必须明确其背后的指导思想——MVC模式,这种模式将应用程序清晰地划分为三个部分,以实现高内聚、低耦合:

  • Model(模型):负责业务逻辑和数据封装,在我们的场景中,它通常指代一个JavaBean(POJO),用于封装从数据库中取出的一行数据(例如一个用户信息),或者是一个包含多个JavaBean的集合(例如用户列表)。
  • View(视图):负责数据显示,它不包含任何业务逻辑,仅负责将模型中的数据以美观的HTML格式呈现给用户,JSP页面就扮演着视图的角色。
  • Controller(控制器):作为模型和视图之间的协调者,它接收用户的请求,调用模型处理业务逻辑(如查询数据库),然后选择合适的视图进行响应,并将处理结果(数据)传递给视图,Servlet正是控制器的最佳实现。

遵循MVC模式,数据传递的路径就变得非常清晰:数据库 → Servlet(Controller) → 数据模型 → JSP(View)

第一步:后端数据准备(Servlet的工作)

Servlet是整个数据流转的起点和指挥中心,它的主要职责包括连接数据库、执行查询、封装数据,并将数据“放置”在一个JSP可以访问到的地方。

1 数据库连接与查询

Servlet需要使用JDBC(Java Database Connectivity)技术来连接数据库并执行SQL查询,这是一个标准流程,通常包括加载驱动、建立连接、创建Statement或PreparedStatement对象、执行查询并获取ResultSet

// 示例代码片段
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
List<User> userList = new ArrayList<>(); // 创建一个List用于存放用户数据
try {
    // 1. 获取数据库连接(实际项目中通常使用连接池)
    conn = dataSource.getConnection();
    String sql = "SELECT id, name, email FROM users";
    // 2. 创建PreparedStatement
    pstmt = conn.prepareStatement(sql);
    // 3. 执行查询
    rs = pstmt.executeQuery();
    // 4. 处理结果集
    while (rs.next()) {
        User user = new User(); // 创建User模型对象
        user.setId(rs.getInt("id"));
        user.setName(rs.getString("name"));
        user.setEmail(rs.getString("email"));
        userList.add(user); // 将封装好的User对象添加到List中
    }
} catch (SQLException e) {
    e.printStackTrace();
} finally {
    // 5. 关闭资源(非常重要)
    // ... 关闭 rs, pstmt, conn
}

2 数据封装

直接将ResultSet对象传递给JSP是一种非常糟糕的做法。ResultSet与数据库连接紧密绑定,如果在JSP页面中处理它,会导致数据库连接长时间占用,并且严重违反MVC原则,使视图层混杂了数据访问逻辑。

正确的做法是,如上例所示,遍历ResultSet,将每一行数据封装成一个独立的JavaBean对象(如User),然后将所有这些对象存入一个List集合中,这个List<User>就是我们的“模型”,它是一个纯粹的、与数据库无关的Java对象集合。

3 设置请求作用域属性

数据封装完毕后,Servlet需要将这个userList传递给JSP,传递的“桥梁”就是HTTP请求对象(HttpServletRequest),Servlet可以通过调用setAttribute方法,将任何Java对象存入请求作用域中。

// 将userList存入request作用域,键名为"userList"
request.setAttribute("userList", userList);

这里,"userList"是一个字符串键,JSP将通过这个键来获取数据;userList则是我们之前创建的包含所有用户数据的List对象。

第二步:请求转发

设置完属性后,Servlet需要将请求转发给指定的JSP页面来处理响应,这里必须使用请求转发,而不是重定向。

JSP如何将数据库数据传递并展示到前台页面?

// 将请求转发到showUsers.jsp页面
request.getRequestDispatcher("showUsers.jsp").forward(request, response);

forward()方法会将同一个requestresponse对象传递给showUsers.jsp,这意味着,我们刚刚存入request中的userList属性,在JSP页面中是完全可以访问的,而重定向会告知浏览器发起一个新的请求,原请求中的所有属性都会丢失。

第三步:前端数据渲染(JSP的工作)

JSP页面的任务单一而纯粹:从请求作用域中取出数据,并将其渲染成HTML。

1 使用EL和JSTL(推荐做法)

为了保持JSP页面的整洁,避免在页面中嵌入大量的Java代码(即Scriptlet <% ... %>),强烈推荐使用表达式语言(EL)JSP标准标签库(JSTL)

需要在JSP页面顶部引入JSTL核心库:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

2 遍历并展示数据

我们可以使用JSTL的<c:forEach>标签来遍历Servlet传递过来的userList,并使用EL表达式 来访问每个User对象的属性。

<table border="1">
    <thead>
        <tr>
            <th>ID</th>
            <th>姓名</th>
            <th>邮箱</th>
        </tr>
    </thead>
    <tbody>
        <%-- 使用c:forEach遍历request作用域中的userList --%>
        <c:forEach items="${userList}" var="user">
            <tr>
                <%-- 使用EL表达式访问User对象的属性 --%>
                <td>${user.id}</td>
                <td>${user.name}</td>
                <td>${user.email}</td>
            </tr>
        </c:forEach>
    </tbody>
</table>
  • items="${userList}"items属性指定要遍历的集合。${userList}是EL表达式,它会自动在page、request、session、application作用域中查找名为userList的属性,由于我们是在Servlet中将其存入request作用域的,所以这里能正确找到。
  • var="user"var属性定义了一个临时变量名,在每次循环中,user会引用集合中的当前元素(即一个User对象)。
  • ${user.id}:EL表达式会调用user对象的getId()方法(注意:EL会自动将属性名首字母大写并加上get前缀来寻找对应的getter方法),并将其返回值输出到页面。

浏览器会收到一个包含完整用户数据的HTML表格。

将数据库数据传递到JSP前台的完整流程,可以概括为以下几个关键步骤:

步骤 执行者 核心操作 目的
1 Servlet (Controller) JDBC查询数据库 获取原始数据
2 Servlet (Controller) 遍历ResultSet,封装为JavaBean集合 创建与数据库无关的模型数据
3 Servlet (Controller) request.setAttribute("key", data) 将模型数据放入请求作用域
4 Servlet (Controller) request.getRequestDispatcher().forward() 将请求(包含数据)转发给JSP
5 JSP (View) 使用JSTL的<c:forEach>和EL 从请求中获取数据并渲染成HTML

通过这一套严谨的流程,我们实现了业务逻辑、数据访问和视图展示的彻底分离,使得代码结构清晰、易于维护和扩展,是Java Web开发中值得遵循的最佳实践。


相关问答FAQs

问题1:为什么不应该在JSP页面中直接写JDBC代码来查询数据库?

JSP如何将数据库数据传递并展示到前台页面?

解答: 直接在JSP中编写JDBC代码是一种严重的反模式,主要弊端如下:

  1. 违反MVC原则:它将数据访问逻辑(模型)和视图展示逻辑(视图)混杂在一起,导致代码混乱,职责不清。
  2. 难以维护:一旦数据库连接信息或SQL语句需要变更,就必须修改JSP文件,增加了维护成本和风险,业务逻辑和页面逻辑的耦合使得任何一方的改动都可能影响另一方。
  3. 资源管理风险:在JSP中管理数据库连接的打开和关闭非常容易出错,稍有不慎就可能导致连接泄漏,最终耗尽数据库资源,使整个应用崩溃。
  4. 安全性与可测试性差:代码分散且难以进行单元测试,同时也更容易引入SQL注入等安全漏洞。

通过Servlet作为控制器来处理所有后台逻辑,可以完美地解决以上所有问题。

问题2:request.setAttribute(), session.setAttribute(), 和 application.setAttribute() 有什么区别?

解答: 这三个方法都用于在Web应用中存储数据,但它们的作用域(生命周期和可见范围)完全不同,选择哪个取决于数据的使用场景。

  • request.setAttribute()

    • 作用域:请求作用域。
    • 生命周期:仅在单次HTTP请求-响应周期内有效,当服务器将响应发送给客户端后,该请求结束,其中存储的所有数据都会被销毁。
    • 用途:最常用于在Servlet和JSP之间传递数据,将查询结果从Servlet传递给用于展示的JSP页面。
  • session.setAttribute()

    • 作用域:会话作用域。
    • 生命周期:在整个用户会话期间有效,会话从用户首次访问网站开始,直到浏览器关闭或会话超时(例如30分钟无操作)。
    • 用途:用于存储与特定用户相关的数据,用户的登录信息、购物车内容等,这些数据需要在用户浏览不同页面时持续可用。
  • application.setAttribute()

    • 作用域:应用作用域。
    • 生命周期:在整个Web应用程序的生命周期内有效,从服务器启动应用开始,直到服务器关闭或应用被卸载。
    • 用途:用于存储全局共享的数据,网站的配置参数、所有用户共享的缓存数据、在线用户计数器等,此作用域内的数据对所有用户的所有会话都是可见的,因此在使用时需考虑线程安全问题。

【版权声明】:本站所有内容均来自网络,若无意侵犯到您的权利,请及时与我们联系将尽快删除相关内容!

(0)
热舞的头像热舞
上一篇 2025-10-07 11:35
下一篇 2025-10-07 11:38

相关推荐

发表回复

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

联系我们

QQ-14239236

在线咨询: QQ交谈

邮件:asy@cxas.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信