1

有人请帮助我。

 private void forward(String address,
                    HttpServletRequest  request,
                    HttpServletResponse response)
                        throws ServletException, IOException{
    getServletContext()
        .getRequestDispatcher("/" + address)
        .forward(request, response);
}
private void include(String address,
                    HttpServletRequest  request,
                    HttpServletResponse response)
                        throws ServletException, IOException{
    getServletContext()
        .getRequestDispatcher("/" + address)
        .include(request, response);
}

这两个函数已经写在我项目的每个 servlet 中,问题是当我第一次在 servlet 中使用这两个函数时 include("servlet/abc",request.response); 在它使用了 forward("servlet/def",request.response); 所以使用Netbeans 7我一步一步地观察到转发不是转发servlet的控制但是当我在转发之前不使用include时转发它的控制。

所以我想知道它为什么会发生,原因是什么,以及在包含任何 servlet 之后我该怎么做。

请有人帮助我……这是一个有趣的问题。

include("servlet/abc",request, response);


forward("servlet/def",request, response);   //HERE IS PROBLEM NOT FORWRDING AFTER INCLUDE
4

3 回答 3

7

无论您似乎观察到这种行为的确切原因,您所尝试的都不会奏效。根据RequestDispatcher.forward()的约定,“如果响应已经提交,则此方法会抛出 IllegalStateException”,并且“响应缓冲区中未提交的输出在转发之前会自动清除。”

因此,无论转发成功与否,您都无法在转发之前和之后成功地将内容发送回用户。这是因为转发的目的是允许“一个 servlet 对请求进行初步处理,另一个资源生成响应”,而不是让两个不同的 servlet 生成响应的不同部分。在 Servlet 模型中,生成响应始终只属于一个 servlet。

如果您不知道“已提交”和“未提交”是什么意思,则指的是响应状态和标头是否已发送给用户。当您编写响应时,实际上是在写入本地缓冲区。不会立即发送任何内容。只要您编写的所有内容仍然是本地的,您就可以自由地做任何事情,包括重置缓冲区和重新开始,就像前锋一样,但是一旦发送了某些内容,您就已经承诺并且不能再改变你要做什么。响应可以通过几种方式提交(即全部或部分发送给用户),包括填充缓冲区以便必须发送它以腾出空间容纳更多内容,手动,或刷新响应的WriterOutputStream

最终,在您的情况下可能发生的事情是您正在使用包含编写一些东西,并且它导致响应被提交,或者是因为您已经填充了缓冲区,或者因为我似乎记得包含通常会导致自动冲洗(不确定有关此文档的文档)。然后,当您尝试转发时,它会抛出所需的 IllegalStateException,您可能应该在日志中的某个地方看到它,但不会导致典型的 500 响应状态,因为正如我所讨论的,您已经提交了一些其他状态代码。

于 2012-12-30T06:29:15.713 回答
2

提交响应后,您无法更改响应状态或状态。当您使用请求调度程序包含某些页面时,您实际上是在提交响应并且数据开始发送到客户端。之后,您将无法将响应状态更改为重定向所需的 302。

java.lang.IllegalStateException: Cannot forward after response has been committed如果你尝试这样做,你会得到一个错误。

于 2012-12-30T05:01:45.400 回答
0

RequestDispatcher 只有两种方法:

public interface javax.servlet.RequestDispatcher {
  public abstract void forward(javax.servlet.ServletRequest, javax.servlet.ServletResponse) throws javax.servlet.ServletException, java.io.IOException;
  public abstract void include(javax.servlet.ServletRequest, javax.servlet.ServletResponse) throws javax.servlet.ServletException, java.io.IOException;
}

你给它作为

include("servlet/abc",request, response);
forward("servlet/def",request, response);

但是在 API 中只提到了 servlet 请求对象和响应对象作为参数,所以我想你应该从那里删除你的 url。如果我错了,请纠正我,因为我也在学习。

于 2013-09-25T20:26:47.240 回答