Spring Async DeferredResult在Tomcat 8中不起作用

我使用Spring 4.0.5和Servlet API 3.1.0创建了一个异步MVC应用程序。 使用Firefox 24,异步行为在Jetty 8.0中运行良好,但我无法在Tomcat 8.0和Firefox 24中使用它。我正在使用DeferredResult来管理异步请求。 知道我错过了什么吗? 它可能是一些Tomcat设置或web.xml中的某些内容,因为完全相同的Java代码在Jetty中运行良好。

当异步请求最终有结果并且应该写入响应时,我看到记录了以下消息:

WebAsyncManager - Dispatching request to resume processing RequestResponseBodyMethodProcessor - Written [true] as "application/json" using MappingJacksonHttpMessageConvertor DispatcherServlet - Null ModelAndView returned to DispatcherServlet with name 'app': assuming HandlerAdapter completed request handling DispatcherServlet - Successfully completed request 

长时间运行的请求永远不会回到我的浏览器,最终我在Tomcat日志中看到这个超时错误:

 CoyoteAdapter.asyncDispatch Exception while processing an asynchronous request java.lang.IllegalStateException: Calling [asyncTimeout()] is not valid for a request with Async state [Dispatching] 

–server.xml–

   

–Tomcat web.xml–

    default org.apache.catalina.servlets.DefaultServlet  debug 0   listings false  1 true   jsp org.apache.jasper.servlet.JspServlet  fork false   xpoweredBy false  3 true    default /    jsp *.jsp *.jspx   

–Spring web-app web.xml–

     org.springframework.web.context.ContextLoaderListener   webAppRootKey my-async-app   contextConfigLocation classpath:spring/app-config.xml    app org.springframework.web.servlet.DispatcherServlet  contextConfigLocation classpath:spring/controllers-config.xml  1 true    app /app/*   

此问题与此处和此处描述的Tomcat中的错误有关。

可能的解决方案:

  1. 使用更稳定的Tomcat版本,例如已修复此错误的Tomcat 7.0.47。
  2. 使用更高级的调度程序,例如org.springframework.web.servlet.DispatcherServlet
  3. 按照此处的建议覆盖HttpServlet:

     public class AsyncServlet extends HttpServlet { protected void doGet(final HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { if (request.isAsyncStarted()) { response.getWriter().write("asyncResult=" + request.getAttribute("asyncResult")); } else { final AsyncContext asyncContext = request.startAsync(request, response); asyncContext.addListener(new AsyncListener() { public void onTimeout(AsyncEvent event) throws IOException { request.setAttribute("asyncResult", "timeout\n"); asyncContext.dispatch(); } public void onStartAsync(AsyncEvent event) throws IOException { } public void onError(AsyncEvent event) throws IOException { } public void onComplete(AsyncEvent event) throws IOException { } }); asyncContext.setTimeout(5000L); } } }