Servlet如何向JSP传递参数?

99ANYc3cd6
预计阅读时长 32 分钟
位置: 首页 参数 正文

Servlet 作为控制器,负责处理业务逻辑和请求,然后将处理结果(数据)传递给 JSP 视图层进行展示,传递参数主要有三种方式,它们各有特点,适用于不同的场景。

servlet向jsp传递参数
(图片来源网络,侵删)

核心思想

Servlet 和 JSP 的本质区别在于:

  • Servlet: Java 代码,负责逻辑控制
  • JSP: HTML + Java 代码片段,负责数据展示

Servlet 向 JSP 传参的本质就是:Servlet 在处理完请求后,将数据存入某个“容器”中,然后通过 forwardredirect 方式将请求“转发”或“重定向”到 JSP 页面,JSP 再从这个“容器”中取出数据并展示。

重要提示:在 Servlet 中传递数据给 JSP,强烈推荐使用 RequestDispatcher.forward() 进行请求转发,而不是 response.sendRedirect() 进行重定向。

  • 请求转发 (forward):服务器内部行为,浏览器地址栏不会改变,数据通过 HttpServletRequest 对象传递,就像一个方法调用,数据可以共享。
  • 重定向 (sendRedirect):浏览器行为,服务器返回一个 302 状态码和新的 URL,浏览器会向这个新 URL 发起新的请求,数据无法通过 HttpServletRequest 共享,必须通过 URL 参数或 Session 来传递,这会导致 JSP 无法直接获取到 Servlet 存入 request 的属性。

三种主要传递方式

我们将通过一个完整的例子来演示这三种方式。

场景: 用户在 Servlet 中计算 1 + 1 的结果,然后将结果和一条消息传递给 JSP 页面进行显示。

准备工作

  1. 创建一个 Web 项目 (例如在 Eclipse 或 IntelliJ IDEA 中)。
  2. 配置 web.xml (如果使用较新的 Servlet API,可以省略,但为了兼容性,我们这里写一下)。
<!-- web.xml -->
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <servlet>
        <servlet-name>ParameterPassingServlet</servlet-name>
        <servlet-class>com.example.ParameterPassingServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ParameterPassingServlet</servlet-name>
        <url-pattern>/passParams</url-pattern>
    </servlet-mapping>
</web-app>

使用 request.setAttribute()request.getRequestDispatcher().forward()

这是最常用、最推荐的方式,它通过将数据作为请求属性存储在 HttpServletRequest 对象中来实现传递。

Servlet 代码 (ParameterPassingServlet.java)

package com.example;
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;
@WebServlet("/passParams") // 使用注解简化配置,可以不用在 web.xml 中配置
public class ParameterPassingServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1. 设置请求属性
        // 参数1: 属性名 (String),在 JSP 中通过这个名来取值
        // 参数2: 属性值 (Object),可以是任意 Java 对象
        request.setAttribute("message", "Hello from Servlet!");
        request.setAttribute("result", 2); // 1 + 1 的结果
        // 2. 获取请求分发器,指定要转发的 JSP 页面
        // 注意:这里的路径是相对于 Web 应用的根目录 (webapp) 的
        request.getRequestDispatcher("/result.jsp").forward(request, response);
    }
}

JSP 代码 (result.jsp)

在 JSP 中,我们使用 EL (Expression Language) 表达式 来轻松获取 request 中的属性,EL 是 JSP 2.0 及以后版本推荐的获取数据的方式,比传统的 JSP Scriptlet (<% ... %>) 更简洁、更安全。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<head>Result Page</title>
</head>
<body>
    <h1>从 Servlet 传递过来的参数</h1>
    <p>消息: ${message}</p>
    <p>计算结果: ${result}</p>
    <!-- 也可以使用 JSTL 的 c:out 标签,它更安全,可以防止 XSS 攻击 -->
    <%-- <p>消息: <c:out value="${message}"/></p> --%>
</body>
</html>

访问流程:

  1. 浏览器访问 http://localhost:8080/your-app-name/passParams
  2. ParameterPassingServlet 被调用。
  3. Servlet 将 messageresult 存入 request 对象。
  4. Servlet 将请求转发/result.jsp
  5. result.jsp 执行,EL 表达式 ${message}${result}request 作用域中取出对应的值并显示。
  6. 浏览器地址栏仍然是 /passParams

使用 request.setAttribute()response.sendRedirect()

这种方式不推荐用于传递数据,因为它会丢失 request 中的所有属性,但它偶尔会用于需要改变 URL 的场景(在 POST 请求后重定向到 GET 请求页面,避免表单重复提交)。

为了在重定向时传递数据,我们需要将数据拼接到 URL 中。

Servlet 代码

package com.example;
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;
@WebServlet("/redirectParams")
public class RedirectServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1. 设置请求属性 (这部分其实没有用,因为重定向后 request 对象是新的)
        request.setAttribute("message", "This message will be LOST!");
        // 2. 将数据作为 URL 参数拼接
        String msg = "Hello from Redirect!";
        int res = 2;
        // response.sendRedirect 的路径必须是绝对路径或相对于当前应用的路径
        // 使用 URLEncoder.encode() 对参数进行编码,防止特殊字符导致 URL 错误
        String encodedMsg = java.net.URLEncoder.encode(msg, "UTF-8");
        response.sendRedirect("redirect_result.jsp?message=" + encodedMsg + "&result=" + res);
    }
}

JSP 代码 (redirect_result.jsp)

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<head>Redirect Result Page</title>
</head>
<body>
    <h1>通过 URL 参数传递过来的数据</h1>
    <p>消息: ${param.message}</p>
    <p>计算结果: ${param.result}</p>
    <!-- param 是 JSP 的隐式对象,专门用来获取请求参数 -->
</body>
</html>

访问流程:

  1. 浏览器访问 http://localhost:8080/your-app-name/redirectParams
  2. RedirectServlet 被调用。
  3. Servlet 发送一个 302 响应,告诉浏览器去访问 http://localhost:8080/your-app-name/redirect_result.jsp?message=Hello%20from%20Redirect!&result=2
  4. 浏览器立即发起一个新的 GET 请求到新的 URL。
  5. redirect_result.jsp 被调用,EL 表达式 ${param.message}${param.result} 从新的 request 对象的参数列表中获取值。
  6. 浏览器地址栏变为 .../redirect_result.jsp?message=...&result=...

使用 HttpSession

当数据需要在多个请求之间共享时(用户登录信息),就应该使用 HttpSession,它是一个用户级别的会话对象,数据在整个会话期间都存在。

Servlet 代码

package com.example;
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.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/sessionParams")
public class SessionServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1. 获取或创建 Session 对象
        HttpSession session = request.getSession();
        // 2. 将数据存入 Session 作用域
        session.setAttribute("user", "John Doe");
        session.setAttribute("loginTime", new java.util.Date().toString());
        // 3. 转发到 JSP 页面
        request.getRequestDispatcher("/session_result.jsp").forward(request, response);
    }
}

JSP 代码 (session_result.jsp)

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<head>Session Result Page</title>
</head>
<body>
    <h1>从 Session 中获取的数据</h1>
    <p>用户名: ${sessionScope.user}</p>
    <p>登录时间: ${sessionScope.loginTime}</p>
    <!-- sessionScope 是 EL 的隐式对象,明确指定从 Session 作用域查找 -->
    <!-- 也可以直接写 ${user},EL 会按 page -> request -> session -> application 的顺序查找 -->
</body>
</html>

访问流程:

  1. 浏览器访问 http://localhost:8080/your-app-name/sessionParams
  2. SessionServlet 被调用,创建 Session 并存入数据。
  3. 请求被转发到 session_result.jsp
  4. JSP 从 session 作用域中取出数据并显示。
  5. 即使用户之后访问其他页面,只要 Session 未失效,这些数据依然可以通过 ${user} 获取。

总结与对比

特性 request.setAttribute() + forward() sendRedirect() + URL 参数 session.setAttribute()
作用域 Request 作用域 (仅当前请求有效) Request 作用域 (新请求) Session 作用域 (整个会话有效)
数据可见性 数据不会暴露在 URL 中 数据暴露在 URL 中 数据不会暴露在 URL 中
安全性 (敏感信息不能放 URL)
数据大小 无限制 (受服务器内存影响) 受 URL 长度限制 (2KB) 无限制 (受服务器内存影响)
适用场景 最常用,控制器向视图传递数据,一次请求完成。 需要改变 URL,或跨应用传递简单数据。 用户状态管理,如登录信息、购物车等需要跨页面共享的数据。
代码示例 request.setAttribute("key", value);
request.getRequestDispatcher("xxx.jsp").forward(req, resp);
response.sendRedirect("xxx.jsp?key=value"); request.getSession().setAttribute("key", value);
JSP 取值 ${key} ${param.key} ${sessionScope.key}${key}

最佳实践

  1. 优先使用 request.setAttribute() + forward():这是 MVC 模式中 Controller 向 View 传递数据的标准方式,简洁、安全、高效。
  2. 避免在 URL 中传递敏感信息:永远不要使用 URL 参数传递密码、Token 等敏感数据。
  3. 合理使用 Session:Session 会占用服务器内存,不要滥用,只在真正需要跨请求共享数据时使用,并且在数据不再需要时及时移除 (session.removeAttribute()) 或使 Session 失效 (session.invalidate())。
  4. 使用 EL 和 JSTL:在 JSP 中,尽量使用 EL 表达式和 JSTL 标签库来处理数据,而不是使用过时的 Scriptlet (<% ... %>),这样代码更清晰、更易于维护。
-- 展开阅读全文 --
头像
适马85mm f/1.4 ART镜头参数有何亮点?
« 上一篇 今天
MacBook Pro拆机大全,深度拆解有何发现?
下一篇 » 今天

相关文章

取消
微信二维码
支付宝二维码

最近发表

标签列表

目录[+]