Spring MVC 的 Servlet 3 异步支持不起作用

Servlet 3 Async support with Spring MVC doesn't work

我正在尝试从服务器的文件系统流式传输视频。我正在使用 Spring 中的 StreamingResponseBody 作为响应返回。所以我必须异步处理流媒体。 我对如何配置我的 web.xml 和 Spring MVC 做了很多研究,我遵循了这个简单的教程:http://shengwangi.blogspot.de/2015/09/asynchronous-spring-mvc-hello-world.html 但不幸的是没有成功! 尽管我认为我做的一切都是正确的,但我仍然收到异常告诉我 "Async support must be enabled on a servlet and for all filters involved in async request processing. This is done in Java code using the Servlet API or by adding "true" to servlet and filter declarations in web.xml"。 这是我在 web.xml

中的 servlet 配置
<servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/mvc-config.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
        <async-supported>true</async-supported>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/application-context.xml</param-value>
    </context-param>
    <context-param>
        <param-name>spring.profiles.active</param-name>
        <param-value>production</param-value>
    </context-param>
    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>ASYNC</dispatcher>
    </filter-mapping>
    <filter>
        <display-name>springSecurityFilterChain</display-name>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>ASYNC</dispatcher>
    </filter-mapping>

Spring MVC 配置的代码片段:

<mvc:annotation-driven>
    <mvc:async-support default-timeout="30000"  task-executor="taskExecutor">
    </mvc:async-support>
</mvc:annotation-driven>
<bean id="taskExecutor"
        class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
    <property name="corePoolSize" value="5" />
    <property name="maxPoolSize" value="50" />
    <property name="queueCapacity" value="10" />
    <property name="keepAliveSeconds" value="120" />
</bean>

这是请求处理程序:

@GetMapping("/videos/play")
    public StreamingResponseBody stream(@RequestParam("code") String code, @RequestParam("locale") String locale) throws FileNotFoundException{
        File video = videoService.getVideo(code, locale);
        final InputStream videoInputStream = new FileInputStream(video);
        return (outputStream) -> {
            copyToStream(videoInputStream, outputStream);
        };
    }
private void copyToStream(final InputStream is, OutputStream os)
            throws IOException {
        byte[] data = new byte[2048];
        int read = 0;
        while ((read = is.read(data)) > 0) {
            os.write(data, 0, read);
        }
        os.flush();
    }

感谢任何帮助,因为 3 天前我还在苦苦挣扎! 我正在使用 Tomcat8.0 和 Spring 4.3.6

我读了很多线程,表明它是 Tomcat 7 或 8 中的错误,但它并没有't.The 异常清楚地表明必须在所有过滤器中启用异步支持。因为我尝试这样做,但问题是我如何向 web.xml 文件中的过滤器添加异步支持。 我所做的是以下

<filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>ASYNC</dispatcher>
</filter-mapping>

这实际上表明映射接受异步请求(我猜),但它并未在过滤器本身中启用异步支持。 所以在每个过滤器定义中我们应该启用异步支持,所以 springSecurityFilterChain 定义变成:

<filter>
    <display-name>springSecurityFilterChain</display-name>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <async-supported>true</async-supported>
</filter>