java获取HttpServletRequest状态以避免IllegalStateException
有时来自HttpServletRequest
的方法req.startAsync()
抛出一个IllegalStateException
(响应已经关闭)
如何检查请求状态以避免IllegalStateException
req.isAsyncSupported()
始终返回true
相关代码:
final HttpSession httpSession = req.getSession(false);
if (httpSession == null) {
resp.sendError(HttpServletResponse.SC_PRECONDITION_FAILED);
return;
}
final AsyncContext asynContext = req.startAsync(); //exception here`
例外情况:
12:28:12,735 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/esus].[LongPollServlet]] (http-/0.0.0.0:8080-2) JBWEB000236: Servlet.service() for servlet LongPollServlet threw exception: java.lang.IllegalStateException: JBWEB000049: Response has been closed already at org.apache.catalina.connector.Request.startAsync(Request.java:3180) [jbossweb-7.2.0.Final-redhat-1.jar:7.2.0.Final-redhat-1] at org.apache.catalina.connector.Request.startAsync(Request.java:3170) [jbossweb-7.2.0.Final-redhat-1.jar:7.2.0.Final-redhat-1] at org.apache.catalina.connector.RequestFacade.startAsync(RequestFacade.java:925) [jbossweb-7.2.0.Final-redhat-1.jar:7.2.0.Final-redhat-1] at com.performer.framework.server.LongPollServlet.continueDoPost(LongPollServlet.java:75) [st10.framework.webserver.jar:] at com.performer.framework.server.LongPollServlet.doPost(LongPollServlet.java:62) [st10.framework.webserver.jar:] at javax.servlet.http.HttpServlet.service(HttpServlet.java:754) [jboss-servlet-api_3.0_spec-1.0.2.Final-redhat-1.jar:1.0.2.Final-redhat-1] at javax.servlet.http.HttpServlet.service(HttpServlet.java:847) [jboss-servlet-api_3.0_spec-1.0.2.Final-redhat-1.jar:1.0.2.Final-redhat-1] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:295) [jbossweb-7.2.0.Final-redhat-1.jar:7.2.0.Final-redhat-1] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214) [jbossweb-7.2.0.Final-redhat-1.jar:7.2.0.Final-redhat-1] at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230) [jbossweb-7.2.0.Final-redhat-1.jar:7.2.0.Final-redhat-1] at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:149) [jbossweb-7.2.0.Final-redhat-1.jar:7.2.0.Final-redhat-1] at org.jboss.as.jpa.interceptor.WebNonTxEmCloserValve.invoke(WebNonTxEmCloserValve.java:50) [jboss-as-jpa-7.2.0.Final-redhat-8.jar:7.2.0.Final-redhat-8] at org.jboss.as.jpa.interceptor.WebNonTxEmCloserValve.invoke(WebNonTxEmCloserValve.java:50) [jboss-as-jpa-7.2.0.Final-redhat-8.jar:7.2.0.Final-redhat-8] at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:169) [jboss-as-web-7.2.0.Final-redhat-8.jar:7.2.0.Final-redhat-8] at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:145) [jbossweb-7.2.0.Final-redhat-1.jar:7.2.0.Final-redhat-1] at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:97) [jbossweb-7.2.0.Final-redhat-1.jar:7.2.0.Final-redhat-1] at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:102) [jbossweb-7.2.0.Final-redhat-1.jar:7.2.0.Final-redhat-1] at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:336) [jbossweb-7.2.0.Final-redhat-1.jar:7.2.0.Final-redhat-1] at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:856) [jbossweb-7.2.0.Final-redhat-1.jar:7.2.0.Final-redhat-1] at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:653) [jbossweb-7.2.0.Final-redhat-1.jar:7.2.0.Final-redhat-1] at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:915) [jbossweb-7.2.0.Final-redhat-1.jar:7.2.0.Final-redhat-1] at java.lang.Thread.run(Unknown Source) [rt.jar:1.6.0_34]
# 1 楼答案
根据startAsync()的文件:
Tomcat似乎将
isAsyncSupported()
设置为true
可以通过以下方式将
HttpServletRequest
对象中的async属性设置为true
:或者
您还必须在servlet前面添加:
# 2 楼答案
您希望检查响应,而不是请求状态,因为原始响应关闭时无法调用
startAsync()
您应该能够从代码中看到is关闭响应的位置(例如,如果它在某处调用
response.close();
)。您应该在这一点之前调用startAsync()
,或者在调用startAsync()
之前设置一个标志并检查它如果根本不处理响应,可以尝试测试
HttpServletResponse
,看看它是否已关闭,但没有明确的方法:有关
isClosed()
实现的讨论,请参见this answer。没有简单或推荐的方法,但如果您正在进行desparate,这可能会起作用(未经测试),但它会写入响应输出流,这很危险:或者,您也可以依赖
response.isCommitted()
(see doc),因为提交的响应通常是关闭的,但这并不确定——它可以关闭,但不能提交