转发和重定向的比较

       提起转发和重定向,我们脑海中就会浮现 request作用域;大家都知道当我们提交一个表单时,就创建了一个新

的请求。而实际上,当我们点击某个链接时,也会创建一个新的请求。那么个请求的生命周期到底有多长呢,作用域会有多大?一起来看!

✎   了解

      现有一个页面  a.jsp,该页面中有一个链接:

<span style="font-size:18px;"><a href="b.jsp?id=1">这是指向b的一个链接,而且还带了一个参数</a></span>

     

      当我们点击这个链接时,就会产生一个请求,我们将它称为requestA->B 。这个时候,我们就可以使用这个请求在b.jsp中获取数据信息 id 的信息了:

<span style="font-size:18px;">system.out.println(request.getParameter("id"))</span>

    现在我们将难度升级,在b.jsp中添加如下语句:

<span style="font-size:18px;">request.setAttribute("name","funcreal");

system.out.println(request.getAttriblute("name"));//成功显示了name变量的值</span>
       并且在b.jsp中添加链接:

<span style="font-size:18px;"><a href="c.jsp?age=23">这是指向c的一个链接,而且还带了一个参数</a></span>

      当我们点击b.jsp的链接时,又会创建一个新的请求,而这个时候requestA->B 也就可以消匿了,所以我们将新的请求成为requestB->C ;那么我们可以从requestB->C中获取到age的数据信息,而id,name的属性我们就都无法在c.jsp中获取了,因为id和name都是requestA->B中的信息,而该请求已经消失了,所以无法获取这些信息;

     那么转发又是几个意思呢??

     现在增加了一个页面 d.jsp ,并且在c.jsp的页面顶端加入一句:

<span style="font-size:18px;"><jsp:forward page="d.jsp"/></span><pre name="code" class="html"><span style="font-size:18px;"><%@ page contentType="text/html; charset=GBK" %>
<html>
<body bgcolor="#ffffff">
<%
out.println("id=" + request.getParameter("id"));
out.println("name=" + request.getAttribute("name"));
out.println("age=" + request.getParameter("age"));
%>
</body>
</html></span>

 
     d.jsp的页面如下: 

<span style="font-size:18px;"><%@ page contentType="text/html; charset=GBK" %>
<html>
<body bgcolor="#ffffff">
requestB-C的魔爪已经伸到了d.jsp页面
<%
out.println("age=" + request.getParameter("age"));
%>
</body>
</html></span>

      运行程序,我们可以发现,c.jsp的内容并没有显示出来,因为forward是自动执行的,地址中虽然是c.jsp,但实际上浏览器中显示的已经是d.jsp的内容,而且可以看到从b.jsp中传过来的参数;所以我们可以这样理解:转发,延长了requestB->C的作用域,而c.jsp顶端添加的那句代码:<jsp:forwardpage="d.jsp"/>,则是将c.jsp和d.jsp粘连到了一起,它们就相当于处于同一个页面中。比如在struts中的Action,我们经常会用到一句话:mapping.findForward("###****"),因为我们在Action设置中的请求作用域的变量都会被应用到下一个页面(或者Action)中,所以使用的是转发;

  ✎   比较  RequestDispatcher.forward  和 HttpServletResponse.sendRedirect:

(1)forward 方法只能将请求转发给同一个WEB应用中的组件;而sendRedirect 方法不仅可以重定向到当前应用程序中的其他资源,还可以重定向到同一个站点上的其他应用程序中的资源,甚至是使用绝对URL重定向到其他站点的资源。

       如果 传递给sendRedirect 方法的相对URL以“/”开头,它是相对于整个WEB站点的根目录;如果创建RequestDispatcher 对象时指定的相对URL以“/”开头,它是相对于当前WEB应用程序的根目录。


(2)调用sendRedirect 方法重定向的访问过程结束后,浏览器地址栏中显示的URL会发生改变,由初始的URL地址变成重定向的目标URL;而调用 forward 方法的请求转发过程结束后,浏览器地址栏保持初始的URL地址不变。


(3)sendRedirect 方法对浏览器的请求直接作出响应,响应的结果就是告诉浏览器去重新发出对另外一个URL的访问请求。

     举个例子重定向过程好比有个绰号叫“浏览器”的人写信找张三借钱,张三回信说没有钱,让“浏览器”去找李四借, 并将李四现在的通信地址告诉给了“浏览器 ”。于是,“浏览器”又按张三提供通信地址给李四写信借钱,李四收到信后就把钱汇给了“浏览器”。可见,“浏览器”一共发出了两封信和收到了两次回复,“ 浏览器”也知道他借到的钱出自李四之手。

     forward 方法在服务器端内部将请求转发给另外一个资源,浏览器只知道发出了请求并得到了响应结果,并不知道在服务器程序内部发生了转发行为。这个过程好比绰号叫“ 浏览器”的人写信找张三借钱,张三没有钱,于是张三找李四借了一些钱,甚至还可以加上自己的一些钱,然后再将这些钱汇给了“浏览器”。可见,“浏览器”只 发出了一封信和收到了一次回复,他只知道从张三那里借到了钱,并不知道有一部分钱出自李四之手。


(4)forward 方法的调用者与被调用者之间共享相同的request 对象和response 对象,它们属于同一个访问请求和响应过程;而sendRedirect 方法调用者与被调用者使用各自的request 对象和response 对象,它们属于两个独立的访问请求和响应过程。

     对于同一个WEB应用程序的内部资源之间的跳转,特别是跳转之前要对请求进行一些前期预处理,并使用 HttpServletRequest.setAttribute 方法传递预处理结果,那就应该使用 forward 方法。

     不同WEB应用程序之间的重定向,特别是要重定向到另外一个WEB站点上的资源的情况,都应该 sendRedirect方法。


(5)无论是forward 方法,还是sendRedirect 方法,在调用它们之前,都不能有内容已经被实际输出到了客户端。如果缓冲区中已经有了一些内容,这些内容将被从缓冲区中清除。

✎  总结:

   当使用转发时,JSP容器将使用一个内部的方法来调用目标页面,新的页面继续处理同一个请求,而浏览器将不会知道这个过程。

    与之相反,重定向方式的含义是第一个页面通知浏览器发送一个新的页面请求。因为,当你使用重定向时,浏览器中所显示的URL会变成新页面的URL, 而当使用转发时,该URL会保持不变。由于重定向需要浏览创建一个新的请求,所以速度要比转发慢。同时,由于重定向方式产生了一个新的请求,所以经过一次重 定向后,request内的对象将无法使用。 

    怎么选择是重定向还是转发呢?通常情况下转发更快,而且能保持request内的对象,所以它是第一选择。但是由于在转发之后,浏览器中URL仍然指向开始页面,此时如果重载当前页面,开始页面将会被重新调用。


     


      

    

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 21
    评论
JavaWeb中的请求转发和请求重定向是两种不同的操作。 请求转发是服务器行为,通过调用`request.getRequestDispatcher(URL地址).forward(request,response)`方法进行转发转发后,请求对象会保存,地址栏的URL地址不会变。 请求重定向是客户端行为,通过调用`response.sendRedirect(URL地址)`方法进行重定向重定向从本质上讲等同于两次请求,前一次的请求对象不会保存,地址栏的URL地址会变。 在路径问题上,如果URL地址使用相对路径,转发重定向没有区别。但如果URL地址使用绝对路径,有以下注意事项: - 对于请求转发,绝对路径的写法是以"/"开头,指的是当前Web程序的根目录。例如,`/login.jsp`或者`/servlet/LoginServlet`。 - 对于请求重定向,绝对路径的写法是完整的URL地址,包括协议、域名和资源路径。例如,`http://www.example.com/login.jsp`或者`http://www.example.com/servlet/LoginServlet`。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Javaweb 请求的转发重定向](https://blog.csdn.net/qq28129019/article/details/118990213)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [javaWEB请求转发重定向](https://blog.csdn.net/JasomMNn/article/details/114102491)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值