- Servlet的跳轉有2種,一種是轉發,一種是重定向。
重定向:
<strong><span style="font-size:14px;"></span></strong><pre name="code" class="java"><strong style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: rgb(255, 255, 255);"><span style="font-size:14px;"></span></strong><pre name="code" class="java" style="display: inline !important;">httpServletResponse.sendRedirect("/linkin/Linkin.jsp");轉發:
httpServletRequest.getRequestDispatcher("/Linkin.jsp").forward(httpServletRequest, httpServletResponse);在jsp中,也經常用到轉發。
<jsp:forward page="Linkin.jsp" />
- 在對比整理這2種Servlet之前,我們先來看下RequestDispatcher這個接口。
RequestDispatcher接口中定義了兩個方法:forward方法(頁面跳轉)和include方法(頁面包含,不怎么常用)。
forward和include方法接收的兩個參數必須是傳遞給當前Servlet的service方法的那兩個ServletRequest和ServletResponse對象,或者是對它們進行了包裝的ServletRequestWrapper 或ServletResponseWrapper對象。
ServletContext.getRequestDispatcher (參數只能寫絕對路徑,以“/”開頭)
ServletRequest.getRequestDispatcher (參數可以是絕對路徑,也可以是相對路徑)
關於轉發和重定向,還有表單提交,超鏈接這些路徑到底怎么寫,后面我會專門整理一篇博客,這里不做贅述。
- OK,現在來對比整理轉發和重定向。
轉發過程:客戶瀏覽器發送http請求----》web服務器接受此請求--》調用內部的一個方法在容器內部完成請求處理和轉發動作----》將目標資源發送給客戶。在這里,轉發的路徑必須是同一個web容器下的url,其不能轉向到其他的web路徑上去,中間傳遞的是自己的容器內的request。在客戶瀏覽器路徑欄顯示的仍然是其第一次訪問的路徑,也就是說客戶是感覺不到服務器做了轉發的。
重定向過程:客戶瀏覽器發送http請求----》web服務器接受后發送302狀態碼響應及對應新的location給客戶瀏覽器--》客戶瀏覽器發現是302響應,則自動再發送一個新的http請求,請求url是新的location地址----》服務器根據此請求尋找資源並發送給客戶。在這里location可以重定向到任意URL,既然是瀏覽器重新發出了請求,則就沒有什么request傳遞的概念了。在客戶瀏覽器路徑欄顯示的是其重定向的路徑,客戶可以觀察到地址的變化的。
1,轉發是服務器行為,重定向是客戶端行為。
2,轉發是瀏覽器只做了一次訪問請求。重定向是瀏覽器做了至少兩次的訪問請求的。
3,轉發瀏覽器地址不變,重定向瀏覽器地址改變。
4,轉發2次跳轉之間傳輸的信息不會丟失,重定向2次跳轉之間傳輸的信息會丟失(request范圍)。
5,轉發只能將請求轉發給同一個WEB應用中的組件,重定向可以指向任何的資源,包括當前應用程序中的其他資源,同一個站點上的其他應用程序中的資源,其他站點的資源。
注意:傳遞給HttpServletResponse.sendRedirect 方法的相對URL以“/”開頭,它是相對於整個WEB站點的根目錄;如果創建RequestDispatcher 對象時指定的相對URL以“/”開頭,它是相對於當前WEB應用程序的根目錄。
6,無論是RequestDispatcher.forward 方法,還是HttpServletResponse.sendRedirect 方法,在調用它們之前,都不能有內容已經被實際輸出到了客戶端。如果緩沖區中已經有了一些內容,這些內容將被從緩沖區中清除。
- 怎么選擇是重定向還是轉發呢?
2,因為重定向方式產生了一個新的請求,所以經過一次重定向后,request內的對象將無法使用,所以對於同一個WEB應用程序的內部資源之間的跳轉,特別是跳轉之前要對請求進行一些前期預處理,並要使用 HttpServletRequest.setAttribute 方法傳遞預處理結果,這個時候就只能使用轉發了。
3,因為轉發只能訪問別的應用程序,所以不同WEB應用程序之間的重定向,特別是要重定向到另外一個WEB站點上的資源的情況,這個時候就只能使用重定向了。
4,因為使用轉發,瀏覽器中URL仍然指向開始頁面,此時如果重載當前頁面,開始頁面將會被重新調用。如果你不想看到這樣的情況,則選擇重定向。
最后貼出2段代碼,演示下轉發,重定向。
package linkin; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * @author LinkinPark * @author 2015-7-8 * @Descri 轉發 */ public class LinkinServlet extends HttpServlet { private static final long serialVersionUID = 1L; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("UTF-8"); String userName = req.getParameter("userName"); String passWord = req.getParameter("passWord"); req.setAttribute("userName", userName); req.getSession().setAttribute("passWord", passWord); req.getRequestDispatcher("/Linkin.jsp").forward(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req, resp); } }
package linkin; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * @author LinkinPark * @author 2015-7-8 * @Descri 重定向 */ public class LinkinServlet extends HttpServlet { private static final long serialVersionUID = 1L; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("UTF-8"); String userName = req.getParameter("userName"); String passWord = req.getParameter("passWord"); req.setAttribute("userName", userName); req.getSession().setAttribute("passWord", passWord); resp.sendRedirect("/linkin/Linkin1.jsp"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req, resp); } }
