IllegalStateException: Cannot forward a response that is already committed

对于初学者来说,一个常见的误解是:当调用 forward() 或者 sendRedirect() 时控制流将会自动跳出原函数。标题所示错误通常是基于此误解而引起的。
示例代码:
protected void doPost() {
    if (someCondition) {
        sendRedirect();
    }
    forward(); // This is STILL invoked when someCondition is true!}
forward() 和 sendRedirect() 与system.exit() 不同,当上例中的 someCondition为true时,很有可能得到此异常:
IllegalStateException: Cannot forward a response that is already committed
为了解决此问题,可以在sendRedirect() / forward() 之后加上 return;
protected void doPost() {
    if (someCondition) {
        sendRedirect();
        return;
    }
    forward();}
    或者把后一个forward() 放入else中
protected void doPost() {
    if (someCondition) {
        sendRedirect();
    }else{
        forward();
    }
}
上文所述是引起该异常的最常见的情况;近日在一个由服务器下载文件函数中避免了上述问题,但仍然出现了此异常。除去冗余部分的函数如下:
public void download(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
          ...
          OutputStream out = response.getOutputStream();
          try {
             ...
             out.write();       
          } catch (Exception e){
               log.error(e.getMessage());
          } finally {
             if (out!=null ){
               out.flush();
               out.close();
          }
          ...
          forward();
   }  
Server端在提交response到Client端之前会向一个缓冲区写入相应头和状态码,然后将内容清空。而一旦缓冲区被清空就标志着该response已被提交(response is committed)。于是在finally块中随着out.flush(),该response已被提交了。原因找到,解决方法同上。

你可能感兴趣的:(java,Servlets)