请求分派机制中的include和forward机制有什么区别?

52

Forward() :这可以通过 Request 和 ServeletContext 两种方式完成。将请求从一个 servlet 转发到服务器上的另一个资源(servlet、JSP 文件或 HTML 文件)。转发是在服务器端完成的,而客户端不知道。

当您调用转发请求时,请求被发送到服务器上的另一个资源,而无需通知客户端另一个资源将处理该请求。此过程完全在 Web 容器中进行。

简单来说:

include:将在当前文件中包含另一个文件

forward:将当前请求转发到转发页面


16
我通过谷歌搜索来到这里。几乎任何问题都可以用“RTFM”或“STFW”来回答,但是StackOverflow对我来说已成为一个绝佳的资源,因为它提供简明扼要的解释和多个角度的可消化大小的信息。我很高兴有人问已经有答案的问题。 - WoodenKitty
2
很少有什么比做谷歌搜索找答案然后找到“你试过叫做谷歌搜索吗?”更恼人的事情了。 - A B
5个回答

72
两个标签的区别在于它们的工作方式。我将举个例子,这样你可以更好地想象它。
假设你有两个页面,pageA和pageB。在pageA中,您编写了include标签。在这种情况下,控制权在调用include标签之前一直在pageA中。此时完全转移到pageB上。完成后,控制权将返回到pageA,从include标签之后的下一个编码点开始,并继续执行pageA的其余部分。
为了让事情更加清晰,让我们假设我们有相同的页面pageA和pageB,但这次我们将在pageA中使用forward标签而不是包含标签。同样,在调用pageA中的forward标记之前,控件将始终在pageA中。此时,控制转移到pageB,就像使用include标记一样。但是区别在于,完成pageB后,控制不会再返回到pageA。

2
解释非常到位。像我这样的初学者肯定需要它。被接受的答案是正确的,但这个例子比被接受的答案更详细和完整。 - user5228393

39
主要区别在于使用forward时,控制转移至下一个被调用的servlet/jsp,而include保持当前servlet的控制权,只包含调用servlet/jsp执行的处理(例如执行任何out.println或其他处理)。

澄清“控制”:使用include时,调用response.sendErrorresponse.sendRedirect对实际响应没有影响。而使用forward则会操作实际响应。 - Yeti

28

include(request, response);

如果资源是静态的,则 include 方法可以实现编程式服务器端包含。如果资源是 Web 组件,则该方法的效果是将请求发送到所包含的 Web 组件,执行 Web 组件,然后将执行结果包含在包含 Servlet 的响应中。

所包含的 Web 组件可以访问请求对象,但在对响应对象进行操作时受到限制。

  • 它可以向响应的正文部分写入内容并提交响应。
  • 它不能设置头信息或调用任何影响响应头的方法,例如 setCookie。

通常,在 Web 组件返回响应时,包含其他 Web 资源(例如横幅内容或版权信息)非常有用。

forward(request, response);

在某些应用程序中,您可能希望一个Web组件对请求进行初步处理,并让另一个组件生成响应。例如,您可能希望部分处理请求,然后根据请求的性质转移到另一个组件。
要将控制权转移到另一个Web组件,需要调用RequestDispatcher的forward方法。当请求被转发时,请求URL将设置为转发页面的路径。原始URI及其组成部分将保存为请求属性。
javax.servlet.forward.[request-uri|context-path|servlet-path|path-info|query-string]  

应该使用forward方法将用户的响应责任交给另一个资源。如果你在servlet中已经访问了ServletOutputStreamPrintWriter对象,则不能使用此方法;这样做会抛出IllegalStateException异常。

相关链接


11

两者之间的主要区别在于forward()方法在被调用后会关闭输出流,而include方法则不会关闭输出流。

举个例子:
假设有一个名为xxx.java的servlet页面和一个名为yy.jsp的jsp页面。

在yy.jsp中:

WELCOME to yy.jsp

在xxx.java中 //使用forward()

RequestDispatcher rd = request.getRequestDispatcher("yy.jsp"); rd.forward(request,response); out.println("back to servlet"); //这不会被显示

输出结果

WELCOME to yy.jsp 

在xxx.java中//使用include()

RequestDispatcher rd = request.getRequestDispatcher("yy.jsp"); rd.include(request,response); out.println("回到servlet");

输出结果

WELCOME to yy.jsp back to servlet

但最重要的是它不关乎控制,因为如果我们在.forward()或者.include()调用之后放置一个

System.out.println("console output");

在这两种情况下控制台输出都会生成。 它关乎对客户端的响应。

所以,基本的部分就是:如果我们正在处理一个服务器端组件并且转发到 JSP 或 Servlet 以生成客户端标记,则一旦该 JSP 或 Servlet 完成处理,我们就不能再调用任何其他组件生成可发送给客户端的标记。一旦我们执行了转发,当前请求和响应周期的标记生成过程就完成了。

相反,使用 include 时,输出流仍然保持打开状态,因此我们可以调用尽可能多的不同文件来生成客户端标记。 我们可以在生成客户端基础标记的组件链中包含两个或三个 JSP 文件甚至是一个 Servlet。当我们使用 include 时,在调用之后输出流不会关闭。


http://www.theserverside.com/tip/Include-vs-Forward-of-the-Servlet-RequestDispatcher? - Preuk

-1

forward()函数将控制权转移到目标资源,目标资源将直接向客户端发送响应。

include()函数将控制权转移到目标资源,目标资源将向源资源发送响应。然后源资源将捕获目标资源的响应并将其转发回客户端。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接