Spring Async DeferredResult在Tomcat 8中不起作用 [英] Spring Async DeferredResult Not Working in Tomcat 8

查看:169
本文介绍了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来管理异步请求。知道我错过了什么吗?因为完全相同的Java代码在Jetty中运行良好,所以它可能是一些Tomcat设置或web.xml中的某些东西。

I created an async MVC application using Spring 4.0.5 and Servlet API 3.1.0. The async behavior works well in Jetty 8.0 using Firefox 24 but I cannot get it to work in Tomcat 8.0 and Firefox 24. I'm using DeferredResult to manage the async requests. Any idea what I'm missing? It mus be some Tomcat setting or something in the web.xml since the exact same Java code works well in Jetty.

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

When the async request finally has result and supposedly writes to the response, I see the following messages logged:

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日志中看到这个超时错误:

The long running request never comes back to my browser, and eventually i see this timeoutout error in the Tomcat log:


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


- 服务器.xml -

--server.xml--

    <Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol" 
        maxConnections="100"
               maxThreads="100"
               connectionTimeout="150000" 
               asyncTimeout="150000" />

- Tomcat web.xml -

--Tomcat web.xml--

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
  version="3.1">

    <servlet>
        <servlet-name>default</servlet-name>
        <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
        <init-param>
            <param-name>debug</param-name>
            <param-value>0</param-value>
        </init-param>
        <init-param>
            <param-name>listings</param-name>
            <param-value>false</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
        <async-supported>true</async-supported>
    </servlet>

    <servlet>
        <servlet-name>jsp</servlet-name>
        <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
        <init-param>
            <param-name>fork</param-name>
            <param-value>false</param-value>
        </init-param>
        <init-param>
            <param-name>xpoweredBy</param-name>
            <param-value>false</param-value>
        </init-param>
        <load-on-startup>3</load-on-startup>
        <async-supported>true</async-supported>
    </servlet>  


    <!-- The mapping for the default servlet -->
    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <!-- The mappings for the JSP servlet -->
    <servlet-mapping>
        <servlet-name>jsp</servlet-name>
        <url-pattern>*.jsp</url-pattern>
        <url-pattern>*.jspx</url-pattern>
    </servlet-mapping>    
</web-app>

- Spring web-app web.xml -

--Spring web-app web.xml--

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
  version="3.1">    

    <!-- Creates the Spring Container shared by all Servlets and Filters -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <context-param>
        <param-name>webAppRootKey</param-name>
        <param-value>my-async-app</param-value>
    </context-param>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/app-config.xml</param-value>
    </context-param>

    <!-- Handles all requests into the application -->
    <servlet>
        <servlet-name>app</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring/controllers-config.xml</param-value> 
        </init-param>
        <load-on-startup>1</load-on-startup>
        <async-supported>true</async-supported>
    </servlet>

    <!-- Maps all /app requests to the DispatcherServlet for handling -->
    <servlet-mapping>
        <servlet-name>app</servlet-name>
        <url-pattern>/app/*</url-pattern>
    </servlet-mapping>
</web-app>


推荐答案

此问题与Tomcat描述的错误有关< a href =https://issues.apache.org/bugzilla/show_bug.cgi?id=55331\"rel =nofollow>这里,此处这里

This issue is related to a bug in Tomcat described here, here and here.

可能的解决方案:


  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);
        }
    }
}


这篇关于Spring Async DeferredResult在Tomcat 8中不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆