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 out
的 HttpServletResponse
和它的 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
说响应已经提交(关闭流似乎会自动提交响应)。
如果我将 out
和 writer
的初始化移到 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-resources和return语句