Spring Boot 配置有问题。我在一些应该使用套接字的移动设备上遇到异常:
java.lang.IllegalArgumentException: 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 "<async-supported>true</async-supported>" to servlet and filter declarations in web.xml. Also you must use a Servlet 3.0+ container
at org.springframework.util.Assert.isTrue(Assert.java:65)
at org.springframework.http.server.ServletServerHttpAsyncRequestControl.<init>(ServletServerHttpAsyncRequestControl.java:59)
at org.springframework.http.server.ServletServerHttpRequest.getAsyncRequestControl(ServletServerHttpRequest.java:202)
at org.springframework.web.socket.sockjs.transport.session.AbstractHttpSockJsSession.handleInitialRequest(AbstractHttpSockJsSession.java:202)
at org.springframework.web.socket.sockjs.transport.handler.AbstractHttpSendingTransportHandler.handleRequestInternal(AbstractHttpSendingTransportHandler.java:66)
at org.springframework.web.socket.sockjs.transport.handler.AbstractHttpSendingTransportHandler.handleRequest(AbstractHttpSendingTransportHandler.java:58)
at org.springframework.web.socket.sockjs.transport.TransportHandlingSockJsService.handleTransportRequest(TransportHandlingSockJsService.java:254)
at org.springframework.web.socket.sockjs.support.AbstractSockJsService.handleRequest(AbstractSockJsService.java:322)
at org.springframework.web.socket.sockjs.support.SockJsHttpRequestHandler.handleRequest(SockJsHttpRequestHandler.java:88)
at org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter.handle(HttpRequestHandlerAdapter.java:51)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:938)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:870)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:863)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:646)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
...
正如我从异常中看到的那样,我必须通过将 true 添加到 web.xml 文件来启用异步处理。但这是问题所在,因为我没有它——我们的项目使用 Spring Boot。
有什么方法可以在 Spring Boot 中提供相同的功能吗?
你只需要定义
dispatcherServlet
@Bean
:
@Bean
public ServletRegistrationBean<DispatcherServlet> dispatcherServlet() {
DispatcherServletRegistrationBean registration = new DispatcherServletRegistrationBean(
new DispatcherServlet(), "/");
registration.setAsyncSupported(true);
return registration;
}
它覆盖了
DispatcherServletAutoConfiguration
中的默认值。
也许值得一提的是,Spring Boot 默认为调度程序 servlet 和所有过滤器启用了异步支持
引自github:
我们自动将 async-supported 设置为 true 因为 DispatcherServlet 知道如何处理此类请求,并且 它基本上取决于各个控制器方法来返回一些东西 像一个 DeferredResult。此外,我们还设置异步支持 任何过滤器(通过 getServletFilters 提供)以及设置 每个过滤器的 DispatcherType 都包含 ASYNC。
至少我的实践支持这个说法
即使我迟到了,我也会为后代发布我的工作解决方案。
我遇到了同样的问题并尝试了@Artem Bilan 建议的解决方案。但是调试代码后,我才知道
servletRegistrationBean.isAsyncSupported()
默认是true
.
代码块生成的实际错误来自方法
org.springframework.web.context.request.async.StandardServletAsyncWebRequest.startAsync()
,当getRequest().isAsyncSupported()
为false
时我们会收到此错误。尽管 ServletRegistrationBean#asyncSupported
值为 true
,但对于所有 API 请求,HttpServletRequest#isAsyncSupported()
方法值始终设置为 false
。
代码块摘录代码参考
Assert.state(getRequest().isAsyncSupported(),
"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 \"<async-supported>true</async-supported>\" to servlet and " +
"filter declarations in web.xml.");
进一步分析时,我知道 requestAttributes -> Globals.ASYNC_SUPPORTED_ATTR 决定请求是否必须以异步方式处理。
在正常情况下,请求没有
Globals.ASYNC_SUPPORTED_ATTR
requestAttribute,因此 request.asyncSupported
将为假,如果我们使用过滤器之类的东西手动添加该 requestAttribute ASYNC_SUPPORTED_ATTR
值作为真,那么 request#asyncSupported
值将根据下面的代码块Code Reference设置为
true
specialAttributes.put(Globals.ASYNC_SUPPORTED_ATTR,
new SpecialAttributeAdapter() {
@Override
public Object get(Request request, String name) {
return request.asyncSupported;
}
@Override
public void set(Request request, String name, Object value) {
Boolean oldValue = request.asyncSupported;
request.asyncSupported = (Boolean)value;
request.notifyAttributeAssigned(name, value, oldValue);
}
});
虽然没有明确的答案,但我已经针对这个问题实施了一个解决方法。总结所有需要的变化如下:
request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, true)
@Component
public class AsyncSupportFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, true);
chain.doFilter(request, response);
}
}
@Component
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private AsyncSupportFilter asyncSupportFilter = null;
@Override
public void configure(HttpSecurity httpSecurity) {
httpSecurity.addFilter(asyncSupportFilter);
// we can add the filter before any filter like as httpSecurity.addFilterBefore(asyncSupportFilter , BasicAuthenticationFilter.class);
}
}
我的解决方案:
@WebFilter(value = {"/subscriberinfo/query/single/*"})
public class ...Filter{
}
到
@WebFilter(value = {"/subscriberinfo/query/single/*"}, asyncSupported = true)
public class ...Filter{
}