討論它們的區(qū)別之前,先讓我們看下它們是怎樣被調(diào)用的?
Response.sendRedirect(redirect)
redirect="AccessGoalCharts.jsp?rcatID=3&rhaID=All_&doSearch=true”
實(shí)際上,container會將這個(gè) redirect的 url字符串重新送到
Browser interface,相當(dāng)于用戶重新在address欄中輸入了一個(gè)地址,赫赫,
這樣解釋簡單吧?
request.getRequestDispatcher("welcome.jsp").forward(request, response);
我們查一下web.xml,如果我們沒有找到相應(yīng)的servlet mapping,那么這套
Request和response(也就是原來的browse interface)就被轉(zhuǎn)到 welcome.jsp
去處理了,welcome.jsp產(chǎn)生的html page也就被返回到了 response(也就是原來的browser interface).如果在web.xml當(dāng)中我們找到了相應(yīng)的 servlet mapping, 如下所示,
<servlet-mapping>
<servlet-name>DemoServlet</servlet-name>
<url-pattern>/welcome.jsp</url-pattern>
</servlet-mapping>
那么這套request和response就被forward到了DemoServlet的 doGet或者 doPost去處理了,問題是,getRequestDispatcher為什么不改名字叫做 getURLDispatcher,這不是更加符合 由 web.xml控制的實(shí)際情況嗎?
Request.getRequestDispatcher(“welcome.jsp”).include(request,response)和 forward(request,response)的情況一模一樣,區(qū)別在于,這個(gè)response,也就是 Browse Interface在接收了welcome.jsp產(chǎn)生的html page以后(假設(shè)在 web,xml當(dāng)中沒有相對應(yīng)于 welcome.jsp的 servlet-mapping),還可以在這個(gè)response( browser interface)當(dāng)中接收其他的html page,我測試過的代碼如下所示:
request.getRequestDispatcher("welcome.jsp").include(request, response);
PrintWriter out = response.getWriter();
out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
out.println("<HTML>");
out.println(" <HEAD><TITLE>A Servlet</TITLE></HEAD>");
out.println(" <BODY>");
out.print(" This is " + request.getParameter("name"));
out.print(this.getClass());
out.println(", using the POST method");
out.println(" </BODY>");
out.println("</HTML>");
out.flush();
out.close();
好了,還有一些考試大全中經(jīng)常描述的 forward對于 用戶來講是透明的,而 reDirect對于用戶來講是 在browser的地址欄中可見的講法,都是正確的講法.
好,我再用通俗的講法講解一下 sendRedirct, forward, include的區(qū)別 (基于 servlet api 2.2以上)
(1)response.sendRedirect(String location)
Sends a temporary redirect response to the client using the specified redirect location URL 實(shí)際上是給client返回一個(gè)臨時(shí)的response,里面也就一個(gè)url,告訴client,我現(xiàn)在已經(jīng)處理完了你的request, 你應(yīng)該進(jìn)入這個(gè)URL,它會處理你的request了(這個(gè)request的內(nèi)容您這個(gè)client可能就不太清楚了) (2)requestDispatcher.forward(request, response)
現(xiàn)在的servlet把控制權(quán)完全交給另外一個(gè)Servlet,這個(gè)servlet已經(jīng)預(yù)先處理過的request和response也一并移交過去, 這個(gè)forward的過程實(shí)際上Client并不知道,是Server端的幾個(gè)servlet collaboration. (3)include又和 forward有什么區(qū)別呢?
赫赫, requestDispatcher.include(request, response) 好像沒有什么區(qū)別啊,include僅僅是include, 接收request的那個(gè)servlet (called servlet),它往printerWriter(或OutputStream, writer是寫文本 而stream是寫二進(jìn)制)中寫的內(nèi)容是 caller servlet往 printerWriter(或 outputStream)中寫的內(nèi)容的一部分.而 requestDispatcher.forward(request, response)就不一樣了,calling servlet控制權(quán)完全交出去了, calling servlet 的response buffer中的東西都被清空了,所以如果你要 forward,就是轉(zhuǎn)移控制權(quán)的話, 你根本就不應(yīng)該在calling servlet 中的response里面寫任何東西,寫了的話一旦 forward的話也就白瞎了,因?yàn)楸磺蹇樟寺? (4)為什么 request.getRequestDispatcher 而 response.sendRedirect(new_url)呢?
我舉個(gè)簡單的例子, request.getRequestDispatcher("/servlets/bookItems?bookId=18871"); 赫赫,在 getRequestDispatcher的同時(shí)還可以往 request當(dāng)中塞一個(gè)parameter啊. 而response.sendRirect(new_url)呢, 這個(gè)new_url可是會返回給client browser看的,所以 當(dāng)然是response.sendRedirect(new_url)了. Servlet中forward和redirect的區(qū)別
forward方式:request.getRequestDispatcher("/somePage.jsp").forwardrequest, response); -------------------------------------------------------------------------------------------------- 在Java Web開發(fā)中,經(jīng)常會用到跳轉(zhuǎn)頁面的方法,一般有下面兩種方法。 -------------------------------------------------------------------------------------------------- 清空當(dāng)前緩存: 在之前撰寫JSP的例子中,實(shí)用了out這個(gè)對象,這個(gè)對象您不用事先宣告,就可以在JSP網(wǎng)頁中使用,這是JSP所提供的隱含對象 (Implicit Object),在轉(zhuǎn)譯為Servlet之后,out會轉(zhuǎn)換為對應(yīng)于javax.servlet.jsp.JspWriter型態(tài)的對象。 JspWriter直接繼承自java.io.Writer,您可以使用println()、print()方法將指定的數(shù)據(jù)以字符的方式傳送至客戶端,println()會 在送出數(shù)據(jù)之后進(jìn)行換行,而print()則否,注意換行指的是在HTML原始碼中設(shè)定換行字符,而不是輸出<br>標(biāo)簽使得在網(wǎng)頁中可以 換行。 out(JspWriter)具有緩沖區(qū)功能,HTTP的特性是為了要取得一份資源,就進(jìn)行一份協(xié)議溝通,如果資源數(shù)目很多(例如一份HTML文件 還包括了許多的小圖片),而每份資源的容量實(shí)際上很小,那么為了要取得完整的資源,將會花費(fèi)很多通訊在協(xié)議往來上,假設(shè)如果 out(JspWriter)不具有緩沖功能,則每一次out.println(),就會直接將數(shù)據(jù)送出至客戶端,那么單要完成一個(gè)完整網(wǎng)頁的傳送,就 會花費(fèi)不少的網(wǎng)絡(luò)資源,每一個(gè)JSP網(wǎng)頁預(yù)設(shè)上都會具有緩沖,您可以使用page指令元素的autoFlush屬性來設(shè)定是否使用緩沖區(qū)功能 。 在Tomcat5上,預(yù)設(shè)為每一個(gè)JSP網(wǎng)頁備有8192字節(jié)的緩沖區(qū)(您可以使用page指令元素的buffer屬性來自緩沖區(qū)的大小),在緩沖區(qū)還 沒有滿之前,數(shù)據(jù)不會真正被送出至客戶端,在這之前,您還有機(jī)會重設(shè)送出的數(shù)據(jù),如果緩沖區(qū)滿了,數(shù)據(jù)將會被清出并送至客戶 端,可以使用下面這個(gè)程序來示范: buffer.jsp 您可以使用flush()直接清出緩沖區(qū)的內(nèi)容,而clearBuffer()會將緩沖區(qū)的內(nèi)容清除,所以第二段文字不會出現(xiàn)在客戶端的網(wǎng)頁上, 而最后一段會整個(gè)JSP網(wǎng)頁執(zhí)行完整后自動(dòng)送出至客戶端,執(zhí)行結(jié)果如下: 預(yù)設(shè)緩沖區(qū)大?。?192 這段您可以看到! 您可以使用page指令元素的autoFlush來設(shè)定JSP頁面是否使用緩沖區(qū)自動(dòng)清出功能,out(JspWriter)以一種方式與 HttpServletResponse的PrintWriter建立關(guān)系,兩者之間的行為關(guān)系取決于是否使用緩沖區(qū)自動(dòng)清出,如果使用緩沖區(qū)自動(dòng)清出,則 在緩沖區(qū)滿之前,或是使用flush()之前不會建立PrintWriter對象來對客戶端進(jìn)行輸出,如果不使用緩沖區(qū)自動(dòng)清出,則寫入out (JspWriter)對象的數(shù)據(jù)會直接寫入PrintWriter對象,然后在指定flush()之后輸出至客戶端。 如果您將autoFlush設(shè)定為false,則您必須明確的使用flush()來輸出數(shù)據(jù),否則緩沖區(qū)滿了的話,就會發(fā)生IOException例外,使用 緩沖區(qū)有其好處,但由于緩沖區(qū)在滿之前,數(shù)據(jù)并不會真正送出客戶端,所以會有響應(yīng)延遲的問題,如果您要實(shí)時(shí)性將結(jié)果響應(yīng)至客 戶端,則可以關(guān)閉緩沖區(qū)。 下面這個(gè)程序測試緩沖區(qū)關(guān)閉之后,如果緩沖區(qū)滿了,會有什么結(jié)果: buffer.jsp 如果沒有移開out.flush()的批注符號,則會響應(yīng)一下的錯(cuò)誤訊息: |
|