【问题标题】:try-with-resource vs java.lang.IllegalStateException: Cannot call sendError() after the response has been committedtry-with-resource vs java.lang.IllegalStateException:提交响应后无法调用 sendError()
【发布时间】: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...

标签: servlets exception-handling try-with-resources


【解决方案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);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-12-21
    • 2017-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-23
    • 1970-01-01
    • 2014-08-22
    相关资源
    最近更新 更多