2024年4月12日发(作者:)

请求转发(Forward)和重定向(Redirect)之间区别与联系

一个比喻:

小张向小李发送一次请求,想让他完成某项工作,当小李接受到请求时,发现自己完成不了,又请求小王帮忙,小王接收到

小李请求之后最终完成了该项工作,并把最后的结果交给了小张。这个过程就是请求转发,在此期间,小张只发送了一次请

求,他只知道把任务交给了小李,至于小李是如何完成的,小张并不知道,他只等待最终的结果。

重定向则不同,首先小张向小李发送请求,想让他完成某项工作,当小李接收到这个请求时,发现自己完成不了,他立即通

知小张,并推荐小王可以完成任务,于是小张又联系小王,最终小王完成了该项任务。

区别:

1、浏览器地址栏显示不同(表面区别)

无论进行多少次请求,如果使用请求转发来实现,浏览器地址栏中只显示第一次发送请求的地址;如果使用重定向来实现,

浏览器地址栏显示的是每次请求的新地址。这只是表面上看到的不同地方。

2、组件之间可否共享信息不同(本质区别)

从本质上讲,请求转发时,从发送第一次到最后一次请求的过程中,WEB容器只创建一次request和response对象,请求

之间始终共享这两个对象,所以每个请求可以访问他之前请求中的参数和属性的值;而重定向时,浏览器每发送一次请求,

WEB容器都会重新创建新的request和response对象,所以请求之间不能共享信息,即不能在请求中访问到他之前请求中

的参数和属性的值。

3、实现方式不同

请求转发的实现步骤:

说明将要转发的资源;

获取请求转发的对象;

调用请求转发对象中forward()方法

Java代码

1.

2.

3.

String forward = "/";

RequestDispatcher rd = uestDispatcher(forward);

d(request, reponse);

重定向的实现步骤:

说明将要重定向的资源;

调用response对象中sendRedirect方法

Java代码

1.

2.

String resource = extPath() + "/";

direct(resource);

4、知情人不同

请求转发时转发的过程只有WEB服务器知道,而浏览器不知道进行了多少次转发,以及都转发给哪些组件(servlet,JSP),

它只是在等待WEB服务器最终的结果。而重定向时,每发送一次请求,WEB服务器都会通知浏览器的,所以重定向了几

次请求以及每次都向哪个组件发送的请求,浏览器很清楚,当让WEB服务器也很明白。

相同点:

两者都可以进行多次请求的转发。

请求转发与重定向的区别

先是看上去不同,他们的调用分别如下:

uestDispatcher("").forward(request, response);//转发到

direct("");//重定向到

在jsp页面中你也会看到通过下面的方式实现转发:

我在初学jsp的时候,对这两个概念非常模糊,看别人的例子的时候,也是一头雾水,不知道什么时候该

用哪个。希望下面的解说能对你有所帮助。

提到转发和重定向就不得不提到request作用域。很多初学者都知道当我们提交一个表单时,就创建了

一个新的请求。实际上,当我们点击一个链接时,也创建了一个新的请求。那么一个请求的作用于到底有

多大呢?

例如:在页面中有一个链接

这是指向b的一个链接,而且还带了一个参数

当我们点击这个连接的时候,就产生了一个请求,为了明确起见,我们把它叫做requestA->B。现在,

在页面中我们就可以从这个请求中获取信息了。在中你可以写入

n(ameter("id"))进行测试。

下面更复杂一点,我们在页面中增加下面的语句:

ribute("name","funcreal");

n(riblute("name"));//成功显示了name变量的值。

现在在中再增加一个链接:

这是指向c的一个链接,而且还带了一个参数

当我们点击这个连接的时候,将产生一个新的请求,这时requestA-B也就安息了,新的请求叫做

requestB-C。同样的道理,在中,我们可以访问到的变量只有age,因为id,name这两个变

量都属于requestA-B,此时他已经不存在了。下面是源代码:

<%@ page contentType="text/html; charset=GBK" %>

指向,而且还带了一个参数id=1。requestA-B现在诞生了

<%@ page contentType="text/html; charset=GBK" %>

<%

n("id=" + ameter("id"));

ribute("name","Func Real");

n("name=" + ribute("name"));

%>

requestA-B已经结束了。指向,而且还带了一个参数age=23

<%@ page contentType="text/html; charset=GBK" %>

<%

n("id=" + ameter("id"));

n("name=" + ribute("name"));

n("age=" + ameter("age"));

%>

那么转发又是怎么回事呢?现在增加一个页面叫做,并且在中前面增加一句

<%@ page contentType="text/html; charset=GBK" %>

requestB-C的魔爪已经伸到了页面

<%

n("age=" + ameter("age"));

%>

运行程序,你会发现c页面中的内容没有显示出来,因为forward是自动执行的,地址栏中虽然是

但实际上,但浏览器中显示的已经是的内容了,而且看到了从传过来的参数。你可以简单

得这样理解:转发,就是延长了requestB-C的作用域,,这一句

话实际上是把和粘到了一起,他们就像是在一个页面中。

如果你用过struts,那么你就知道为什么在Action中,最后一句几乎总是

rward("xxx");了。因为我们在这个Action中设置的请求作用域的变量都将会在下

一个页面(也许是另一个Action)中用到,所以要用转发。

总结:

用重定向和转发不是一个习惯问题。而是什么情况下必须用什么的问题。

不要仅仅为了把变量传到下一个页面而使用session作用域,那会无故增大变量的作用域,转发也许可

以帮助你解决这个问题。

重定向:以前的request中存放的变量全部失效,并进入一个新的request作用域。

转发:以前的request中存放的变量不会失效,就像把两个页面拼到了一起。

有关JSP/Servlet的重定向技术综述如下[补充]

d()转发

是在服务器端起作用,当使用forward()时,Servlet engine传递HTTP请求从当前的Servletor

JSP到另外一个Servlet,JSP 或普通HTML文件,也即你的form提交至,在用到了

forward()重定向至,此时 form提交的所有信息在都可以获得,参数自动传递.

但forward()无法重定向至有frame的jsp文件,可以重定向至有frame的html文件,同时

forward()无法在后面带参数传递,比如servlet?name=frank,这样不行,可以程序内通过

ribute("name",name) 来传至下一个页面.

重定向后浏览器地址栏URL不变.

例:在servlet中进行重定向

public void doPost(HttpServletRequest request,HttpServletResponse response)

throws ServletException,IOException

{

tentType("text/html; charset=gb2312");

ServletContext sc = getServletContext();

RequestDispatcher rd = null;

rd = uestDispatcher("/"); //定向的页面

d(request, response);

}

通常在servlet中使用,不在jsp中使用。

direct()

是在用户的浏览器端工作,sendRedirect()可以带参数传递,比如servlet?name=frank传至下

个页面,同时它可以重定向至不同的主机上,sendRedirect()可以重定向有frame.的jsp文件.

重定向后在浏览器地址栏上会出现重定向页面的URL

例:在servlet中重定向

public void doPost(HttpServletRequest request,HttpServletResponse response)

throws ServletException,IOException

{

tentType("text/html; charset=gb2312");

direct("/");

}

由于response是jsp页面中的隐含对象,故在jsp页面中可以用direct()直接

实现重定位。

注意:

(1).使用direct时,前面不能有HTML输出。

这并不是绝对的,不能有HTML输出其实是指不能有HTML被送到了浏览器。事实上现在的server都有

cache机制,一般在8K(我是说 JSP SERVER),这就意味着,除非你关闭了cache,或者你使用了

()强制刷新,那么在使用sendRedirect之前, 有少量的HTML输出也是允许的。

(2).direct之后,应该紧跟一句return;

我们已经知道direct是通过浏览器来做转向的,所以只有在页面处理完成后,才会

有实际的动作。既然你已经要做转向了,那么后的输出还有什么意义呢?而且有可能会因为后面的输出导

致转向失败。

比较:

(1).Request d()是容器中控制权的转向,在客户端浏览器地址栏中不会显示出

转向后的地址;

(2).direct()则是完全的跳转,浏览器将会得到跳转的地址,并重新发送请求链接。

这样,从浏览器的地址栏中可以看到跳转后的链接地址。

前者更加高效,在前者可以满足需要时,尽量使用d()方法.

注:在有些情况下,比如,需要跳转到一个其它服务器上的资源,则必须使用

quest()方法。

3.

它的底层部分是由RequestDispatcher来实现的,因此它带有d()方

法的印记。

如果在之前有很多输出,前面的输出已使缓冲区满,将自动输出到客户端,那么该语句将

不起作用,这一点应该特别注意。

另外要注意:它不能改变浏览器地址,刷新的话会导致重复提交

4.修改HTTP header的Location属性来重定向

通过设置直接修改地址栏来实现页面的重定向。

jsp文件代码如下:

<%

tus(_MOVED_PERMANENTLY);

String newLocn = "/newpath/";

der("Location",newLocn);

%>

中实现在某页面停留若干秒后,自动重定向到另一页面

在html文件中,下面的代码:

它的含义:在5分钟之后正在浏览的页面将会自动变为这一页。代码中300为刷新

的延迟时间,以秒为单位。为你想转向的目标页,若为本页则为自动刷新本页。

由上可知,可以通过setHeader来实现某页面停留若干秒后,自动重定向到另一页面。

关键代码:

String content=stayTime+";URL="+URL;

der("REFRESH",content);