forward和sendRedirect的區別


部分內容轉自: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的改變。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM