异步请求处理功能必须在 Servlet 容器级别启用。MVC 配置也为异步请求暴露了几个选项。
Servlet Container / Servlet 容器
过滤器和 Servlet 声明有一个 asyncSupported 标志,需要设置为 true 以启用异步请求处理。此外,Filter 映射应该被声明为处理 ASYNC javax.servlet.DispatchType
。
在 Java 配置中,当你使用 AbstractAnnotationConfigDispatcherServletInitializer
来初始化 Servlet 容器时,这将自动完成(这个暂时不知道咋使用的)。
在 web.xml 配置中,你可以在 DispatcherServlet 和 Filter 声明中添加 <async-supported>true</async-supported>
,在 Filter 映射中添加<dispatcher>ASYNC</dispatcher>
。
异步需要在 servlet 容器级别启用异步支持,如果内嵌 Tomcat 的话,以编程方式初始化 DispatcherServlet 的话(下面的方式对应的是 web.xml 中设置的逻辑),可以如下方式开启
package cn.mrcode.study;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletRegistration;
/**
* @author mrcode
*/
public class MyWebApplicationInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) {
// 加载 Spring web application configuration
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(AppConfig.class);
// Manage the lifecycle of the root application context
servletContext.addListener(new ContextLoaderListener(context));
// 创建和注册 DispatcherServlet
DispatcherServlet servlet = new DispatcherServlet(context);
ServletRegistration.Dynamic registration = servletContext.addServlet("app", servlet);
registration.setLoadOnStartup(1);
registration.addMapping("/");
// 启用异步支持
registration.setAsyncSupported(true);
}
}
Spring MVC
MVC 配置暴露了以下与异步请求处理有关的选项:
- Java 配置:使用 WebMvcConfigurer 上的 configureAsyncSupport 回调。
- XML 配置:使用
<mvc:annotation-driven>
下的<async-support>
元素。
你可以配置以下内容:
- 异步请求的 默认超时值,如果没有设置,则取决于底层 Servlet 容器。
- AsyncTaskExecutor:用于在使用反应式类型流时进行阻塞式写入,以及执行从控制器方法返回的可调用实例。如果你使用反应式类型的流媒体或有返回 Callable 的控制器方法,我们强烈建议配置这个属性,因为默认情况下,它是一个 SimpleAsyncTaskExecutor。
- DeferredResultProcessingInterceptor 实现和 CallableProcessingInterceptor 实现。
注意,你也可以在 DeferredResult、ResponseBodyEmitter 和 SseEmitter 上设置默认超时值。对于一个 Callable,你可以使用 WebAsyncTask 来提供一个超时值。