1. Forward (请求转发 / 直接转发)
-
核心思想:服务器内部的“移花接木”。
-
工作流程:
- 客户端(例如浏览器)向服务器发送一个 HTTP 请求(比如请求一个 Servlet A)。
- Servlet A 开始处理请求,但在处理过程中,它决定将这个请求交给服务器上的另一个资源(比如 Servlet B 或一个 JSP 页面)来完成后续的处理和响应生成。
- Servlet A 使用 forward 机制,将原始的请求对象 (request) 和响应对象 (response) “原封不动”地传递给 Servlet B。
- Servlet B 接手后,继续处理这个请求,并最终生成响应内容,通过原始的 response 对象发送回客户端。
-
关键特征:
- 一次 HTTP 请求:从客户端的角度看,它只发送了一次请求,也只收到了一次响应。整个转发过程对客户端是透明的。
- URL 不变:浏览器的地址栏中显示的 URL 仍然是最初请求 Servlet A 的那个 URL,不会改变。
- 数据共享:由于是同一个 request 对象在传递,所以在 Servlet A 中往 request 里存入的数据(例如通过 request.setAttribute()),在 Servlet B 中可以无障碍地获取 (request.getAttribute())。这对于在不同处理单元间传递数据非常方便。
- 服务器端行为:整个转发过程完全在服务器内部完成,不涉及与客户端的额外通信。
- 效率较高:因为它只涉及服务器内部的资源调用,没有额外的网络往返。
-
你的比喻很形象:“A找B借钱,B说没有,B去找C借,借到借不到都会把消息传递给A”。
- 这里,A 是客户端,B 是第一个 Servlet,C 是被转发到的 Servlet/JSP。B 在内部完成了向 C 的“请求”,然后将结果直接返回给 A。A 始终认为是在和 B 打交道。
-
Java Web 中的实现:通常使用 RequestDispatcher 对象的 forward() 方法。
// 在 Servlet A 中 RequestDispatcher dispatcher = request.getRequestDispatcher("/servletB_or_page.jsp"); dispatcher.forward(request, response);
2. Redirect (重定向 / 间接转发)
-
核心思想:服务器告诉客户端“你走错门了,去那边那个门”。
-
工作流程:
- 客户端向服务器发送一个 HTTP 请求(比如请求 Servlet X)。
- Servlet X 处理请求后,判断需要将用户引导到另一个 URL(可能在同一个服务器,也可能在完全不同的服务器)。
- Servlet X 向客户端发送一个特殊的 HTTP 响应。这个响应的状态码通常是 302 Found (临时重定向) 或 301 Moved Permanently (永久重定向),并且在响应头 (Header) 的 Location 字段中指明了新的 URL。
- 客户端浏览器接收到这个重定向响应后,会读取 Location 头中的新 URL,然后自动地、立刻地向这个新 URL 发起一个全新的 HTTP 请求。
- 新的服务器(或同一个服务器上的新资源)处理这个新的请求,并返回响应。
-
关键特征:
- 两次 HTTP 请求:客户端实际上发起了两次请求。第一次请求 Servlet X,第二次请求新的 URL。
- URL 改变:浏览器的地址栏会更新,显示为第二次请求的那个新 URL。
- 数据不直接共享 (原始请求):因为是两次完全独立的请求,所以第一次请求的 request 对象及其中的数据,在第二次请求中是不可用的。如果需要在重定向过程中传递少量数据,通常会将其作为新 URL 的查询参数 (query parameters,例如 newUser.jsp?userId=123),或者通过 Session 来传递。
- 客户端行为驱动:重定向的“跳转”是由客户端浏览器根据服务器的指示完成的。
- 效率相对较低:因为它涉及两次客户端与服务器之间的完整 HTTP 通信往返。
-
你的比喻也很到位:“A找B借钱,B说没有,让A去找C借”。
- 这里,A 是客户端,B 是第一个 Servlet。B 没有直接帮 A 解决问题,而是告诉 A 一个新的地址 C(新的 URL),让 A 自己再去 C 那里请求。A 的地址栏会从 B 更新到 C。
-
Java Web 中的实现:通常使用 HttpServletResponse 对象的 sendRedirect() 方法。
// 在 Servlet X 中 response.sendRedirect("http://www.new-target.com/somepage.jsp"); // 或者重定向到同一应用内的其他资源 // response.sendRedirect(request.getContextPath() + "/anotherServlet");
一张表格总结 Forward 与 Redirect 的区别:
特性 | Forward (请求转发) | Redirect (重定向) |
---|---|---|
HTTP请求次数 | 1 次 | 2 次 |
浏览器URL变化 | 不变 (显示原始请求的URL) | 改变 (显示重定向后的新URL) |
数据共享 (Request Scope) | 共享 (原始request对象及其数据被传递) | 不共享 (第二次是全新的request对象,原始数据丢失) |
发生位置 | 服务器内部完成 | 服务器指示,客户端浏览器发起新请求 |
资源范围 | 只能转发到同一Web应用程序内部的资源 | 可以重定向到任何有效的URL (内部或外部服务器) |
效率 | 较高 | 较低 (因有额外网络往返) |
用途举例 | MVC模式中Controller处理后转发给View (JSP) 进行页面渲染。 | 用户登录成功后跳转到用户主页;处理完POST请求后重定向到一个GET页面(避免表单重复提交)。 |
Java实现 | request.getRequestDispatcher(...).forward(req, res) | response.sendRedirect("...") |
什么时候用 Forward?什么时候用 Redirect?
-
使用 Forward 的场景:
- 当你想在服务器内部将处理逻辑从一个组件传递到另一个组件,并且这些组件需要共享请求数据时。
- 典型的 MVC (Model-View-Controller) 架构中,Controller 处理完业务逻辑和数据准备后,通常会 forward 给一个 View (如 JSP) 来渲染页面。用户看到的 URL 不变,但页面内容是动态生成的。
-
使用 Redirect 的场景:
-
当一个操作完成后,为了防止用户刷新页面导致操作被重复执行(尤其是对于 POST 请求,如提交订单、发帖等),通常会 redirect 到一个结果展示页面(通常是 GET 请求)。这被称为 "Redirect After Post" 模式。
详解
-
当用户需要被导向到另一个完全不同的网站,或者当前应用的另一个功能模块,并且希望用户浏览器地址栏明确显示新的位置时。
-
例如,用户未登录时访问受保护资源,可以 redirect 到登录页面。登录成功后,再 redirect 回之前的页面或用户主页。
-
Comments NOTHING