在 Web 开发中,我们经常需要在不同页面之间跳转,比如登录成功后跳到首页、提交表单后跳到结果页面。这时,常见的两种跳转方式就是 请求转发(Request Forward) 和 重定向(Redirect)。
虽然它们都能实现"页面跳转",但底层原理、适用场景和实现方式都不同。
一、请求转发(Forward)
1. 定义
请求转发是服务器内部的一种操作方式,它允许服务器将客户端请求在服务器内部转发给另一个资源(如 JSP 或 Servlet)进行处理,而客户端对转发行为是"不可见"的。
简单理解:
用户发送请求 → 服务器内部转发 → 返回最终响应给用户(URL 不变)
2. 工作原理
-
客户端发送请求到服务器。
-
服务器接收请求,并在内部通过
RequestDispatcher
将请求转发给另一个资源。 -
转发的资源使用相同的请求对象
request
和响应对象response
。 -
客户端看到的 URL 不会改变。
3. 使用方式
java
// Servlet 示例
RequestDispatcher dispatcher = request.getRequestDispatcher("target.jsp");
dispatcher.forward(request, response);
4. 特点
-
地址栏 URL 不变,对用户透明。
-
请求作用域共享 ,转发后的资源可以访问原请求中的数据(如
request.setAttribute()
)。 -
服务器内部操作,效率较高。
-
不能转发到其他服务器或不同的域名。
5. 典型场景
-
登录成功后,转发到用户首页。
-
请求处理后将结果展示在 JSP 页面。
-
MVC 模式中,Controller 转发给 View。
6. Java示例
java
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String username = req.getParameter("username");
String password = req.getParameter("password");
if ("admin".equals(username) && "123".equals(password)) {
// 存储数据到 request
req.setAttribute("user", username);
// 请求转发到首页
req.getRequestDispatcher("/home.jsp").forward(req, resp);
} else {
req.setAttribute("msg", "用户名或密码错误");
req.getRequestDispatcher("/login.jsp").forward(req, resp);
}
}
}
二、重定向(Redirect)
1. 定义
重定向是服务器向客户端发送一个新的 URL,让浏览器再次发起请求。浏览器地址栏会发生变化。
简单理解:
用户发送请求 → 服务器返回 302 状态码和新 URL → 浏览器重新请求新 URL → 返回响应
2. 工作原理
-
客户端发送请求到服务器。
-
服务器通过
response.sendRedirect("新地址")
告诉浏览器去请求新的 URL。 -
浏览器收到响应后,再次发送请求到新的 URL。
-
客户端地址栏发生变化。
3. 使用方式
java
// Servlet 示例
response.sendRedirect("target.jsp");
4. 特点
-
地址栏 URL 会改变。
-
请求作用域不共享,相当于新的请求。
-
可以重定向到其他网站。
-
需要客户端再次发起请求,效率略低于转发。
5. 典型场景
-
表单提交后避免重复提交(Post/Redirect/Get 模式)。
-
登录成功后跳转到另一个模块或不同域的页面。
-
页面重构或网站 URL 改变时进行跳转。
6. Java示例
java
@WebServlet("/loginRedirect")
public class LoginRedirectServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String username = req.getParameter("username");
String password = req.getParameter("password");
if ("admin".equals(username) && "123".equals(password)) {
// 登录成功后重定向到首页
resp.sendRedirect(req.getContextPath() + "/home.jsp");
} else {
// 带参数重定向(URL 拼接)
resp.sendRedirect(req.getContextPath() + "/login.jsp?error=1");
}
}
}
三、请求转发与重定向的对比
特性 | 请求转发(Forward) | 重定向(Redirect) |
---|---|---|
URL显示 | 不变 | 改变 |
请求对象 | 共享 | 不共享,新的请求 |
浏览器行为 | 浏览器不感知 | 浏览器必须发起新请求 |
可跨域 | 否 | 可以 |
性能 | 高(服务器内部操作) | 较低(客户端需再次请求) |
使用场景 | 内部资源跳转,如 MVC 转发 | 表单防重、跨站跳转 |
四、与安全相关的提示
请求转发和重定向在实际开发中,需要注意一些安全问题,特别是 SQL 注入 和 开放重定向:
-
SQL 注入
-
转发或重定向本身不会直接导致 SQL 注入,但如果传递参数没有做安全处理,攻击者可以通过 URL 或表单注入恶意 SQL。
-
建议:使用 PreparedStatement 或参数化查询,避免直接拼接 SQL。
-
-
开放重定向风险
-
重定向如果直接使用用户提供的 URL,可能被攻击者利用跳转到恶意网站。
-
建议:对重定向的 URL 做 白名单校验,不要直接使用用户输入。
-
五、实用小 Tips
- 使用转发传递数据
java
request.setAttribute("msg", "登录成功");
request.getRequestDispatcher("home.jsp").forward(request, response);
- 使用重定向避免重复提交
java
response.sendRedirect("home.jsp");
- 避免跨站重定向漏洞
java
String target = request.getParameter("url");
if (target != null && target.startsWith("/app")) {
response.sendRedirect(target);
} else {
response.sendRedirect("/app/home.jsp");
}
六、总结
-
请求转发:服务器内部跳转,地址栏不变,请求共享,适合内部资源处理。
-
重定向:客户端跳转,地址栏改变,不共享请求,适合防重、跨站跳转。
-
安全方面,注意 SQL 注入 和 开放重定向。
掌握了请求转发与重定向的原理、使用方式及场景,你就能在 Java Web 开发中更加灵活地处理请求和页面跳转。