几个问题(十六)-------Servlet内部跳转和外部跳转的区别,底层实现原理

本文详细介绍了Servlet中两种页面跳转的方式:redirect和forward。redirect是客户端重定向,可以跳转到任何URL,地址栏会发生变化;forward是服务器端内部重定向,仅限于同一Web应用,地址栏不变。此外,还解释了两种方式在参数传递和路径处理上的差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Servlet页面跳转分两部分,一是发生在Servlet,一是在JSP,其实JSP也就是servlet,不过还是有点差异。

当然,在servlet中,一般跳转都发生在doGet, doPost等方法里面。

一、原理
1) redirect 方式
response.sendRedirect("/a.jsp");
页面的路径是相对路径。sendRedirect可以将页面跳转到任何页面,不一定局限于本web应用中,如:
response.sendRedirect("http://www.ycul.com");

跳转后浏览器地址栏变化。
这种方式要传值出去的话,只能在url中带parameter或者放在session中,无法使用request.setAttribute来传递。

这种方式是在客户端作的重定向处理。该方法通过修改HTTP协议的HEADER部分,对浏览器下达重定向指令的,让浏览器对在location中指定的URL提出请求,使浏览器显示重定向网页的内容。该方法可以接受绝对的或相对的URLs。如果传递到该方法的参数是一个相对的URL,那么Web container在将它发送到客户端前会把它转换成一个绝对的URL。public void doPost(HttpServletRequest request,HttpServletResponse response)    throws ServletException,IOException
{
        response.setContentType("text/html; charset=UTF-8");
        response.sendRedirect("/index.jsp");
}


2) forward方式
RequestDispatcher dispatcher = request.getRequestDispatcher("/a.jsp");
dispatcher .forward(request, response);
页面的路径是相对路径。forward方式只能跳转到本web应用中的页面上。

跳转后浏览器地址栏不会变化。
使用这种方式跳转,传值可以使用三种方法:url中带parameter,session,request.setAttribute

这种方式是在服务器端作的重定向。

服务器往client发送数据的过程是这样的:服务器在向客户端发送数据之前,是先将数据输出到缓冲区,然后将缓冲区中数据发送给client端。什么时候将缓冲区里的数据发送给client端呢?

(1)当对来自client的request处理完,并把所有数据输出到缓冲区。

(2)当缓冲区满。

(3)在程序中调用缓冲区的输出方法out.flush()或response.flushbuffer(),web container才将缓冲区中的数据发送给client。

这种重定向方式是利用服务器端的缓冲区机制,在把缓冲区的数据发送到客户端之前,原来的数据不发送,将执行转向重定向页面,发送重定向页面的数据,重定向调用页的数据将被清除。

如果在<JSP:FORWORD>之前有很多输出,前面的输出已使缓冲区满,将自动输出到客户端,那么这种重定向方式将不起作用,这一点应该特别注意。

public void doPost(HttpServletRequest request,HttpServletResponse response)   throws ServletException,IOException
{
        response.setContentType("text/html; charset=UTF-8");
        ServletContext sc = getServletContext();
        RequestDispatcher rd = null;
        rd = sc.getRequestDispatcher("/index.jsp");
        rd.forward(request, response);
}

二、区别.

1、forward重定向是在容器内部实现的同一个Web应用程序的重定向,所以forward方法只能重定向到同一个Web应用程序中的一个资源,重定向后浏览器地址栏URL不变,而  sendRedirect方法可以重定向到任何URL, 因为这种方法是修改http头来实现的,URL没什么限制,重定向后浏览器地址栏URL改变。
2、forward重定向将原始的HTTP请求对象(request)从一个servlet实例传递到另一个实例,而采用sendRedirect方式两者不是同一个application。
3、基于第二点,参数的传递方式不一样。forward的form参数跟着传递,所以在第二个实例中可以取得HTTP请求的参数。sendRedirect只能通过链接传递参数,response.sendRedirect(“login.jsp?param1=a”)。
4、sendRedirect能够处理相对URL,自动把它们转换成绝对URL,如果地址是相对的,没有一个‘/’,那么Web container就认为它是相对于当前的请求URI的。比如,如果为response.sendRedirect("login.jsp"),则会从当前servlet 的URL路径下找login.jsp: http://localhost:8080/····· 重定向的URL: http://localhost:8080/·····/····/login.jsp,如果为response.sendRedirect("/login.jsp")则会从当前应用径下查找url:http://localhost:8080/login.jsp。而forward不能这样处理相对路径。
java 他们的区别是:
response.sendRedirect是向客户浏览器发送页面重定向指令,浏览器接收后将向web服务器重新发送页面请求,所以执行完后浏览器的url显示的是跳转后的页面。跳转页面可以是一个任意的url(本服务器的和其他服务器的均可)。RequestDispatcher.forward则是直接在服务器中进行处理,将处理完后的信息发送给浏览器进行显示,所以完成后在url中显示的是跳转前的页面。
在forward的时候将上一页面中传送的request和response信息一同发送给下一页面(而response.sendRedirect不能将上一页面的request和response信息发送到下一页面)。由于forward是直接在服务器中进行处理,所以forward的页面只能是本服务器的。 


JSP:
1) response.sendRedirect();
和servlet的response.sendRedirect()方式一样。

此语句前不允许有out.flush(),如果有,会有异常:
java.lang.IllegalStateException: Can't sendRedirect() after data has committed to the client.
at com.caucho.server.connection.AbstractHttpResponse.sendRedirect(AbstractHttpResponse.java:558)
...
跳转后浏览器地址栏变化
如果要跳到不同主机下,跳转后,此语句后面的语句会继续执行,如同新开了线程,但是对response的操作已经无意义了;
如果要跳到相同主机下,此语句后面的语句执行完成后才会跳转;


2) response.setHeader("Location","");
此语句前不允许有out.flush(),如果有,页面不会跳转。
跳转后浏览器地址栏变化
此语句后面的语句执行完成后才会跳转

3) <jsp:forward page="" />
此语句前不允许有out.flush(),如果有,会有异常:
java.lang.IllegalStateException: forward() not allowed after buffer has committed.
at com.caucho.server.webapp.RequestDispatcherImpl.forward(RequestDispatcherImpl.java:134)
at com.caucho.server.webapp.RequestDispatcherImpl.forward(RequestDispatcherImpl.java:101)
at com.caucho.jsp.PageContextImpl.forward(PageContextImpl.java:836)
...
跳转后浏览器地址栏不变,但是只能跳到当前主机下
此语句后面的语句执行完成后才会跳转


本文来自网络。

<think>我们正在讨论请求转移(即请求转发)响应重定向的区别及应用场景。根据用户提供的引用,我们可以总结如下: 引用[1]提到:重定向、转发或包含用于将请求转交给其他Servlet处理。 引用[2]:Header Location重定向机制,用于实现页面跳转URL管理。 引用[3]:Python网络请求重定向错误,涉及重定向的触发机制与目标。 引用[4]:请求重定向的特点:浏览器地址栏变化,两次请求,不共享Request域中的数据,不能访问WEB-INF下的资源,可以访问工程外的资源。 用户问题:请求转移(转发)与响应重定向的区别及各自应用场景。 注意:在Java Web开发中,请求转移通常指的是“请求转发”(forward),而响应重定向指的是“重定向”(redirect)。 下面我将从以下几个方面进行解析: 1. 定义与机制 2. 区别(包括浏览器行为、请求次数、数据共享、地址栏变化、应用场景等) 3. 应用场景 根据引用[4],重定向的特点已经明确,而转发(请求转移)的特点可以对比来看。 一、定义与机制 1. 请求转发(Forward): 是服务器内部的行为。当客户端发送请求到服务器服务器内部将请求转发给另一个资源(如ServletJSP)进行处理,然后将响应返回给客户端。客户端只发送了一次请求,并不知道服务器内部进行了转发。 2. 响应重定向(Redirect): 是客户端行为。服务器收到客户端的请求后,会返回一个状态码(如302)Location响应头,告诉浏览器去重新请求一个新的URL浏览器会自动根据Location的地址再次发送请求。因此,重定向过程中,客户端发出了两次请求。 二、区别 1. 浏览器地址栏变化: - 转发:浏览器地址栏不会变化,因为浏览器只发送了一次请求,且并不知道服务器内部转发了请求。 - 重定向:浏览器地址栏会变成新的URL,因为第二次请求是浏览器主动发起的。 2. 请求次数: - 转发:1次请求(服务器内部转发,浏览器只发一次) - 重定向:2次请求(第一次请求得到重定向响应,第二次请求新的URL) 3. 数据共享(Request域): - 转发:同一个请求,因此请求域(request scope)中的数据可以共享。在转发链中,可以通过request.setAttribute()设置的数据在转发的资源中获取。 - 重定向:两次独立的请求,因此第一个请求中的request对象在第二次请求中已经不存在,不能共享request域数据。如果需要在重定向后传递数据,可以使用session或者将参数附加在URL后面。 4. 资源访问权限: - 转发:可以访问WEB-INF目录下的资源(因为是在服务器内部跳转)。 - 重定向:不能访问WEB-INF目录下的资源(因为该目录受保护,不允许客户端直接访问)。 5. 目标资源范围: - 转发:只能跳转到同一应用内的资源。 - 重定向:可以跳转到任意URL,包括其他应用或外部网站(如引用[4]中跳转到百度)。 6. 性能: - 转发:效率较高,因为只有一个请求,在服务器内部完成跳转- 重定向:效率较低,因为需要两次请求,且需要经过客户端。 三、应用场景 1. 请求转发(Forward)的应用场景: - 当需要访问WEB-INF下的资源(如受保护的JSP页面)时,因为客户端不能直接访问WEB-INF,所以只能通过转发。 - 当需要共享同一个请求中的数据时(例如,在Servlet中处理业务逻辑,然后转发到JSP显示数据,即MVC模式中的视图渲染)。 - 需要保持同一个请求的上下文,比如在多个Servlet之间传递控制权(如使用RequestDispatcher进行转发)。 2. 响应重定向(Redirect)的应用场景: - 当需要跳转到其他站点(如引用[4]中跳转到百度)时。 - 当需要避免表单重复提交时(例如,用户提交表单后,服务器处理完数据,重定向到一个结果页面,这样即使刷新页面也不会重复提交)。 - 当需要改变浏览器地址栏的URL,使其与当前资源对应时(例如,用户登录后重定向到主页,这样地址栏就是主页的URL,而不是登录处理的URL)。 - 当需要让用户访问一个需要重新定向的资源(如URL缩短服务)时。 四、代码示例(Java Servlet) 1. 请求转发示例: ```java RequestDispatcher dispatcher = request.getRequestDispatcher("/targetServlet"); dispatcher.forward(request, response); ``` 2. 响应重定向示例: ```java response.sendRedirect("http://www.example.com"); ``` 五、总结 请求转发(请求转移)响应重定向是两种不同的请求处理机制。选择使用哪种方式取决于具体需求: - 如果需要保持请求数据,使用转发。 - 如果需要跳转外部资源或避免表单重复提交,使用重定向。 根据引用[1][2][3][4],我们了解到重定向在HTTP协议中是通过Location头实现的,而转发是服务器内部机制。同时,引用[3]提醒我们注意重定向可能带来的问题(如循环),而引用[4]则详细说明了重定向的特点。 最后,生成相关问题: 1.Java Web开发中,如何选择请求转发与重定向? 2. 重定向导致循环跳转的原因及解决方法? 3. 请求转发重定向在性能上有何差异?如何优化?</think>### 请求转移(请求转发)与响应重定向的区别及应用场景解析 #### 一、核心机制对比 | **特性** | **请求转移(请求转发)** | **响应重定向** | |-------------------|-------------------------------------------|----------------------------------------| | **HTTP动作** | 服务器内部跳转(单次请求) | 客户端二次请求(状态码 3xx) | | **浏览器地址栏** | 不变(显示原始URL) | 变化(显示新URL) | | **请求次数** | 1次 | 2次 | | **数据共享** | 共享同一Request域(可传递属性) | 不共享Request域(属性丢失) | | **资源访问范围** | 仅限当前应用内(不能访问外部资源) | 可访问任意资源(包括外部网站) | | **性能开销** | 较低(服务器内部处理) | 较高(客户端额外请求) | | **WEB-INF访问** | ✅ 可访问 | ❌ 不可访问 | #### 二、底层原理详解 1. **请求转移(Forward)** - **工作流程**: ```mermaid graph LR A[客户端] --> B[Servlet1] B -->|forward| C[Servlet2] C --> A[响应返回] ``` - 服务器内部通过`RequestDispatcher`完成跳转,客户端无感知 - 代码示例(Java): ```java // Servlet1中设置共享数据 request.setAttribute("key", "value"); // 执行转发 RequestDispatcher dispatcher = request.getRequestDispatcher("/target"); dispatcher.forward(request, response); ``` 2. **响应重定向(Redirect)** - **工作流程**: ```mermaid graph LR A[请求1] --> B[Servlet] B -->|302+Location| C[浏览器] C --> D[请求2] D --> E[新资源] ``` - 通过HTTP响应头控制(状态码 + Location头): ``` HTTP/1.1 302 Found Location: https://new-url.com ``` - 代码示例: ```java // 设置重定向(会丢失request数据) response.sendRedirect("https://baidu.com"); ``` #### 三、典型应用场景 **✅ 请求转移适用场景** 1. **MVC模式视图渲染** ```java // Controller处理业务后转发到JSP request.getRequestDispatcher("/result.jsp").forward(request, response); ``` 2. **访问受保护资源** 访问WEB-INF目录下的JSP(如安全配置页面) 3. **多组件协作处理** 多个Servlet链式处理请求(如:认证 → 授权 → 业务) **✅ 响应重定向适用场景** 1. **跨系统跳转** ```java // 跳转外部支付网关 response.sendRedirect("https://pay.thirdparty.com"); ``` 2. **防止表单重复提交** POST请求处理后重定向到结果页(PRG模式) 3. **登录后跳转** 用户认证成功后重定向到目标页面 4. **旧URL迁移** 将废弃页面重定向到新地址(HTTP 301) #### 四、关键差异总结 | **维度** | **请求转移** | **响应重定向** | |------------------|--------------------------------------|-----------------------------------| | **数据生命周期** | 同一请求周期 | 跨请求(需session/URL参数传递) | | **安全性** | 隐藏内部路径 | 暴露目标URL | | **SEO影响** | 原始URL权重保留 | 权重转移到新URL | | **错误处理** | 服务器直接返回500 | 客户端显示404/403等错误 | | **书签支持** | 保存原始URL(可能失效) | 保存最终有效URL | #### 五、选择决策树 ```mermaid graph TD A[需要跳转资源] --> B{是否需保持数据?} B -->|是| C[请求转移] B -->|否| D{是否跨域/外部?} D -->|是| E[响应重定向] D -->|否| F{是否需隐藏路径?} F -->|是| C F -->|否| E ``` > 示例场景:用户支付流程 > - 订单验证(请求转移)→ 支付计算(请求转移)→ 银行网关(重定向)→ 回调处理(请求转移)[^1][^2][^4]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值