一、轉(zhuǎn)發(fā)
轉(zhuǎn)發(fā)的原理,可以通過(guò)下圖展示:
瀏覽器的請(qǐng)求發(fā)送給組件1,組件1經(jīng)過(guò)一些處理之后,將request和response對(duì)象“傳遞”給組件2,由組件2繼續(xù)處理,然后輸出響應(yīng)(當(dāng)然,也可以繼續(xù)向其他組件“傳遞”),這個(gè)傳遞的過(guò)程稱之為“轉(zhuǎn)發(fā)”。整個(gè)過(guò)程只涉及一次瀏覽器和服務(wù)器之間的“請(qǐng)求-響應(yīng)”,轉(zhuǎn)發(fā)過(guò)程中的組件共享同一個(gè)請(qǐng)求(request)和響應(yīng)(response)對(duì)象。
轉(zhuǎn)發(fā)的意義在于可以實(shí)現(xiàn)組件的“分工”。在基于MVC,多層結(jié)構(gòu)的Web應(yīng)用中,經(jīng)常需要多個(gè)組件協(xié)同完成一次“請(qǐng)求-響應(yīng)”工作,例如:用戶要獲取“設(shè)備列表信息”,提交請(qǐng)求至控制器組件(Servlet),該Servlet調(diào)用適當(dāng)?shù)?span lang="EN-US">JavaBean獲取了“設(shè)備列表”數(shù)據(jù)然后再轉(zhuǎn)發(fā)至JSP組件去顯示信息。
RequestDispatcher對(duì)象封裝了轉(zhuǎn)發(fā)操作。通過(guò)request的getRequestDispatcher(String path)方法獲得RequestDispatcher對(duì)象,其中String類型參數(shù)path表示要轉(zhuǎn)發(fā)到的地址。調(diào)用Dispacther對(duì)象的forward(request, response)方法實(shí)現(xiàn)轉(zhuǎn)發(fā)。關(guān)于轉(zhuǎn)發(fā)的具體操作,有如下幾點(diǎn)需要注意:
1、轉(zhuǎn)發(fā)只能在同一個(gè)應(yīng)用的組件之間進(jìn)行,不可以轉(zhuǎn)發(fā)給其他應(yīng)用的地址。
2、轉(zhuǎn)發(fā)的地址可以用“相對(duì)地址”方式,也可以用“絕對(duì)地址”方式。但需要注意的是:用絕對(duì)地址方式時(shí),應(yīng)從應(yīng)用名后(Context path)開始。例如:要轉(zhuǎn)發(fā)到的地址為: http://192.168.5.100/tst/jsp/somewhere.jsp (其中tst為應(yīng)用名),對(duì)應(yīng)的絕對(duì)地址為:“/jsp/somewhere.jsp”。這是很好理解的,因?yàn)檗D(zhuǎn)發(fā)只能轉(zhuǎn)到本應(yīng)用內(nèi)的地址,所以絕對(duì)地址是沒有必要包含應(yīng)用名的。
3、組件之間通過(guò)轉(zhuǎn)發(fā)來(lái)分工協(xié)作,勢(shì)必涉及數(shù)據(jù)的傳遞,可以通過(guò)request對(duì)象傳遞數(shù)據(jù)。request對(duì)象的setAttribute和getAttribute分別用于以“名稱-對(duì)象對(duì)”的形式存取數(shù)據(jù)。例如:
request.setAttribute("food", "roast duck");
RequestDispatcher rd = request.getRequestDispatcher("jsp/somewhere.jsp");
rd.forward(request, response);
somewhere.jsp的內(nèi)容:
<h1>Hey, <%=request.getAttribute("food")%></h1>
在轉(zhuǎn)發(fā)之前通過(guò)request的setAttribute(String name,Object obj)方法向request中存入了一個(gè)名為“food”的字符串對(duì)象“roast duck”。在轉(zhuǎn)發(fā)到的jsp/somewhere.jsp中可以通過(guò)request的方法
getAttribute方法取出名為“food”的對(duì)象,然后顯示在頁(yè)面上。
4、在一個(gè)組件轉(zhuǎn)發(fā)給另外一個(gè)組件之前,通過(guò)response輸出的響應(yīng)內(nèi)容是沒有意義的。例如:在下面的語(yǔ)句中:
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<h2>head</h2><hr/>");
RequestDispatcher rd = request.getRequestDispatcher("jsp/somewhere.jsp");
rd.forward(request, response);
用戶看到的是/jsp/somewhere.jsp的內(nèi)容,而在轉(zhuǎn)發(fā)之前的通過(guò)out對(duì)象輸出的內(nèi)容:
"<h2>head</h2><hr/>" 最終不會(huì)輸出到瀏覽器,這是由于RequestDispatcher在轉(zhuǎn)發(fā)之前清空了輸出緩沖區(qū)。但如果在轉(zhuǎn)發(fā)之前輸出的信息超出了緩沖區(qū),或者調(diào)用了out對(duì)象的flush()方法,此響應(yīng)內(nèi)容已經(jīng)輸出到了客戶端(稱之為響應(yīng)信息已提交),此時(shí)如果實(shí)施轉(zhuǎn)發(fā)操作會(huì)拋出運(yùn)行時(shí)異常:java.lang.IllegalStateException。
二、重定向
重定向的含義可以由下圖說(shuō)明:
瀏覽器向某組件發(fā)出請(qǐng)求信息,組件向?yàn)g覽器發(fā)回一個(gè)重定向響應(yīng)信息,該響應(yīng)信息不包含具體的數(shù)據(jù)內(nèi)容,只是在響應(yīng)頭信息中包含了需要重定向到的地址信息,該地址可以是任何有效的URL。瀏覽器收到該重定向響應(yīng)后會(huì)自動(dòng)的向響應(yīng)信息頭中所指示的地址發(fā)出請(qǐng)求。整個(gè)重定向的過(guò)程涉及兩次“請(qǐng)求-響應(yīng)”。具體的重定向響應(yīng)格式如下所示:
HTTP/1.1 302 Moved Temporarily
Server: Apache-Coyote/1.1
Location: http://192.168.5.100:8080/tst/jsp/somewhere.jsp
Content-Length: 0
Date: Mon, 30 Jun 2008 03:52:54 GMT
注意:重定向響應(yīng)中包含重定向地址的部分。
重定向可以通過(guò)response的sendRedirect(String url)方法來(lái)實(shí)現(xiàn),注意String類型的參數(shù)url表示重定向到的地址,需要注意的是,如果表示重定向到本應(yīng)用內(nèi)的一個(gè)絕對(duì)地址時(shí),要從應(yīng)用名前開始,例如:tst應(yīng)用中的某個(gè)組件要重定向到本應(yīng)用內(nèi)的/jsp/somewhere.jsp,則重定向的絕對(duì)地址應(yīng)該是:“/tst/jsp/somewhere.jsp”這一點(diǎn)和轉(zhuǎn)發(fā)中的絕對(duì)地址表示是不同的。

