部分內容轉自:http://blog.csdn.net/zhouysh/article/details/380364和http://blog.csdn.net/frank_jay/article/details/51243481
1.RequestDispatcher.forward()
是在服務器端起作用,當使用forward()時,Servletengine傳遞HTTP請求從當前的Servlet or JSP到另外一個Servlet,JSP 或普通HTML文件,也即你的form提交至a.jsp,在a.jsp用到了forward()重定向至b.jsp,此時form提交的所有信息在b.jsp都可以獲得,參數自動傳遞.
但forward()無法重定向至有frame的jsp文件,可以重定向至有frame的html文件,同時forward()無法在后面帶參數傳遞,比如servlet?name=frank,這樣不行,可以程序內通過response.setAttribute("name",name)來傳至下一個頁面.
重定向后瀏覽器地址欄URL不變.
因為完成一個業務操作往往需要跨越多個步驟,每一步驟完成相應的處理后,轉向到下一個步驟。比如,通常業務處理在Servlet中處理,處理的結果轉向到一個 JSP頁面進行顯示。這樣看起來類似於Servlet鏈的功能,但是還有一些區別。一個RequestDispatcher對象可以把請求發送到任意一個服務器資源,而不僅僅是另外一個Servlet。
注意,只有在尚未向客戶端輸出響應時才可以調用forward()方法,如果頁面緩存不為空,在重定向前將自動清除緩存。否則將拋出一個異常
2.response.sendRedirect()
是在用戶的瀏覽器端工作,sendRedirect()可以帶參數傳遞,比如servlet?name=frank傳至下個頁面,同時它可以重定向至不同的主機上,且在瀏覽器地址欄上會出現重定向頁面的URL.
HttpServletResponse接口定義了可用於轉向的sendRedirect()方法。代碼如下:
public void sendRedirect(java.lang.String location)throws java.io.IOException |
這個方法將響應定向到參數location指定的、新的URL。location可以是一個絕對的URL,如response.sendRedirect ("http://java.sun.com")也可以使用相對的URL。如果location以"/"開頭,則容器認為相對於當前Web應用的根,否則,容器將解析為相對於當前請求的URL。這種重定向的方法,將導致客戶端瀏覽器的請求URL跳轉。從瀏覽器中的地址欄中可以看到新的URL地址,作用類似於上面設置HTTP響應頭信息的實現
sendRedirect()方法是通過瀏覽器重定向的,所以第二個JSP頁面中獲得的request並非是前一個頁面的request(兩次請求生成了前后兩個不同的 request對象了)。sendRedirect()是請求從定向,和超連接是一個意思,比如你在A頁面中寫一個request.setAtribute,sendRedirect到B頁面,就是說服務器從A頁面中給你一個response,然后你的瀏覽器再去request到B頁面,由於有兩次request和response,是不能在B頁面取到request.setAtribute里的值,能從地址欄看到url的改變。
request.getRequestDispatcher().forward(request,response)是請求分發器,比如你在A頁面中寫一個request.setAtribute,request.getRequestDispatcher().forward(request,response)到B頁面,那就是說服務器給你的response是B頁面的,並且只有一次request和response,所以是能在B頁面取到request.setAtribute里的值,地址欄的url仍然是A頁面的。
所以通常情況下,setAttribute()方法都和RequestDispatcher.forward()都在一起使用
看例子:
一個簡單的登錄界面,這里是個登錄的servlet:
package com.library.service; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import com.library.dao.LoginDao; import com.library.po.Librarian; public class LoginServlet extends HttpServlet { private static final long serialVersionUID = 1L; LoginDao loginDao = new LoginDao();//引入持久層 @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub super.doGet(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub String userName = req.getParameter("inputAccount"); String password = req.getParameter("inputPassword"); System.out.println("#############test:userName:"+userName+" password:"+password); Librarian user = loginDao.loginSuccess(userName, password); if(user==null) {//不存在,登錄失敗 Librarian userFail = new Librarian(userName, password); HttpSession session = req.getSession(); req.setAttribute("theUser", userFail); session.setAttribute("theUser", userFail); System.out.println("Login Failed"); req.getRequestDispatcher("/templates/loginFail.jsp").forward(req, resp); } else { HttpSession session = req.getSession(); req.setAttribute("theUser", user); session.setAttribute("theUser", user); System.out.println("Login Success!"); resp.sendRedirect("/TestWeb/templates/mainPage.jsp"); } } }
其中登錄成功的頁面是通過req.getRequestDispatcher("/templates/loginFail.jsp").forward(req, resp);來重定向的
而登錄失敗頁面是通過resp.sendRedirect("/TestWeb/templates/mainPage.jsp");來重定向的。
分別在登錄成功頁面和登錄失敗頁面用session和request來獲得數據
登錄失敗:
<body> <h1>登錄失敗</h1> <% Librarian user = (Librarian)request.getAttribute("theUser"); out.print("test in the dispatcher:<br>"); %> userName:<%=user.getUserName() %><br> password:<%=user.getPassword() %><br><br> <% Librarian user2 = (Librarian)session.getAttribute("theUser"); out.print("test in the session:<br>"); %> userName:<%=user2.getUserName() %><br> password:<%=user2.getPassword() %><br> </body>
發
登錄成功:
<body> <h1>成功登錄!</h1> <% //Librarian user = (Librarian)request.getAttribute("theUser"); //out.print("test in the dispatcher:<br>"); %> <%-- userName:<%=user.getUserName() %><br> password:<%=user.getPassword() %><br> age:<%=user.getAge() %><br> --%> <% Librarian user2 = (Librarian)session.getAttribute("theUser"); out.print("test in the session:<br>"); %> userName:<%=user2.getUserName() %><br> password:<%=user2.getPassword() %><br> age:<%=user2.getAge() %><br> position:<%=user2.getPosition() %><br><br> </body>
結果是在登錄失敗頁面兩種方法都可以訪問到user的信息,並且界面跳轉后仍然是servlet的url(/login是form的action的url):
而登錄成功頁面只能在session中訪問的到,而且url變了:
說明forward只有一次請求和回應,所以在重新定向的頁面可以通過request訪問的到之前request.setAttribute的數據,且url沒變。
而sendRediect跟超鏈接其實是一個意思,從A頁面sendRedirect到B頁面,就是說服務器從A頁面中給你一個response,然后你的瀏覽器再去request到B頁面,由於有兩次request和response,是不能在B頁面取到request.setAtribute里的值,能從地址欄看到url的改變。