jsp內(nèi)置對(duì)象 ?轉(zhuǎn)發(fā)與重定向的比較
? ? ? ? 重定向和轉(zhuǎn)發(fā)有一個(gè)重要的不同:當(dāng)使用轉(zhuǎn)發(fā)時(shí)凌彬,JSP容器將使用一個(gè)內(nèi)部的方法來(lái)調(diào)用目標(biāo)頁(yè)面逞力,新的頁(yè)面繼續(xù)處理同一個(gè)請(qǐng)求啦吧,而瀏覽器將不會(huì)知道這個(gè)過(guò)程绿店。 與之相反妙痹,重定向方式的含義是第一個(gè)頁(yè)面通知瀏覽器發(fā)送一個(gè)新的頁(yè)面請(qǐng)求铸史。因?yàn)椋?dāng)你使用重定向時(shí)怯伊,瀏覽器中所顯示的URL會(huì)變成新頁(yè)面的URL, 而當(dāng)使用轉(zhuǎn)發(fā)時(shí)琳轿,該URL會(huì)保持不變。重定向的速度比轉(zhuǎn)發(fā)慢耿芹,因?yàn)闉g覽器還得發(fā)出一個(gè)新的請(qǐng)求崭篡。同時(shí),由于重定向方式產(chǎn)生了一個(gè)新的請(qǐng)求吧秕,所以經(jīng)過(guò)一次重 定向后琉闪,request內(nèi)的對(duì)象將無(wú)法使用。?
怎么選擇是重定向還是轉(zhuǎn)發(fā)呢砸彬?通常情況下轉(zhuǎn)發(fā)更快颠毙,而且能保持request內(nèi)的對(duì)象斯入,所以它是第一選擇。但是由于在轉(zhuǎn)發(fā)之后蛀蜜,瀏覽器中URL仍然指向開(kāi)始頁(yè)面刻两,此時(shí)如果重載當(dāng)前頁(yè)面,開(kāi)始頁(yè)面將會(huì)被重新調(diào)用涵防。如果你不想看到這樣的情況闹伪,則選擇重定向沪铭。?
轉(zhuǎn)發(fā)和重定向的區(qū)別 :
1壮池、重定向時(shí)瀏覽器上的網(wǎng)址改變,轉(zhuǎn)發(fā)是瀏覽器上的網(wǎng)址不變杀怠;
2椰憋、重定向?qū)嶋H上產(chǎn)生了兩次請(qǐng)求,轉(zhuǎn)發(fā)只有一次請(qǐng)求赔退;
重定向:
發(fā)送請(qǐng)求 -->服務(wù)器運(yùn)行-->響應(yīng)請(qǐng)求橙依,返回給瀏覽器一個(gè)新的地址與響應(yīng)碼-->瀏覽器根據(jù)響應(yīng)碼,判定該響應(yīng)為重定向硕旗,自動(dòng)發(fā)送一個(gè)新的請(qǐng)求給服務(wù)器窗骑,請(qǐng)求地址為之前返回的地址-->服務(wù)器運(yùn)行-->響應(yīng)請(qǐng)求給瀏覽器;
轉(zhuǎn)發(fā):
發(fā)送請(qǐng)求 -->服務(wù)器運(yùn)行-->進(jìn)行請(qǐng)求的重新設(shè)置漆枚,例如通過(guò)request.setAttribute(name,value)-->根據(jù)轉(zhuǎn)發(fā)的地址创译,獲取該地址的網(wǎng)頁(yè)-->響應(yīng)請(qǐng)求給瀏覽器
3、重定向時(shí)的網(wǎng)址可以是任何網(wǎng)址墙基,轉(zhuǎn)發(fā)的網(wǎng)址必須是本站點(diǎn)的網(wǎng)址软族。
重定向:以前的request中存放的變量全部失效,并進(jìn)入一個(gè)新的request作用域残制。
轉(zhuǎn)發(fā):以前的request中存放的變量不會(huì)失效立砸,就像把兩個(gè)頁(yè)面拼到了一起。
詳細(xì)介紹:
首先是看上去不同初茶,他們的調(diào)用分別如下:
1颗祝、request.getRequestDispatcher("apage.jsp").forward(request, response);//轉(zhuǎn)發(fā)到apage.jsp
? ?2、response.sendRedirect("apage.jsp");//重定向到apage.jsp
在jsp頁(yè)面中也允許通過(guò)下面的方式實(shí)現(xiàn)轉(zhuǎn)發(fā):
<jsp:forward page="apage.jsp" />
重定向:以前的request中存放的變量全部失效恼布,并進(jìn)入一個(gè)新的request作用域吐葵。?
轉(zhuǎn)發(fā):以前的request中存放的變量不會(huì)失效,就像把兩個(gè)頁(yè)面拼到了一起桥氏。
提 到轉(zhuǎn)發(fā)和重定向就不得不提到request作用域温峭。很多初學(xué)者都知道當(dāng)我們提交一個(gè)表單時(shí),就創(chuàng)建了一個(gè)新的請(qǐng)求字支。實(shí)際上凤藏,當(dāng)我們點(diǎn)擊一個(gè)鏈接時(shí)奸忽,也創(chuàng)建 了一個(gè)新的請(qǐng)求。那么一個(gè)請(qǐng)求的作用于到底有多大呢揖庄?例如:在頁(yè)面a.jsp中有一個(gè)鏈接<a href="b.jsp?id=1"></a>這是指向b的一個(gè)鏈接栗菜,而且還帶了一個(gè)參數(shù)</a>。當(dāng)我們點(diǎn)擊這個(gè)鏈接的時(shí)候蹄梢,就產(chǎn)生了一個(gè)請(qǐng) 求疙筹,為了明確起見(jiàn),我們把它叫做requestA->B〗矗現(xiàn)在而咆,在b.jsp頁(yè)面中我們就可以從這個(gè)請(qǐng)求中獲取信息了。在b.jsp中你可以寫入 out.println(request.getParameter("id"))進(jìn)行測(cè)試幕袱。下面更復(fù)雜一點(diǎn)暴备,我們?cè)赽.jsp頁(yè)面中增加下面的語(yǔ)句:
request.setAttribute("name","funcreal"); //為請(qǐng)求設(shè)置一個(gè)name屬性
out.println(request.getAttriblute("name"));//在jsp顯示name變量的值
在b.jsp中再增加一個(gè)鏈接:<a href="c.jsp?age=23"></a>這是指向c的一個(gè)鏈接,而且還帶了一個(gè)參數(shù)</a>,當(dāng)我們點(diǎn)擊這個(gè)連接的時(shí)候们豌,將產(chǎn)生一個(gè)新的請(qǐng)求涯捻,這時(shí)requestA-B請(qǐng)求失效了,新的請(qǐng)求叫做requestB-C望迎。同樣的道理障癌,在c.jsp中,我們可以訪問(wèn)到的變量只有age辩尊,因?yàn)?id涛浙,name這兩個(gè)變量都屬于requestA-B,此時(shí)它已經(jīng)不存在了对省。下面是源代碼:
a.jsp
<%@ page contentType="text/html; charset=GBK" %>
<html>
<body bgcolor="#ffffff">
<a href="b.jsp?id=1">指向b.jsp蝗拿,而且還帶了一個(gè)參數(shù)id=1。requestA-B現(xiàn)在誕生了</a>
</body>
</html>
b.jsp
<%@ page contentType="text/html; charset=GBK" %>
<html>
<body bgcolor="#ffffff">
<%
out.println("id=" + request.getParameter("id"));
request.setAttribute("name","Func Real");
out.println("name=" + request.getAttribute("name"));
%>
<a href="c.jsp?age=23">requestA-B已經(jīng)蒿涎。指向c.jsp哀托,而且還帶了一個(gè)參數(shù)age=23</a>
</body>
</html>
c.jsp
<%@ 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>
那么轉(zhuǎn)發(fā)又是怎么回事呢?再增加一個(gè)頁(yè)面叫做d.jsp劳秋,并且在c.jsp中</body>前面增加一句<jsp:forward page="d.jsp"/>
d.jsp
<%@ page contentType="text/html; charset=GBK" %>
<html>
<body bgcolor="#ffffff">
requestB-C的魔爪已經(jīng)伸到了d.jsp頁(yè)面
<%
out.println("age=" + request.getParameter("age"));
%>
</body>
</html>
運(yùn)行程序仓手,發(fā)現(xiàn)c頁(yè)面中的內(nèi)容沒(méi)有顯示出來(lái),因?yàn)閒orward是自動(dòng)執(zhí)行的玻淑,地址欄中雖然是c.jsp但實(shí)際上嗽冒,但瀏覽器中顯示的已經(jīng)是d.jsp的 內(nèi)容了,而且看到了從b.jsp傳過(guò)來(lái)的參數(shù)补履。你可以簡(jiǎn)單得這樣理解:轉(zhuǎn)發(fā)添坊,就是延長(zhǎng)了requestB-C的作用 域,<jsp:forwardpage="d.jsp"/>箫锤,這一句話實(shí)際上是把c.jsp和d.jsp粘到了一起贬蛙,他們就像是在一個(gè)頁(yè)面 中雨女。
HttpServletResponse.sendRedirect?方法實(shí)現(xiàn)的請(qǐng)求重定向與RequestDispatcher.forward?方法實(shí)現(xiàn)的請(qǐng)求轉(zhuǎn)發(fā)的總結(jié):
1、RequestDispatcher.forward 方法只能將請(qǐng)求轉(zhuǎn)發(fā)給同一個(gè)WEB應(yīng)用中的組件阳准;而HttpServletResponse.sendRedirect 方法不僅可以重定向到當(dāng)前應(yīng)用程序中的其他資源氛堕,還可以重定向到同一個(gè)站點(diǎn)上的其他應(yīng)用程序中的資源,甚至是使用絕對(duì)URL重定向到其他站點(diǎn)的資源野蝇。如果 傳遞給HttpServletResponse.sendRedirect 方法的相對(duì)URL以“/”開(kāi)頭讼稚,它是相對(duì)于整個(gè)WEB站點(diǎn)的根目錄;如果創(chuàng)建RequestDispatcher 對(duì)象時(shí)指定的相對(duì)URL以“/”開(kāi)頭绕沈,它是相對(duì)于當(dāng)前WEB應(yīng)用程序的根目錄锐想。
2、調(diào)用HttpServletResponse.sendRedirect 方法重定向的訪問(wèn)過(guò)程結(jié)束后七冲,瀏覽器地址欄中顯示的URL會(huì)發(fā)生改變痛倚,由初始的URL地址變成重定向的目標(biāo)URL规婆;而調(diào)用 RequestDispatcher.forward 方法的請(qǐng)求轉(zhuǎn)發(fā)過(guò)程結(jié)束后澜躺,瀏覽器地址欄保持初始的URL地址不變。
3抒蚜、HttpServletResponse.sendRedirect 方法對(duì)瀏覽器的請(qǐng)求直接作出響應(yīng)掘鄙,響應(yīng)的結(jié)果就是告訴瀏覽器去重新發(fā)出對(duì)另外一個(gè)URL的訪問(wèn)請(qǐng)求。
舉個(gè)例子:重定向過(guò)程好比有個(gè)綽號(hào)叫“瀏覽器”的人寫信找張三借錢嗡髓,張三回信說(shuō)沒(méi)有錢操漠,讓“瀏覽器”去找李四借,并將李四現(xiàn)在的通信地址告訴給了“瀏覽器 ”饿这。于是浊伙,“瀏覽器”又按張三提供通信地址給李四寫信借錢,李四收到信后就把錢匯給了“瀏覽器”长捧∠桑可見(jiàn),“瀏覽器”一共發(fā)出了兩封信和收到了兩次回復(fù)串结,“ 瀏覽器”也知道他借到的錢出自李四之手哑子。 RequestDispatcher.forward 方法在服務(wù)器端內(nèi)部將請(qǐng)求轉(zhuǎn)發(fā)給另外一個(gè)資源,瀏覽器只知道發(fā)出了請(qǐng)求并得到了響應(yīng)結(jié)果肌割,并不知道在服務(wù)器程序內(nèi)部發(fā)生了轉(zhuǎn)發(fā)行為卧蜓。這個(gè)過(guò)程好比綽號(hào)叫“ 瀏覽器”的人寫信找張三借錢,張三沒(méi)有錢把敞,于是張三找李四借了一些錢弥奸,甚至還可以加上自己的一些錢,然后再將這些錢匯給了“瀏覽器”奋早∈Ⅵ可見(jiàn)冒冬,“瀏覽器”只 發(fā)出了一封信和收到了一次回復(fù),他只知道從張三那里借到了錢摩渺,并不知道有一部分錢出自李四之手简烤。
4、RequestDispatcher.forward 方法的調(diào)用者與被調(diào)用者之間共享相同的request 對(duì)象和response 對(duì)象摇幻,它們屬于同一個(gè)訪問(wèn)請(qǐng)求和響應(yīng)過(guò)程横侦;而HttpServletResponse.sendRedirect 方法調(diào)用者與被調(diào)用者使用各自的request 對(duì)象和response 對(duì)象,它們屬于兩個(gè)獨(dú)立的訪問(wèn)請(qǐng)求和響應(yīng)過(guò)程绰姻。
對(duì)于同一個(gè)WEB應(yīng)用程序的內(nèi)部資源之間的跳轉(zhuǎn)枉侧,特別是跳轉(zhuǎn)之前要對(duì)請(qǐng)求進(jìn)行一些前期預(yù)處理,并要使用 HttpServletRequest.setAttribute 方法傳遞預(yù)處理結(jié)果狂芋,那就應(yīng)該使用RequestDispatcher.forward 方法榨馁。
不同WEB應(yīng)用程序之間的重定向,特別是要重定向到另外一個(gè)WEB站點(diǎn)上的資源的情況帜矾,都應(yīng)該使HttpServletResponse.sendRedirect 方法翼虫。
5、無(wú)論是RequestDispatcher.forward 方法屡萤,還是HttpServletResponse.sendRedirect 方法珍剑,在調(diào)用它們之前,都不能有內(nèi)容已經(jīng)被實(shí)際輸出到了客戶端死陆。如果緩沖區(qū)中已經(jīng)有了一些內(nèi)容招拙,這些內(nèi)容將被從緩沖區(qū)中清除。