try-with-resource vs java.lang.IllegalStateException:提交响应后无法调用 sendError()
try-with-resource vs java.lang.IllegalStateException: Cannot call sendError() after the response has been committed
我的 RSS servlet 将 try-with-resource 用于 HttpServletResponse
的 OutputStream out
及其编写器。在某些情况下,生成 RSS 文档时会抛出 SomeException
,在这种情况下,我需要 return 向客户端发送 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
说响应已经提交(关闭流似乎提交自动响应)。
如果我将 out
和 writer
的初始化移动到 try 块之外,并在 finally 块中关闭它们(pre-Java7 方式),错误代码已正确发送。
我想知道是否有一种方法可以继续使用 try-with-resource 并在出现异常时仍然能够 return 错误代码。
谢谢!
您不需要关闭不是您自己创建的资源。容器自行创建底层 OutputStream
,因此也自行负责正确关闭它。您应该想象容器已经在 servlet 的 doXxx()
方法周围放置了一个 try-with-resources。另见 Should I close the servlet outputstream?
换句话说,doXxx()
内 OutputStream
上的整个 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);
}
我的 RSS servlet 将 try-with-resource 用于 HttpServletResponse
的 OutputStream out
及其编写器。在某些情况下,生成 RSS 文档时会抛出 SomeException
,在这种情况下,我需要 return 向客户端发送 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
说响应已经提交(关闭流似乎提交自动响应)。
如果我将 out
和 writer
的初始化移动到 try 块之外,并在 finally 块中关闭它们(pre-Java7 方式),错误代码已正确发送。
我想知道是否有一种方法可以继续使用 try-with-resource 并在出现异常时仍然能够 return 错误代码。
谢谢!
您不需要关闭不是您自己创建的资源。容器自行创建底层 OutputStream
,因此也自行负责正确关闭它。您应该想象容器已经在 servlet 的 doXxx()
方法周围放置了一个 try-with-resources。另见 Should I close the servlet outputstream?
换句话说,doXxx()
内 OutputStream
上的整个 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);
}