IllegalStateException:必须在servlet和所有过滤器上启用异步支持

问题描述 投票:1回答:2

我正在尝试在控制器中使用返回类型Callable以便在处理请求时释放servlet线程,但是当在开发环境中部署spring boot应用程序时,我收到以下错误:

org.springframework.web.util.NestedServletException:请求处理失败;嵌套异常是java.lang.IllegalStateException:必须在servlet和异步请求处理中涉及的所有过滤器上启用异步支持。这是使用Servlet API在Java代码中完成的,或者通过在web.xml中向servlet和过滤器声明添加\“true \”来完成。

注意:我已经阅读了几篇关于此错误的帖子,但没有一个解决了我的问题。

我所拥有的特定行为是本地一切都按预期工作:释放servlet线程并在带外处理请求以最终返回到客户端所需的响应。

但是,如前所述,当应用程序部署在开发环境中时,事情就无法按预期工作。

在本地测试时,我检查了servlet / filters是否支持异步;调试时要做的只是在ApplicationFilterChain的给定过滤器中放置一个断点,然后检查整个链。在那里,我可以检查servlet属性(我在其中看到asyncSupported on true)以及链中包含的每个过滤器(我逐个检查它们;所有这些都设置为asyncSupported为true)。

我还有一个自定义JwtAuthenticationFilter,它从AbstractAuthenticationProcessingFilter扩展,作为身份验证阶段的一部分,所以我也在这样的过滤器中放置一个断点并检查链。在那里,我看到原始链接(之前评论过的ApplicationFilterChain)和“additionalFilters”集合,其中出现了我的JwtAuthenticationFilter以及弹簧安全过滤器。但是它们都没有asyncSupported属性,所以我假设它们不是开发服务器抛出的错误的一部分。请注意,正如我在本地提到的,一切正常;部署到开发服务器时出现错误。

控制器方法:

  @GetMapping(path = "/export")
  public Callable<ResponseEntity> exportData() throws IOException {
    return new CustomContextAwareCallable(() -> handleResponse());
  }

所以我的问题是:即使ApplicationFilterChain上的每个过滤器和servlet都具有asyncSupported为true,为什么我在部署后会从服务器收到上面显示的错误?

该应用程序未在服务器上部署为.WAR,它只是使用嵌入式tomcat(我在本地做同样的事情)。

更新:另一个区别是在开发环境中客户端请求通过nginx代理(只是想知道是否由于某种原因,请求属性org.apache.catalina.ASYNC_SUPPORTED可能被修改为假(本地它是真的)。

有任何想法吗?

spring spring-mvc servlet-filters callable
2个回答
1
投票

我通过向当前请求添加async支持属性找到了一种解决方法,如:

  @GetMapping(path = "/export")
  public Callable<ResponseEntity> exportData(HttpServletRequest request) throws IOException {
    request.setAttribute(org.apache.catalina.Globals.ASYNC_SUPPORTED_ATTR, true);
    return new CustomContextAwareCallable(() -> handleResponse());
  }

由于所有过滤器都与我正在使用的dispatchServlet一起被异步支持(如原始问题所述),似乎在开发环境中部署时,以下某些tomcat阀门正在为请求设置此类属性为false:

  • StandardEngineValve
  • StandardHostValve
  • StandardContextValve

我验证了我在本地使用的嵌入式tomcat版本,它与开发环境相同:Apache Tomcat/8.5.23

似乎我之前显示的错误:

org.springframework.web.util.NestedServletException:请求处理失败;嵌套异常是java.lang.IllegalStateException:必须在servlet和异步请求处理中涉及的所有过滤器上启用异步支持。这是使用Servlet API在Java代码中完成的,或者通过在web.xml中向servlet和过滤器声明添加\“true \”来完成。

并不像它描述的那样专门绑定到servlet和过滤器,因为任何列出的tomcat阀门最终都可能不允许异步支持请求。

目前我没有足够的细节知道为什么会发生这种情况(有可能在开发环境中远程调试这个以查看每个tomcat阀门如何处理请求)。


0
投票

对于那些有Filter实现的人。您可以在request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, true)回调中执行相同操作,而不是将Controller设置为doFilter()中的每个请求。这就是我在Kotlin中的表现:

import org.apache.catalina.Globals
import javax.servlet.Filter
import javax.servlet.FilterChain
import javax.servlet.ServletRequest
import javax.servlet.ServletResponse
import javax.servlet.annotation.WebFilter
import javax.servlet.http.HttpServletResponse

@Suppress("unused")
@WebFilter(urlPatterns = ["/v1/*"])
class RequestResponseFilter : Filter {

    override fun doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain) {
        request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, true)
        val httpServletResponse = response as HttpServletResponse
        httpServletResponse.setHeader("Cache-Control", "max-age=60")
        chain.doFilter(request, response)
    }

}
© www.soinside.com 2019 - 2024. All rights reserved.