两种跳转方式概述
| 特性 | 客户端跳转 (使用 response.sendRedirect) |
服务器端跳转 (使用 RequestDispatcher.forward) |
|---|---|---|
| 执行位置 | 浏览器 | 服务器 |
| 工作原理 | 服务器向浏览器返回一个 302 状态码和新的 URL,浏览器收到后重新发起一个新的请求到新地址。 |
服务器在内部将请求从一个资源(如 Servlet 或 JSP)转发给另一个资源,整个过程浏览器完全不知情。 |
| URL 地址栏 | 会改变为新的 URL。 | 不会改变,仍然显示原始请求的 URL。 |
| 数据传递 | 不能直接传递 request 范围内的数据,因为这是两个独立的请求,数据需要通过 URL 参数 (?key=value) 或 Session 传递。 |
可以传递 request 范围内的数据,因为是在同一个请求内流转,共享同一个 request 对象。 |
| 适用场景 | 跳转到外部网站。 需要改变 URL 的场景(如登录后重定向到主页)。 避免表单重复提交(使用 PRG 模式)。 |
在同一个 Web 应用内跳转。 需要共享 request 数据的场景。 希望对用户隐藏真实的资源路径。 |
客户端跳转 (response.sendRedirect)
这种方式最常用,尤其是在处理登录、注册等需要改变 URL 的操作后。

(图片来源网络,侵删)
在 Servlet 中实现
这是最标准、最推荐的做法,遵循了 MVC (Model-View-Controller) 设计模式。
LoginServlet.java
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 获取客户端提交的参数
String username = request.getParameter("username");
String password = request.getParameter("password");
// 2. 简单的业务逻辑判断
if ("admin".equals(username) && "password123".equals(password)) {
// 登录成功,使用 sendRedirect 进行客户端跳转
// URL 会变成 http://yourdomain.com/welcome.jsp
response.sendRedirect("welcome.jsp");
} else {
// 登录失败,跳转到错误页面,并传递错误信息
// 通过 URL 参数传递数据
response.sendRedirect("error.jsp?message=用户名或密码错误");
}
}
}
login.jsp (登录表单页面)
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">登录页面</title>
<style>
body { font-family: Arial, sans-serif; background-color: #f4f4f4; }
.container { width: 300px; margin: 100px auto; padding: 20px; background: #fff; border-radius: 5px; box-shadow: 0 0 10px rgba(0,0,0,0.1); }
input[type=text], input[type=password] { width: 100%; padding: 10px; margin: 10px 0; border: 1px solid #ddd; box-sizing: border-box; }
input[type=submit] { width: 100%; background-color: #4CAF50; color: white; padding: 10px; border: none; cursor: pointer; }
</style>
</head>
<body>
<div class="container">
<h2>用户登录</h2>
<form action="login" method="post">
<input type="text" name="username" placeholder="请输入用户名" required>
<input type="password" name="password" placeholder="请输入密码" required>
<input type="submit" value="登录">
</form>
</div>
</body>
</html>
welcome.jsp (登录成功页面)

(图片来源网络,侵删)
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">欢迎页面</title>
</head>
<body>
<h1>欢迎, <%= request.getParameter("username") %>!</h1>
<p>您已成功登录。</p>
<!-- 注意:这里的 username 是从上一个 request 中获取的,如果刷新页面可能会丢失 -->
<!-- 更好的做法是在登录成功后把用户信息存入 Session -->
</body>
</html>
error.jsp (登录失败页面)
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">错误页面</title>
</head>
<body>
<h1>登录失败</h1>
<p style="color: red;">
<%= request.getParameter("message") != null ? request.getParameter("message") : "未知错误" %>
</p>
<a href="login.jsp">返回登录</a>
</body>
</html>
服务器端跳转 (RequestDispatcher.forward)
适用于在应用内部流转,且需要共享 request 数据的场景。
在 Servlet 中实现
ProcessServlet.java
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/process")
public class ProcessServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 获取客户端提交的参数
String data = request.getParameter("data");
// 2. 可以对数据进行处理,并放入 request 范围内
request.setAttribute("processedData", "您输入的数据是: " + data);
// 3. 使用 forward 进行服务器端跳转
// URL 不会改变,仍然是 http://yourdomain.com/process
RequestDispatcher dispatcher = request.getRequestDispatcher("result.jsp");
dispatcher.forward(request, response);
}
}
processForm.jsp (提交表单的页面)

(图片来源网络,侵删)
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">数据处理页面</title>
</head>
<body>
<h2>数据提交与处理</h2>
<form action="process" method="post">
<input type="text" name="data" placeholder="请输入一些数据">
<input type="submit" value="提交处理">
</form>
</body>
</html>
result.jsp (处理结果页面)
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">处理结果</title>
</head>
<body>
<h1>处理结果</h1>
<p>
<%= request.getAttribute("processedData") %>
</p>
<p>
注意:查看浏览器地址栏,URL 仍然是 process,没有改变。
</p>
</body>
</html>
JSP 中的直接跳转 (不推荐)
虽然可以在 JSP 页面中直接使用脚本片段进行跳转,但这违背了 JSP 作为视图层、应尽量少写 Java 代码的原则,会使页面变得混乱难维护,仅作了解。
客户端跳转 (JSP 内)
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%
// 一些逻辑判断后...
response.sendRedirect("anotherPage.jsp");
%>
<!-- 这里的代码将不会被执行,因为响应已经重定向了 -->
<h1>这行不会显示</h1>
服务器端跳转 (JSP 内)
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="javax.servlet.RequestDispatcher" %>
<%
// 一些逻辑判断后...
request.setAttribute("key", "value");
RequestDispatcher dispatcher = request.getRequestDispatcher("target.jsp");
dispatcher.forward(request, response);
%>
<!-- 这里的代码也不会被执行 -->
<h1>这行也不会显示</h1>
- 优先使用 Servlet 控制器:让 Servlet (Controller) 负责接收请求、处理业务逻辑、决定跳转到哪个视图 (JSP),JSP 只负责展示数据,这是清晰的 MVC 模式。
- 数据传递:
- 如果使用
sendRedirect,需要传递数据时,优先使用 Session,URL 参数 (?key=value) 传递的数据会暴露在地址栏且有长度限制。 - 如果使用
forward,可以直接使用request.setAttribute()和request.getAttribute(),这是最高效的方式。
- 如果使用
- 选择合适的跳转方式:
- 登录、注册、退出后,需要改变 URL 以防止刷新重复提交,使用
sendRedirect。 - 在一个流程中,比如多步表单,需要共享数据,使用
forward。
- 登录、注册、退出后,需要改变 URL 以防止刷新重复提交,使用
- 避免在 JSP 中写 Java 跳转逻辑:保持 JSP 的纯净性,只包含 HTML、JSTL、EL 表达式和少量必要的 Java 代码。
希望这份详细的解释和示例能帮助你完全理解在 JSP 项目中进行页面跳转的各种方法!
