try-with-resource vs java.lang.IllegalStateException:提交响应后无法调用 sendError()

Posted

技术标签:

【中文标题】try-with-resource vs java.lang.IllegalStateException:提交响应后无法调用 sendError()【英文标题】:try-with-resource vs java.lang.IllegalStateException: Cannot call sendError() after the response has been committed 【发布时间】:2016-04-01 17:48:00 【问题描述】:

我的 RSS servlet 对 OutputStream outHttpServletResponse 和它的 writer 使用 try-with-resource。在某些情况下,SomeException 在生成 RSS 文档时被抛出,在这种情况下,我需要向客户端返回 HTTP 状态 500:

try (ServletOutputStream out = response.getOutputStream();
     OutputStreamWriter writer = new OutputStreamWriter(out, "utf-8")) 
        response.setContentType("text/xml");

        // Generate RSS here

     catch (SomeException e) 
        response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
        return;
    

但是,在调用 response.sendError() 时,$out$ 已经关闭,我收到 IllegalStateException 说响应已经提交(关闭流似乎会自动提交响应)。

如果我将 outwriter 的初始化移到 try 块之外并在 finally 块中关闭它们(Java7 之前的方式),错误代码会正确发送。

我想知道是否有办法继续使用 try-with-resource 并且在发生异常时仍然能够返回错误代码。

谢谢!

【问题讨论】:

您可以使用 outer try-with-resources 和 inner try-catch... 【参考方案1】:

您不需要关闭不是您自己创建的资源。容器自己创建了底层OutputStream,因此也自己负责正确关闭它。您应该看到容器已经在 servlet 的 doXxx() 方法周围放置了一个 try-with-resources。另见Should I close the servlet outputstream?

换句话说,OutputStream 内部 doXxx() 上的整个 try-with-resources 是不必要的。

只要做:

try 
    // Generate RSS here

    OutputStreamWriter writer = new OutputStreamWriter(response.getOutputStream(), "UTF-8")) 
    response.setContentType("text/xml");

    // Write RSS here.

 catch (SomeException e) 
    response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());


与具体问题无关,如果您将任何已检查的异常重新抛出为ServletException,那么容器也将自行处理正确的响应代码和消息。

try 
    // ...
 catch (SomeException e) 
    throw new ServletException(e);

【讨论】:

以上是关于try-with-resource vs java.lang.IllegalStateException:提交响应后无法调用 sendError()的主要内容,如果未能解决你的问题,请参考以下文章

java try-with-resource语句使用

java中的try-with-resources和return语句

Java 7 使用TWR(Try-with-resources)完成文件copy

java遗珠之try-with-resources

java遗珠之try-with-resources

java 7新特性-TWR(Try-with-resources)