核心概念:转发 vs. 重定向
在开始写代码前,必须理解这两种跳转方式的根本区别,因为它们在用户体验和开发中应用场景完全不同。

| 特性 | 转发 | 重定向 |
|---|---|---|
| 英文 | Forward | Redirect |
| 实现方式 | request.getRequestDispatcher("目标路径").forward(request, response); |
response.sendRedirect("目标路径"); |
| 地址栏URL | 不变,显示的是请求发起的地址 | 改变,显示的是跳转后的新地址 |
| 请求次数 | 1次 HTTP 请求,客户端只发了一次请求,服务器内部处理并返回响应。 | 2次 HTTP 请求,客户端第一次请求后,服务器返回一个 302 状态码和新的 Location,客户端再发第二次请求。 |
| 共享数据 | 可以,因为是在服务器内部,同一个 request 对象在多个资源间传递,可以使用 request.setAttribute() 和 request.getAttribute() 共享数据。 |
不可以,因为第二次请求是完全独立的新的 request 对象,第一次请求中的数据会丢失。 |
| 性能 | 更高,只有一次网络传输。 | 较低,需要两次网络传输。 |
| 跳转范围 | 只能跳转到当前 Web 应用内部的资源。 | 可以跳转到任何地方,包括外部网站(如 https://www.baidu.com)。 |
转发
转发就像是办公室内部同事之间交接工作,你(客户端)把一个任务交给张三(Servlet A),张三处理不了,于是他把任务和所有材料(request 数据)一起交给了李四(Servlet B/JSP)来处理,整个过程你(客户端)并不知道任务被转交了,你只知道最终结果。
代码实现
我们创建一个简单的 Maven 项目来演示。
项目结构
java-page-demo
├── src
│ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ └── example
│ │ │ └── controller
│ │ │ └── ForwardServlet.java
│ │ └── webapp
│ │ ├── WEB-INF
│ │ │ └── web.xml
│ │ ├── index.jsp
│ │ └── target.jsp
│ └── test
└── pom.xml
pom.xml (添加 Servlet 依赖)

<dependencies>
<!-- Servlet API -->
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.0.0</version>
<scope>provided</scope>
</dependency>
<!-- JSP API -->
<dependency>
<groupId>jakarta.servlet.jsp</groupId>
<artifactId>jakarta.servlet.jsp-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
web.xml (配置 Servlet 映射)
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
version="6.0">
<servlet>
<servlet-name>ForwardServlet</servlet-name>
<servlet-class>com.example.controller.ForwardServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ForwardServlet</servlet-name>
<url-pattern>/forward</url-pattern>
</servlet-mapping>
</web-app>
index.jsp (发起跳转的页面)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>Forward Demo</title>
</head>
<body>
<h2>这是首页 index.jsp</h2>
<p>点击下面的链接,触发转发跳转。</p>
<!-- 链接到 Servlet,由 Servlet 进行转发 -->
<a href="${pageContext.request.contextPath}/forward">点击进行转发跳转</a>
</body>
</html>
ForwardServlet.java (处理转发逻辑的 Servlet)
package com.example.controller;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/forward") // 也可以在 web.xml 中配置
public class ForwardServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 在 request 中设置共享数据
request.setAttribute("messageFromServlet", "你好,这是从 ForwardServlet 传递过来的数据!");
// 2. 获取请求调度器,指定要转发的目标资源
// 注意:路径是相对于当前 webapp 根目录的
jakarta.servlet.RequestDispatcher dispatcher = request.getRequestDispatcher("/target.jsp");
// 3. 执行转发
dispatcher.forward(request, response);
}
}
target.jsp (跳转目标页面)

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>Target Page</title>
</head>
<body>
<h2>这是目标页面 target.jsp</h2>
<p>URL 地址栏没有改变,仍然是 <strong>/forward</strong>。</p>
<p>可以接收到从 Servlet 传递过来的数据:
<strong>${messageFromServlet}</strong>
</p>
</body>
</html>
运行流程:
- 访问
http://localhost:8080/java-page-demo/index.jsp。 - 点击链接,请求发送到
ForwardServlet(/forward)。 ForwardServlet设置数据,并将请求转发给target.jsp。- 服务器在内部处理
target.jsp,并将最终结果返回给浏览器。 - 浏览器显示
target.jsp的内容,但地址栏仍然是/forward。
重定向
重定向就像是公司前台给你一张新的地址卡片,你(客户端)来找前台(Servlet A)办事,前台说他办不了,然后给你一张写着新地址(URL)的卡片,并告诉你:“你自己去那里(Servlet B/JSP)办吧”,于是你离开当前地址,自己去访问新地址。
代码实现
web.xml (配置另一个 Servlet)
在之前的 web.xml 中添加:
<servlet>
<servlet-name>RedirectServlet</servlet-name>
<servlet-class>com.example.controller.RedirectServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RedirectServlet</servlet-name>
<url-pattern>/redirect</url-pattern>
</servlet-mapping>
RedirectServlet.java (处理重定向逻辑的 Servlet)
package com.example.controller;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/redirect")
public class RedirectServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 尝试设置数据(注意:这个数据在目标页面是获取不到的)
request.setAttribute("messageFromServlet", "这条数据会丢失!");
// 2. 执行重定向
// 注意:路径必须是完整的 URL(可以是应用内的,也可以是外部的)
response.sendRedirect(request.getContextPath() + "/target.jsp");
}
}
修改 index.jsp (添加重定向链接)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>Redirect Demo</title>
</head>
<body>
<h2>这是首页 index.jsp</h2>
<p>点击下面的链接,触发重定向跳转。</p>
<a href="${pageContext.request.contextPath}/redirect">点击进行重定向跳转</a>
</body>
</html>
**4. target.jsp (无需修改,
