重定向是服务器返回 3xx 让浏览器重新访问新 URL(地址栏会改变,需二次请求),而请求转发只在同一服务器内部把同一 request 转给其他资源处理(一次请求,地址栏不变)。
一、重定向(Redirect)—— 客户端跳转
工作流程

-
请求阶段:
-
客户端访问 URL-A(如
/login)
-
-
服务端响应:
-
返回 3xx 状态码(如
302)和Location头(如/dashboard)
-
-
客户端行为:
-
自动向新 URL(
/dashboard)发起第二次请求
-
-
最终结果:
-
浏览器地址栏 显示新 URL
-
核心特点
| 维度 | 说明 |
|---|---|
| 执行层级 | 客户端主导跳转(浏览器自动发起新请求) |
| HTTP状态码 | 3xx(如 301 永久重定向、302 临时重定向、307 临时重定向保留方法) |
| 地址栏变化 | ✅ 显示新 URL |
| 请求次数 | ≥ 2 次(每次跳转需完整请求) |
| 数据传递 | ❌ 原始请求参数丢失(除非手动拼接到新URL) |
| 性能开销 | 较高(多次网络往返) |
典型场景
-
用户登录后跳转到首页
-
网站改版后旧链接指向新地址
-
支付完成跳转回商户页面
二、请求转发(Forward)—— 服务端跳转
工作流程

-
请求阶段:
-
客户端访问 URL-A(如
/process)
-
-
服务端内部:
-
服务端组件(如 Servlet)将请求转发给另一组件(如 JSP)
-
不返回响应给客户端
-
-
最终响应:
-
最终处理组件生成响应,直接返回给客户端
-
浏览器地址栏 仍显示原始 URL
-
核心特点
| 维度 | 说明 |
|---|---|
| 执行层级 | 服务端内部跳转(客户端无感知) |
| HTTP状态码 | 200(客户端只收到一次响应) |
| 地址栏变化 | ❌ 保持原始 URL |
| 请求次数 | 1 次 |
| 数据传递 | ✅ 共享同一个 request 对象(可传递参数) |
| 性能开销 | 低(无额外网络请求) |
典型场景
-
MVC 架构中 Controller 调用 View 渲染页面
-
权限验证失败跳转到错误页(保持原始URL)
-
多步骤表单处理(各步骤共享表单数据)
三、核心区别对比表
| 特性 | 重定向(Redirect) | 请求转发(Forward) |
|---|---|---|
| 跳转控制方 | 客户端(浏览器) | 服务端(如 Servlet/JSP) |
| 地址栏变化 | ✅ 显示新 URL | ❌ 保持原 URL |
| HTTP 请求次数 | ≥ 2 次 | 1 次 |
| 数据共享 | ❌ 需手动传参(URL参数/cookies) | ✅ 通过 request.setAttribute() 传递 |
| 性能 | 较差(多次网络往返) | 较好(服务端内部调度) |
| 目标资源范围 | 可跳转任意 URL(包括外部域名) | 仅限当前应用内部资源 |
| 实现代码示例 | response.sendRedirect("/new-path") | request.getRequestDispatcher().forward() |
四、关键注意事项
1. 重定向陷阱
-
循环重定向: A → B → A → B...(浏览器报错
ERR_TOO_MANY_REDIRECTS) -
解决方案:
-
检查重定向逻辑终止条件
-
用 301 代替 302 避免浏览器重复判断
-
2. 转发限制
-
响应已提交: 若已调用
response.getWriter()则不能再转发(抛出IllegalStateException) -
解决方案: 在转发前避免输出响应内容
3. 跨域问题
| 方式 | 跨域支持 |
|---|---|
| 重定向 | ✅ 可跳转外部域名 |
| 请求转发 | ❌ 仅限同应用内部 |
五、如何选择?
-
用重定向 When:
-
需要地址栏更新(如登录后跳转)
-
跳转到外部网站
-
避免表单重复提交(PRG模式:Post/Redirect/Get)
-
-
用请求转发 When:
-
保持地址栏不变(如错误页面)
-
需要传递复杂对象(如数据库查询结果)
-
提升性能(避免额外网络请求)
-
📌 黄金法则: 需更新地址栏 → 重定向 需隐藏实现细节 → 请求转发
六、代码示例
1. 重定向(Java Servlet)
// 丢失原始请求参数
response.sendRedirect("/new-page");
// 保留参数(手动拼接)
String param = "?user=" + URLEncoder.encode(userName, "UTF-8");
response.sendRedirect("/dashboard" + param);
2. 请求转发(Java Servlet)
// 传递数据
request.setAttribute("data", queryResult);
// 转发到JSP
RequestDispatcher dispatcher = request.getRequestDispatcher("/result.jsp");
dispatcher.forward(request, response);
总结
| 机制 | 本质 | 地址栏 | 数据传递 | 性能 |
|---|---|---|---|---|
| 重定向 | 客户端跳转(二次请求) | 变化 | 需手动处理 | 较低 |
| 请求转发 | 服务端跳转(内部调度) | 不变 | 自动共享请求域数据 | 较高 |
选择策略:
-
需要 SEO 友好的新 URL → 301 重定向
-
多步骤表单共享数据 → 请求转发
-
支付后防止刷新重复扣款 → 302/307 重定向


3302

被折叠的 条评论
为什么被折叠?



