RequestDispatcher - 响应何时被提交?

7

我正在学习RequestDispatcher,编写一些基本代码。当调用rd.forward()时,控制权(和响应处理)将转发到路径中命名的资源,这里是另一个servlet。但为什么这段代码不会因为之前的out.write()语句而抛出IllegalStateException(虽然我并不想要这个异常)?

我猜我真正想问的是,这些out.write()语句何时或如何被提交?

谢谢, Jeff

public class Dispatcher extends HttpServlet{
  public void doGet(HttpServletRequest request, HttpServletResponse response)
           throws IOException, ServletException{

    response.setContentType("text/plain");
    PrintWriter out = response.getWriter();
    out.write("In Dispatcher\n");

    String modeParam = request.getParameter("mode");
    String path = "/Receiver/pathInfo?fruit=orange";
    RequestDispatcher rd = request.getRequestDispatcher(path);
    if(rd == null){
        out.write("Request Dispatcher is null. Please check path.");
    }
        if(modeParam.equals("forward")){
            out.write("forwarding...\n");
            rd.forward(request, response);
        }
        else if(modeParam.equals("include")){
            out.write("including...\n");
            rd.include(request, response);
        }
    out.flush();
    out.close();
}

}

3个回答

4
因为您没有调用flush方法。
如果您没有刷新缓冲区,一切都将在转发之前被清除。否则,您将得到一个预期之外的异常。
正如文档中所述: 对于通过getRequestDispatcher()获取的RequestDispatcher,ServletRequest对象的路径元素和参数将被调整以匹配目标资源的路径。 在响应已提交给客户端之前(在响应正文输出被刷新之前),应该调用forward方法。如果响应已经提交,此方法将抛出IllegalStateException异常。在转发之前,响应缓冲区中未提交的输出会自动清除。

3
阅读文档

PrintWriter上调用flush()会提交响应。

现在,根据您的好奇心,为什么不会抛出IllegalStateException。这是因为PrintWriter.flush()不会抛出此或任何已检查异常。而且,我们知道在调用rd.forward()时响应尚未提交,因为flush()在该方法中稍后出现。

那么,如果我将代码结尾修改如下,为什么不会抛出异常: `out.flush(); out.write("exception code?"); out.close();` - Jeff Levine
2
如果在调用forward方法之前调用了flush,则会抛出异常。 - Tala
没错,谢谢,Tala。别忘了一切都已经清楚了,当它被转发时。看,Tala的帖子。 - Adeel Ansari

1

在转发之前,您没有调用flush()。因此不会显示任何异常。如果在请求转发之前编写flush(),则会抛出异常。

当我们调用flush()时,缓冲区中的所有内容都将发送到浏览器并清除缓冲区。

在以下情况下,我们将收到异常。

response.getWriter().print('hello...');  
response.getWriter().flush();  
request.getRequestDispatcher("/index.").forward(request, response);

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