一、調用方式
我們知道,在servlet中調用轉發、重定向的語句如下:
request.getRequestDispatcher("new.jsp").forward(request, response); //轉發到new.jsp
response.sendRedirect("new.jsp"); //重定向到new.jsp
在jsp頁面中你也會看到通過下面的方式實作轉發:
<jsp:forward page="apage.jsp" />
當然也可以在jsp頁面中實作重定向:
<%response.sendRedirect("new.jsp"); %> //重定向到new.jsp
二、本質差別
解釋一
一句話,轉發是伺服器行為,重定向是用戶端行為。為什麼這樣說呢,這就要看兩個動作的工作流程:
轉發過程:客戶浏覽器發送http請求——》web伺服器接受此請求——》調用内部的一個方法在容器内部完成請求處理和轉發動作——》将目标資源發送給客戶;在這裡,轉發的路徑必須是同一個web容器下的url,其不能轉向到其他的web路徑上去,中間傳遞的是自己的容器内的request。在客戶浏覽器路徑欄顯示的仍然是其第一次通路的路徑,也就是說客戶是感覺不到伺服器做了轉發的。轉發行為是浏覽器隻做了一次通路請求。
重定向過程:客戶浏覽器發送http請求——》web伺服器接受後發送302狀态碼響應及對應新的location給客戶浏覽器——》客戶浏覽器發現是302響應,則自動再發送一個新的http請求,請求url是新的location位址——》伺服器根據此請求尋找資源并發送給客戶。在這裡location可以重定向到任意URL,既然是浏覽器重新發出了請求,則就沒有什麼request傳遞的概念了。在客戶浏覽器路徑欄顯示的是其重定向的路徑,客戶可以觀察到位址的變化的。重定向行為是浏覽器做了至少兩次的通路請求的。
解釋二
重定向,其實是兩次request
第一次,用戶端request A,伺服器響應,并response回來,告訴浏覽器,你應該去B。這個時候IE可以看到位址變了,而且曆史的回退按鈕也亮了。重定向可以通路自己web應用以外的資源。在重定向的過程中,傳輸的資訊會被丢失。
例子:
response.sendRedirect("loginsuccess.jsp");
請求轉發是伺服器内部把對一個request/response的處理權,移交給另外一個
對于用戶端而言,它隻知道自己最早請求的那個A,而不知道中間的B,甚至C、D。傳輸的資訊不會丢失。
RequestDispatcher dis=request.getRequestDispatcher(“loginsuccess.jsp”);
Dis.forward(request,response);
解釋三
假設你去辦理某個執照
重定向:你先去了A局,A局的人說:“這個事情不歸我們管,去B局”,然後,你就從A退了出來,自己乘車去了B局。
轉發:你先去了A局,A局看了以後,知道這個事情其實應該B局來管,但是他沒有把你退回來,而是讓你坐一會兒,自己到後面辦公室聯系了B的人,讓他們辦好後,送了過來。
http://blog.163.com/tsing_hua/blog/static/139622224201101110836644/
http://blog.csdn.net/cuiweibing/article/details/1791655
1. forward方法使用
<dl></dl>
<dd><dl></dl></dd>
<dt>Parameters:</dt>
<dd></dd>
<code>path</code> - a <code>String</code> specifying the pathname to the resource. If it is relative, it must be relative against the current servlet.
<dt>Returns:</dt>
<dt>See Also:</dt>
<dd>Forwards a request from a servlet to another resource (servlet, JSP file, or HTML file) on the server. This method allows one servlet to do preliminary processing of a request and another resource to generate the response.</dd>
For a <code>RequestDispatcher</code> obtained via <code>getRequestDispatcher()</code>, the <code>ServletRequest</code> object has its path elements and parameters adjusted to match the path of the target resource.
<code>forward</code> should be called before the response has been committed to the client (before response body output has been flushed). If the response already has been committed, this method throws an <code>IllegalStateException</code>. Uncommitted output in the response buffer is automatically cleared before the forward.
<dt>Throws:</dt>
<dd>Sends a temporary redirect response to the client using the specified redirect location URL. This method can accept relative URLs; the servlet container must convert the relative URL to an absolute URL before sending the response to the client. If the location is relative without a leading '/' the container interprets it as relative to the current request URI. If the location is relative with a leading '/' the container interprets it as relative to the servlet container root.</dd>
If the response has already been committed, this method throws an IllegalStateException. After using this method, the response should be considered to be committed and should not be written to.
<dt>參數</dt>
<code>定位</code> - the redirect location URL
<code>java.io.IOException</code> - If an input or output exception occurs
<code>java.lang.IllegalStateException</code> - If the response was committed or if a partial URL is given and cannot be converted into a valid URL
Servlet 跳轉 redirect與forward跳轉的差別
Servlet:
當然,在servlet中,一般跳轉都發生在doGet, doPost等方法裡面。
一、原理
1) redirect 方式
response.sendRedirect("/a.jsp");
頁面的路徑是相對路徑。sendRedirect可以将頁面跳轉到任何頁面,不一定局限于本web應用中,如:
response.sendRedirect("http://www.ycul.com");
跳轉後浏覽器位址欄變化。
這種方式要傳值出去的話,隻能在url中帶parameter或者放在session中,無法使用request.setAttribute來傳遞。
這種方式是在用戶端作的重定向處理。該方法通過修改HTTP協定的HEADER部分,對浏覽器下達重定向指令的,讓浏覽器對在location中指定的URL提出請求,使浏覽器顯示重定向網頁的内容。該方法可以接受絕對的或相對的URLs。如果傳遞到該方法的參數是一個相對的URL,那麼Web container在将它發送到用戶端前會把它轉換成一個絕對的URL。public void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException
{
response.setContentType("text/html; charset=UTF-8");
response.sendRedirect("/index.jsp");
}
2) forward方式
RequestDispatcher dispatcher = request.getRequestDispatcher("/a.jsp");
dispatcher .forward(request, response);
頁面的路徑是相對路徑。forward方式隻能跳轉到本web應用中的頁面上。
跳轉後浏覽器位址欄不會變化。
使用這種方式跳轉,傳值可以使用三種方法:url中帶parameter,session,request.setAttribute
這種方式是在伺服器端作的重定向。伺服器往client發送資料的過程是這樣的:伺服器在向用戶端發送資料之前,是先将資料輸出到緩沖區,然後将緩沖區中資料發送給client端。什麼時候将緩沖區裡的資料發送給client端呢?(1)當對來自client的request處理完,并把所有資料輸出到緩沖區,(2)當緩沖區滿,(3)在程式中調用緩沖區的輸出方法out.flush()或response.flushbuffer(),web container才将緩沖區中的資料發送給client。
這種重定向方式是利用伺服器端的緩沖區機制,在把緩沖區的資料發送到用戶端之前,原來的資料不發送,将執行轉向重定向頁面,發送重定向頁面的資料,重定向調用頁的資料将被清除。如果在<JSP:FORWORD>之前有很多輸出,前面的輸出已使緩沖區滿,将自動輸出到用戶端,那麼這種重定向方式将不起作用,這一點應該特别注意。
public void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException
ServletContext sc = getServletContext();
RequestDispatcher rd = null;
rd = sc.getRequestDispatcher("/index.jsp");
rd.forward(request, response);
二、差別.
1、forward重定向是在容器内部實作的同一個Web應用程式的重定向,是以forward方法隻能重定向到同一個Web應用程式中的一個資源,重定向後浏覽器位址欄URL不變,而sendRedirect方法可以重定向到任何URL, 因為這種方法是修改http頭來實作的,URL沒什麼限制,重定向後浏覽器位址欄URL改變。
2、forward重定向将原始的HTTP請求對象(request)從一個servlet執行個體傳遞到另一個執行個體,而采用sendRedirect方式兩者不是同一個application。
3、基于第二點,參數的傳遞方式不一樣。forward的form參數跟着傳遞,是以在第二個執行個體中可以取得HTTP請求的參數。sendRedirect隻能通過連結傳遞參數,response.sendRedirect(“login.jsp?param1=a”)。
<a href="http://lib.csdn.net/base/java" target="_blank">Java</a>
他們的差別是:
response.sendRedirect是向客戶浏覽器發送頁面重定向指令,浏覽器接收後将向web伺服器重新發送頁面請求,是以執行完後浏覽器的url顯示的是跳轉後的頁面。跳轉頁面可以是一個任意的url(本伺服器的和其他伺服器的均可)。
RequestDispatcher.forward則是直接在伺服器中進行處理,将處理完後的資訊發送給浏覽器進行顯示,是以完成後在url中顯示的是跳轉前的頁面。在forward的時候将上一頁面中傳送的request和response資訊一同發送給下一頁面(而response.sendRedirect不能将上一頁面的request和response資訊發送到下一頁面)。由于forward是直接在伺服器中進行處理,是以forward的頁面隻能是本伺服器的。
JSP:
1) response.sendRedirect();
和servlet的response.sendRedirect()方式一樣。
此語句前不允許有out.flush(),如果有,會有異常:
java.lang.IllegalStateException: Can't sendRedirect() after data has committed to the client.
at com.caucho.server.connection.AbstractHttpResponse.sendRedirect(AbstractHttpResponse.java:558)
...
跳轉後浏覽器位址欄變化
如果要跳到不同主機下,跳轉後,此語句後面的語句會繼續執行,如同新開了線程,但是對response的操作已經無意義了;
如果要跳到相同主機下,此語句後面的語句執行完成後才會跳轉;
2) response.setHeader("Location","");
此語句前不允許有out.flush(),如果有,頁面不會跳轉。
此語句後面的語句執行完成後才會跳轉
3) <jsp:forward page="" />
java.lang.IllegalStateException: forward() not allowed after buffer has committed.
at com.caucho.server.webapp.RequestDispatcherImpl.forward(RequestDispatcherImpl.java:134)
at com.caucho.server.webapp.RequestDispatcherImpl.forward(RequestDispatcherImpl.java:101)
at com.caucho.jsp.PageContextImpl.forward(PageContextImpl.java:836)
跳轉後浏覽器位址欄不變,但是隻能跳到目前主機下
http://blog.csdn.net/honghailiang888/article/details/52679176