RequestDispatcher.forward()vs HttpServletResponse.sendRedirect()

forward()sendRedirect()之间的概念区别是什么?

requestDispatcher – forward()方法

  1. 当我们使用forward方法时,请求被转移到同一个服务器内的其他资源进行进一步处理。

  2. 在转发的情况下,Web容器处理所有内部处理,客户端或浏览器不涉及。

  3. 当在requestdispatcher对象上调用forward时,我们传递请求和响应对象,以便我们的旧请求对象存在于正在处理我们请求的新资源上。

  4. 在视觉上我们无法看到转发的地址,它是透明的。

  5. 使用forward()方法比发送redirect要快。

  6. 当我们使用forward进行redirect时,我们希望在新资源中使用相同的数据,所以我们可以使用request.setAttribute(),因为我们有请求对象可用。

的sendRedirect

  1. 在sendRedirect的情况下,请求被转移到另一个资源到不同的域或不同的服务器,以便进一步处理。

  2. 当你使用sendRedirect时,容器将请求传递给客户端或者浏览器,这样在sendRedirect方法中给出的URL作为对客户端的新请求是可见的。

  3. 在sendRedirect调用的情况下,旧的请求和响应对象由于被浏览器视为新请求而丢失。

  4. 在地址栏中,我们可以看到新的redirect地址。 它不透明。

  5. sendRedirect比较慢,因为需要一个额外的往返行程,因为全新的请求被创build并且旧的请求对象被丢失。 需要两个浏览器请求。

  6. 但是在sendRedirect中,如果我们想要使用,我们必须将数据存储在会话中,或者与URL一起传递。

哪一个好?

它取决于哪种方法更有用的场景。

如果你想控制转移到新的服务器或上下文,它被视为完全新的任务,那么我们去发送redirect。 一般来说,如果浏览器重新加载网页时操作可以安全地重复,则不会影响结果。

资源

首先,术语“redirect”在Web开发世界中是向客户端发送空HTTP响应的动作,其中仅具有Location头,其中客户端必须发送新的GET请求的新URL。 所以基本上:

  • 客户端向some.jsp发送HTTP请求。
  • 服务器使用Location: other.jsp标题返回HTTP响应
  • 客户端向other.jsp发送HTTP请求(这反映在浏览器地址栏中!)
  • 服务器用other.jsp内容返回HTTP响应。

您可以使用网页浏览器的内置/附件开发者工具集进行跟踪。 在Chrome / IE9 / Firebug中按F12,然后选中“networking”部分查看。

完全上面的是通过sendRedirect("other.jsp")RequestDispatcher#forward()不发送redirect。 而是使用目标页面的内容作为HTTP响应。

  • 客户端向some.jsp发送HTTP请求。
  • 服务器用other.jsp内容返回HTTP响应。

但是,由于原始HTTP请求是对some.jsp ,浏览器地址栏中的URL保持不变。


RequestDispatcher在MVC范例中非常有用,并且/或者当您希望隐藏JSP的直接访问时。 您可以将JSP放在/WEB-INF文件夹中,并使用一个Servlet控制,预处理和后处理请求。 /WEB-INF文件夹中的JSP不能通过URL直接访问,但是Servlet可以使用RequestDispatcher#forward()访问它们。

例如,您可以在/WEB-INF/login.jsp拥有一个JSP文件,并在/loginurl-pattern上映射一个LoginServlet 。 当你调用http://example.com/context/login ,servlet的doGet()将被调用。 你可以在那里做任何预处理的东西,并最终转发请求,如:

 request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response); 

提交表单时,通常需要使用POST

 <form action="login" method="post"> 

这样,servlet的doPost()将被调用,你可以在那里做任何处理的东西(如validation,业务逻辑,login用户等)。

如果有任何错误,那么您通常会将请求转发回同一页面,并在input字段旁边显示错误等等。 您可以使用RequestDispatcher

如果POST成功,您通常需要redirect请求,以便在用户刷新请求时(例如按F5或在历史logging中导航回来),请求不会被重新提交。

 User user = userDAO.find(username, password); if (user != null) { request.getSession().setAttribute("user", user); // Login user. response.sendRedirect("home"); // Redirects to http://example.com/context/home after succesful login. } else { request.setAttribute("error", "Unknown login, please try again."); // Set error. request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response); // Forward to same page so that you can display error. } 

redirect因此指示客户端在给定的URL上触发新的GET请求。 刷新请求将只刷新redirect的请求,而不是初始请求。 这样可以避免“双重提交”和混乱以及糟糕的用户体验。 这也被称为POST-Redirect-GET模式 。

RequestDispatcher接口允许你做一个服务器端转发/包含,而sendRedirect()做一个客户端redirect。 在客户端redirect中,服务器将发回一个302 (临时redirect)的HTTP状态码,这将导致Web浏览器为redirect位置的内容发出全新的HTTP GET请求。 相比之下,使用RequestDispatcher接口时,包含/转发到新资源完全在服务器端处理。

这两种方法中的任何一种都可能是“更好的”,也就是说更合适,取决于你想要做什么。

服务器端redirect速度更快,只要你从一个不同的页面获取数据,而不需要往返浏览器。 但浏览器中看到的URL仍然是原始地址,所以你在这里创build了一些不一致的地方。

客户端redirectfunction更为通用,因为它可以将您发送到完全不同的服务器,或者更改协议(例如从HTTP到HTTPS)或两者。 浏览器知道新的URL。 但是在服务器和客户端之间需要额外的来回。

SendRedirect()将search服务器之间的内容。 它很慢,因为它必须通过发送内容的URL来隐藏浏览器。 那么浏览器将在同一台服务器或另一台服务器上为内容创build一个新的请求。

RquestDispatcher用于search我认为在服务器内的内容。 它的服务器端进程,并且比SendRedirect()方法更快。 但是它不会让浏览器在其中search所需date或内容的服务器,也不会要求浏览器更改URL选项卡中的URL。 所以给用户带来一点不方便。

请求分派器是一个接口,用于将Web资源的请求或响应分配给另一个Web资源。 它主要包含两种方法。

  1. request.forward(req,res) :此方法用于将请求从一个Web资源转发到另一个资源。 即从一个servlet到另一个servlet,或者从一个web应用程序到另一个web appliacation。

  2. response.include(req,res) :这个方法用于包含一个servlet对另一个servlet的响应

注意:通过使用请求分派器,我们可以在同一台服务器上转发或包含请求或响应。

request.sendRedirect() :BY使用这个我们可以在不同的服务器之间转发或包含请求。 在这个客户端得到一个暗示,而redirect页面,但在上述过程中,客户端不会得到暗示

如果我们需要将控制转移到不同的领域或实现任务的分离,则应该使用技术上的redirect。

例如在支付应用程序中,我们首先执行PaymentProcess,然后redirect到displayPaymentInfo。 如果客户端刷新浏览器,则只会重新显示displayPaymentInfo,PaymentProcess不会重复。 但是如果我们在这种情况下使用forward,则PaymentProcess和displayPaymentInfo将会被顺序地重新执行,这可能导致数据不稳定。

对于其他场景,转发使用起来比较有效,因为它比sendRedirect更快