重定向 / 轉發
在JAVA中進行資源跳轉,或者是頁面跳轉,從本質上來講,有兩種方式:重定向 , 轉發
這兩者都可以使頁面進行跳轉,但是兩者之間有不同的區別
其中 SendRedirect,setHeader 屬於重定向方式,而 forward 屬於轉發方式
重定向(sendRedirect,setHeader)
1.重定向到指定URL,是客戶端跳轉
2.地址欄中的地址將會改變,變成重定向的地址
3.調用者和被調用者處於兩次不同的請求。不能通過request域對象來共享數據,
如果需要傳遞參數,需要在 url 後加參數,如 url?id=2,或者使用ServletContext 存放全局數據,不能通過request和response方式
4.使用重定向方式可以重定向到任意 URL
response.sendRedirect(url);
response.sendRedirect( "/uu ");表示相對於服務器根路徑
url 可以使用相對路徑,也可以使用絕對路徑
//需要設置狀態碼 302(found),重新定位
response.setStatus(302);
response.setHeader("Location","url");
重定向的詳細過程:
Redirect 會發送一個 response(響應)給瀏覽器,當瀏覽器接收到 response 後,再發送一個request(請求)給服務器,服務器接收到後,會發送新的 response 給瀏覽器,而這時候,頁面接收到的是從瀏覽器取來的新的request。
那麼,在跳轉之前的頁面所存放在request.setAttribute中的東西就沒了,如果在新頁面中使用request.getAttribute 獲取以前存放的元素,將會得到null。
所以在傳遞參數時,不能使用request和response方式。
瀏覽器和服務器兩次請求響應。
轉發(forward)
1.請求轉發到指定URL
2.是服務器端跳轉
3.地址欄中的網址保持不變
4.只能重定向到同一個Web應用程序中的某個資源(機跳轉範圍只能是整個項目範圍內的資源)
無法重定向至有frame的jsp文件,可以重定向至有frame的html文件,同時forward()無法在後面帶參數傳遞,比如servlet?name=frank
可以通過response.setAttribute("name",name)來傳至下一個頁面
5.採用請求轉發方式,在跳轉頁面的時候是帶着原來頁面的request和response跳轉的,request對象始終存在,所以可以使用域對象傳遞參數。
request.getRequestDispatcher(“url”).forward(request,response);
轉發的詳細過程:
forward() 過程 發生在服務器端, 客戶端瀏覽器只發出一次請求,在服務器端,Servlet將用戶的請求連同請求信息等內容轉發給Servlet、HTML、JSP或其它信息資源,由第2個信息資源響應該請求,兩個信息資源共享同一個request對象,參數自動傳遞。
瀏覽器和服務器一次請求響應。
總結
setHeader() 的其他幾種使用方式
一秒刷新頁面一次:response.setHeader("refresh","1");
二秒跳到其他頁面:response.setHeader("refresh","2;URL=otherPagename");
沒有緩存:response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
forward方法只有一次的瀏覽器服務器請求,只有一個Request和Response,所以調用者與被調用者之間共享Request和Response
sendRedirect方法由於兩次瀏覽器服務器請求,所以有兩個Request和Response。
如果使用 request.setAttribute 傳遞一些屬性就需要用forward,如果想要跳轉到別的應用的資源,就需要用 sendRedirect,setHeader。
PS:無論是forward方法還是sendRedirect方法調用前面都不能有PrintWriter輸出到客戶端。
forward方法報錯: Java.lang.IllegalStateException: Cannot forward after response has been committed
sendRedirect報錯:java.lang.IllegalStateException: at org.apache.catalina.connector.ResponseFacade.sendRedirect