轉(zhuǎn)載:http://www.cnblogs.com/shenliang123/archive/2011/10/27/2226892.html
response.sendredirect("http://www.foo.com/path/error.html");
重定向和轉(zhuǎn)發(fā)有一個重要的不同:當(dāng)使用轉(zhuǎn)發(fā)時覆糟,JSP容器將使用一個內(nèi)部的方法來調(diào)用目標(biāo)頁面,新的頁面繼續(xù)處理同一個請求滩字,而瀏覽器將不會知道這個過程麦箍。 與之相反,重定向方式的含義是第一個頁面通知瀏覽器發(fā)送一個新的頁面請求挟裂。因為,當(dāng)你使用重定向時栗竖,瀏覽器中所顯示的URL會變成新頁面的URL, 而當(dāng)使用轉(zhuǎn)發(fā)時渠啤,該URL會保持不變。重定向的速度比轉(zhuǎn)發(fā)慢份名,因為瀏覽器還得發(fā)出一個新的請求架专。同時,由于重定向方式產(chǎn)生了一個新的請求想邦,所以經(jīng)過一次重 定向后委刘,request內(nèi)的對象將無法使用鹰椒。
怎么選擇是重定向還是轉(zhuǎn)發(fā)呢呕童?通常情況下轉(zhuǎn)發(fā)更快,而且能保持request內(nèi)的對象夺饲,所以他是第一選擇往声。但是由于在轉(zhuǎn)發(fā)之后,瀏覽器中URL仍然指向開始頁面浩销,此時如果重載當(dāng)前頁面慢洋,開始頁面將會被重新調(diào)用。如果你不想看到這樣的情況普筹,則選擇轉(zhuǎn)發(fā)。
轉(zhuǎn)發(fā)和重定向的區(qū)別
不要僅僅為了把變量傳到下一個頁面而使用session作用域肩刃,那會無故增大變量的作用域杏头,轉(zhuǎn)發(fā)也許可以幫助你解決這個問題沸呐。
重定向:以前的request中存放的變量全部失效,并進(jìn)入一個新的request作用域寓娩。
轉(zhuǎn)發(fā):以前的request中存放的變量不會失效呼渣,就像把兩個頁面拼到了一起。
正文開始:
先是看上去不同焊夸,他們的調(diào)用分別如下:
request.getRequestDispatcher("apage.jsp").forward(request, response);//轉(zhuǎn)發(fā)到apage.jsp
response.sendRedirect("apage.jsp");//重定向到apage.jsp
在jsp頁面中你也會看到通過下面的方式實(shí)現(xiàn)轉(zhuǎn)發(fā):
我在初學(xué)jsp的時候蓝角,對這兩個概念非常模糊饭冬,看別人的例子的時候揪阶,也是一頭霧水,不知道什么時候該用哪個炊苫。希望下面的解說能對你有所幫助冰沙。
提 到轉(zhuǎn)發(fā)和重定向就不得不提到request作用域。很多初學(xué)者都知道當(dāng)我們提交一個表單時蒋畜,就創(chuàng)建了一個新的請求撞叽。實(shí)際上,當(dāng)我們點(diǎn)擊一個鏈接時科展,也創(chuàng)建 了一個新的請求糠雨。那么一個請求的作用于到底有多大呢?例如:在頁面a.jsp中有一個鏈接這是指向b的一個鏈接琅攘,而且還帶了一個參數(shù)松邪。當(dāng)我們點(diǎn)擊這個連接的時候,就產(chǎn)生了一個請 求剧辐,為了明確起見邮府,我們把它叫做requestA->B。現(xiàn)在褂傀,在b.jsp頁面中我們就可以從這個請求中獲取信息了紊服。在b.jsp中你可以寫入 out.println(request.getParameter("id"))進(jìn)行測試胸竞。下面更復(fù)雜一點(diǎn)参萄,我們在b.jsp頁面中增加下面的語句:
request.setAttribute("name","funcreal");
out.println(request.getAttriblute("name"));//成功顯示了name變量的值。
現(xiàn) 在在b.jsp中再增加一個鏈接:這是指向c的一個鏈接校赤,而且還帶了一個參數(shù),當(dāng)我們點(diǎn)擊這個連接的時候筒溃,將產(chǎn)生一個 新的請求,這時requestA-B也就安息了浑测,新的請求叫做requestB-C歪玲。同樣的道理,在c.jsp中岖圈,我們可以訪問到的變量只有age钙皮,因為 id,name這兩個變量都屬于requestA-B导匣,此時他已經(jīng)不存在了慌烧。下面是源代碼:
a.jsp
<%@ page contentType="text/html; charset=GBK" %>
指向b.jsp,而且還帶了一個參數(shù)id=1。requestA-B現(xiàn)在誕生了
b.jsp
<%@ page contentType="text/html; charset=GBK" %>
<%
out.println("id=" + request.getParameter("id"));
request.setAttribute("name","Func Real");
out.println("name=" + request.getAttribute("name"));
%>
requestA-B已經(jīng)結(jié)束了进每。指向c.jsp田晚,而且還帶了一個參數(shù)age=23
c.jsp
<%@ page contentType="text/html; charset=GBK" %>
<%
out.println("id=" + request.getParameter("id"));
out.println("name=" + request.getAttribute("name"));
out.println("age=" + request.getParameter("age"));
%>
那么轉(zhuǎn)發(fā)又是怎么回事呢?現(xiàn)在增加一個頁面叫做d.jsp芹壕,并且在c.jsp中前面增加一句
d.jsp
<%@ page contentType="text/html; charset=GBK" %>
requestB-C的魔爪已經(jīng)伸到了d.jsp頁面
<%
out.println("age=" + request.getParameter("age"));
%>
運(yùn) 行程序,你會發(fā)現(xiàn)c頁面中的內(nèi)容沒有顯示出來通孽,因為forward是自動執(zhí)行的睁壁,地址欄中雖然是c.jsp但實(shí)際上,但瀏覽器中顯示的已經(jīng)是d.jsp的 內(nèi)容了潘明,而且看到了從b.jsp傳過來的參數(shù)钳降。你可以簡單得這樣理解:轉(zhuǎn)發(fā),就是延長了requestB-C的作用 域遂填,城菊,這一句話實(shí)際上是把c.jsp和d.jsp粘到了一起,他們就像是在一個頁面 中凌唬。
如果你用過struts客税,那么你就知道為什么在Action中,最后一句幾乎總是mapping.findForward("xxx");了更耻。因為我們在這個Action中設(shè)置的請求作用域的變量都將會在下一個頁面(也許是另一個Action)中用到,所以要用轉(zhuǎn)發(fā)食侮。
下面是HttpServletResponse.sendRedirect方法實(shí)現(xiàn)的請求重定向與RequestDispatcher.forward方法實(shí)現(xiàn)的請求轉(zhuǎn)發(fā)的總結(jié)比較:
(1)RequestDispatcher.forward 方法只能將請求轉(zhuǎn)發(fā)給同一個WEB應(yīng)用中的組件目胡;而HttpServletResponse.sendRedirect 方法不僅可以重定向到當(dāng)前應(yīng)用程序中的其他資源誉己,還可以重定向到同一個站點(diǎn)上的其他應(yīng)用程序中的資源,甚至是使用絕對URL重定向到其他站點(diǎn)的資源噪猾。如果 傳遞給HttpServletResponse.sendRedirect 方法的相對URL以“/”開頭,它是相對于整個WEB站點(diǎn)的根目錄袱蜡;如果創(chuàng)建RequestDispatcher 對象時指定的相對URL以“/”開頭戒劫,它是相對于當(dāng)前WEB應(yīng)用程序的根目錄。
(2)調(diào)用HttpServletResponse.sendRedirect 方法重定向的訪問過程結(jié)束后迅细,瀏覽器地址欄中顯示的URL會發(fā)生改變茵典,由初始的URL地址變成重定向的目標(biāo)URL;而調(diào)用 RequestDispatcher.forward 方法的請求轉(zhuǎn)發(fā)過程結(jié)束后统阿,瀏覽器地址欄保持初始的URL地址不變扶平。
(3)HttpServletResponse.sendRedirect 方法對瀏覽器的請求直接作出響應(yīng),響應(yīng)的結(jié)果就是告訴瀏覽器去重新發(fā)出對另外一個URL的訪問請求结澄。
舉個例子:重定向過程好比有個綽號叫“瀏覽器”的人寫信找張三借錢麻献,張三回信說沒有錢,讓“瀏覽器”去找李四借勉吻,并將李四現(xiàn)在的通信地址告訴給了“瀏覽器 ”齿桃。于是,“瀏覽器”又按張三提供通信地址給李四寫信借錢短纵,李四收到信后就把錢匯給了“瀏覽器”踩娘。可見养渴,“瀏覽器”一共發(fā)出了兩封信和收到了兩次回復(fù)理卑,“ 瀏覽器”也知道他借到的錢出自李四之手。 RequestDispatcher.forward 方法在服務(wù)器端內(nèi)部將請求轉(zhuǎn)發(fā)給另外一個資源藐唠,瀏覽器只知道發(fā)出了請求并得到了響應(yīng)結(jié)果宇立,并不知道在服務(wù)器程序內(nèi)部發(fā)生了轉(zhuǎn)發(fā)行為。這個過程好比綽號叫“ 瀏覽器”的人寫信找張三借錢妈嘹,張三沒有錢润脸,于是張三找李四借了一些錢,甚至還可以加上自己的一些錢毙驯,然后再將這些錢匯給了“瀏覽器”爆价。可見允坚,“瀏覽器”只 發(fā)出了一封信和收到了一次回復(fù)稠项,他只知道從張三那里借到了錢,并不知道有一部分錢出自李四之手展运。
(4)RequestDispatcher.forward 方法的調(diào)用者與被調(diào)用者之間共享相同的request 對象和response 對象拗胜,它們屬于同一個訪問請求和響應(yīng)過程;而HttpServletResponse.sendRedirect 方法調(diào)用者與被調(diào)用者使用各自的request 對象和response 對象锈遥,它們屬于兩個獨(dú)立的訪問請求和響應(yīng)過程。
對于同一個WEB應(yīng)用程序的內(nèi)部資源之間的跳轉(zhuǎn)丽惶,特別是跳轉(zhuǎn)之前要對請求進(jìn)行一些前期預(yù)處理爬立,并要使用 HttpServletRequest.setAttribute 方法傳遞預(yù)處理結(jié)果,那就應(yīng)該使用RequestDispatcher.forward 方法抡秆。
不同WEB應(yīng)用程序之間的重定向吟策,特別是要重定向到另外一個WEB站點(diǎn)上的資源的情況,都應(yīng)該使HttpServletResponse.sendRedirect 方法乍桂。
(5)無論是RequestDispatcher.forward 方法效床,還是HttpServletResponse.sendRedirect 方法剩檀,在調(diào)用它們之前,都不能有內(nèi)容已經(jīng)被實(shí)際輸出到了客戶端沪猴。如果緩沖區(qū)中已經(jīng)有了一些內(nèi)容运嗜,這些內(nèi)容將被從緩沖區(qū)中清除。