该用户从未签到
|
重定向和转发有一个重要的不同:
0 z }3 W1 U8 ?+ Z6 \
4 x0 Z/ y, O# P4 Z7 x) }0 E) b& E; Y G
转发-----JSP容器将使用一个内部的方法来调用目标页面,新的页面继续处理同一个请求, 而浏览器将不会知道这个过程。! ?. r1 J) ~5 v1 [1 \
$ \1 ]* ?- Y1 m: f 重定向------是第一个页面通知浏览器发送一个新的页面请求。此时,浏览器中所显示的URL会变成新页面的URL, 而转发时 ,该URL会保持不变。" A9 f0 _( n* c* f; ?; O
7 P; g4 }9 |( |, p! @+ X 重定向的速度比转发慢,因为浏览器还得发出一个新的请求。同时,由于重定向方式产生了一个新的请求,所以经过一次重定向后,request内的对象将无法使用。
1 O) ]; r, n7 T$ {7 g1 o) q2 E/ n; l9 h8 P _# e, s1 L
U0 t2 h4 t* D0 [
$ M5 ]0 |, E9 |" m! v0 w, G, O t$ f, _ 怎么选择是重定向还是转发呢?
' v5 \5 e F. e1 \4 }4 o' H# K% {
: @0 A) M6 K; | 通常情况下转发更快,而且能保持request内的对象,所以他是第一选择。
; A* C. p7 ~5 W4 }! Q, q
) H$ p. [$ v/ n; N( I 但是由于在转发之后,浏览器中URL仍然指向开始页面,此时如果重载当前页面,开始页面将会被重新调用。
, f! p: X/ I1 D g
: ^' O9 X8 n# f; ]# j/ k 如果你不想看到这样的情况,则选择重定向
- i' `; K4 b* A c) Y( C: Z# n+ a; f$ B$ m/ C
转发和重定向的区别
2 B0 K6 ]# {' R& @7 o. a
9 H0 c& |, I8 M# Q3 {$ [4 J转发方式
5 `1 ]% ]) ? l s8 J6 Z: R! q6 H* t0 u x' M: u9 O
:request.getRequestDispatcher().forward(); 0 v: v! D! d2 B) u5 h
: y8 S4 R8 ~+ u3 y* w) C
重定向方式! E% V4 B8 X, R* K
! Q" ~2 [( q- r: G+ R9 b' P
:response.sendRedirect();
7 Q o( l% w, p! ]+ F% V2 J/ c
0 I; n% p8 M: j, b5 ?; b& U
" K: ~2 f* U9 ^+ ^) M& m, mHttpServletResponse.sendRedirect方法实现的请求重定向与RequestDispatcher.forward方法实现的请求转发的总结比较:3 {& L* Y9 q0 ~ O- e6 F1 K' C
2 I7 ]4 p; n4 O/ ]
y: O* n" m' u3 ~/ z3 K) X
+ z( _2 e4 b2 _4 A 1.RequestDispatcher.forward方法只能将请求转发给同一个WEB应用中的组件;而HttpServletResponse.sendRedirect 方法不仅可以重定向到当前应用程序中的其他资源,8 q# ]$ D" [6 u/ n$ `
" [4 H9 o& @" l n; B还可以重定向到同一个站点上的其他应用程序中的资源,甚至是使用绝对URL重定向到其他站点的资源。如果传递给HttpServletResponse.sendRedirect 方法的相对URL以“/”
6 i5 E# Z) n! U& O4 M# p9 a& a8 E7 K( }! t( ?3 l
开头,它是相对于整个WEB站点的根目录;如果创建RequestDispatcher对象时指定的相对URL以“/”开头,它是相对于当前WEB应用程序的根目录。8 V4 z8 Z6 x6 h% G" _1 D; T
* k+ e* H6 v: l# H' C3 Y9 F* [9 g
2.调用HttpServletResponse.sendRedirect方法重定向的访问过程结束后,浏览器地址栏中显示的URL会发生改变,由初始的URL地址变成重定向的目标URL;而调用RequestDispatcher.forward & @0 C3 a+ A2 {* T
- U; S3 i7 y7 T/ P, u
方法的请求转发过程结束后,浏览器地址栏保持初始的URL地址不变。
; C5 u/ l6 t1 f. \6 k
5 Z( d$ Q8 ]0 }& V( r3.HttpServletResponse.sendRedirect方法对浏览器的请求直接作出响应,响应的结果就是告诉浏览器去重新发出对另外一个URL的访问请求,这个过程好比有个绰号叫“浏览器”的人写信找张三借钱,; F& O2 o, S4 L2 W' v9 r- F
# ^+ { A, |0 X& f" [
张三回信说没有钱,让“浏览器“去找李四借,并将李四现在的通信地址告诉给了“浏览器”。于是,“浏览器”又按张三提供通信地址给李四写信借钱,李四收到信后就把钱汇给了“浏览器”。可见,“浏览器”
) @4 F/ K* c3 j8 ^7 }
; a8 G2 s, j( N# `1 _/ _2 a一共发出了两封信和收到了两次回复,“浏览器”也知道他借到的钱出自李四之手。RequestDispatcher.forward方法在服务器端内部将请求转发给另外一个资源,浏览器只知道发出了请求并得到了响应结果,
7 A* {( o; e( _
4 d* T$ g! y( |0 z" q( M& k并不知道在服务器程序内部发生了转发行为。这个过程好比绰号叫“浏览器”的人写信找张三借钱,张三没有钱,于是张三找李四借了一些钱,甚至还可以加上自己的一些钱,然后再将这些钱汇给了“浏览器”- ^" C2 A2 r. U) i0 y
! e8 v1 }, @6 |7 b: q。可见,“浏览器”只发出了一封信和收到了一次回复,他只知道从张三那里借到了钱,并不知道有一部分钱出自李四之手。7 p! _4 F- D7 @
3 ?, @* N H& [' G9 K9 s
" ~( i- _2 X! M8 u3 Y4.RequestDispatcher.forward方法的调用者与被调用者之间共享相同的request对象和response对象,它们属于同一个访问请求和响应过程;而HttpServletResponse.sendRedirect方法调用者与被调用者使用各自的
+ D% Q, r7 [( ~4 J. W( a4 H8 q, Q3 {. f$ Z3 V
request对象和response对象,它们属于两个独立的访问请求和响应过程。对于同一个WEB应用程序的内部资源之间的跳转,特别是跳转之前要对请求进行一些前期预处理,并要使用HttpServletRequest.setAttribute方法传递预处理 O0 n8 \! y2 e5 t8 p7 g X* [; J
: ~2 y0 ]6 ^ }% N结果,那就应该使用RequestDispatcher.forward方法。不同WEB应用程序之间的重定向,特别是要重定向到另外一个WEB站点上的资源的情况,都应该使用HttpServletResponse.sendRedirect方法。
' w2 |2 z( u- z5 d |; @, x
5 j+ Z& K9 M5 e( s) Z2 [3 o5 L9 W$ d4 Y3 r% { L
5.无论是RequestDispatcher.forward方法,还是HttpServletResponse.sendRedirect方法,在调用它们之前,都不能有内容已经被实际输出到了客户端。如果缓冲区中已经有# x% o+ ]: f7 ]( \ o
5 u0 `$ u$ G8 ?) r- r3 T' J
了一些内容,这些内容将被从缓冲区中清除。
3 b2 s* [1 ]+ ?8 e* G) j 不要仅仅为了把变量传到下一个页面而使用session作用域,那会无故增大变量的作用域,6 X' S9 o% y0 H# V
9 R+ D& J: ]! s4 B/ b
转发也许可以帮助你解决这个问题。( t: C# f# |" P, X4 u- n
0 [+ @) `8 T" F重定向:8 W$ L7 t, `) B; |$ N; d
以前的request中存放的变量全部失效,并进入一个新的request作用域。
. ~) v1 r4 D8 v" n/ N. }7 F转发:
0 @( v5 S' x( V7 \+ ]! i- ] [ E7 Z: ~3 v, W' q5 ~2 f
以前的request中存放的变量不会失效,就像把两个页面拼到了一起。
7 R; M( H5 @& g; f! Y" i! o
" }" c a7 l9 t$ f8 Y& L! @
3 S; ]# m8 K* W6 O/ x* O; F g, f8 {5 N$ E' t# x, X. P: x6 K
|
|