1. 概述
在Java Servlet开发中,我们经常需要将请求委托给其他资源处理。这时有两种选择:转发(Forward)或重定向(Redirect)。本文将深入探讨这两种机制的实现方式、核心差异及最佳实践。
2. Maven依赖
首先添加Servlet核心依赖:
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.1.0-M2</version>
</dependency>
最新版本可查阅Maven中央仓库
3. 转发机制
直接看代码实现:
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
RequestDispatcher dispatcher = getServletContext()
.getRequestDispatcher("/forwarded");
dispatcher.forward(req, resp);
}
核心逻辑:
- 从父Servlet获取
RequestDispatcher
对象 - 指向目标服务器资源
/forwarded
- 执行转发操作
当客户端访问http://localhost:8081/hello?name=Dennis
时:
- 请求在服务器内部被转发到
/forwarded
- 浏览器地址栏保持不变
- ✅ 原始请求参数(如
name=Dennis
)自动保留
4. 重定向机制
重定向的实现更简洁:
protected void doGet(HttpServletRequest req, HttpServletResponse resp){
resp.sendRedirect(req.getContextPath() + "/redirected");
}
核心逻辑:
- 直接使用原始
response
对象 - 构造目标URL(注意添加
getContextPath()
) - 发送重定向指令
当客户端访问http://localhost:8081/welcome?name=Dennis
时:
- 服务器返回302状态码和Location头
- 浏览器自动跳转到
http://localhost:8081/redirected
- ❌ 原始请求参数丢失
Spring框架中的重定向实现可参考专属文章
5. 核心差异对比
特性 | 转发 (Forward) | 重定向 (Redirect) |
---|---|---|
处理位置 | 服务器内部完成 | 客户端浏览器执行跳转 |
URL可见性 | 地址栏不变 | 地址栏显示新URL |
请求对象 | 复用原始request/response | 创建全新request对象 |
参数传递 | ✅ 自动保留所有参数 | ❌ 参数丢失(需手动处理) |
典型场景 | 内部资源调度 | 表单提交后跳转、登录重定向 |
性能开销 | ⚠️ 较低(单次请求) | ⚠️ 较高(两次HTTP往返) |
关键踩坑点:
- 重定向后若需保留参数,必须通过
HttpSession
手动存储 - 转发路径需以
/
开头(相对于应用根路径) - 重定向URL必须包含
getContextPath()
避免路径错误
6. 最佳实践总结
选择机制时遵循以下原则:
使用转发(Forward)的场景:
- 需要复用原始请求参数
- 执行内部业务逻辑跳转
- 不希望用户感知URL变化
- ✅ 例如:MVC框架中Controller到View的跳转
使用重定向(Redirect)的场景:
- 需要更新浏览器地址栏
- 避免表单重复提交(Post/Redirect/Get模式)
- 跨应用跳转
- ✅ 例如:登录成功后跳转到首页
示例代码已上传至GitHub仓库