Spring webflux 在SpringWebFlux弹性线程中获取请求对象

Spring webflux 在SpringWebFlux弹性线程中获取请求对象,spring-webflux,requestcontext,Spring Webflux,Requestcontext,我面临一个问题。 我正在使用SpringWebFlux并行调用一些API。如果任何子线程面临任何问题,它需要记录请求。现在的问题是,要记录一个普通的POJO类,其中有一个静态方法,该方法通过ApplicationContent获取bean并将数据存储在队列中 现在的问题是,我想访问请求参数,如请求URL/控制器等。 我试过了 但在本例中,sra为空。我尝试添加以下代码 @Configuration public class InheritableRequestContextListener ex

我面临一个问题。 我正在使用SpringWebFlux并行调用一些API。如果任何子线程面临任何问题,它需要记录请求。现在的问题是,要记录一个普通的POJO类,其中有一个静态方法,该方法通过ApplicationContent获取bean并将数据存储在队列中

现在的问题是,我想访问请求参数,如请求URL/控制器等。 我试过了

但在本例中,sra为空。我尝试添加以下代码

@Configuration
public class InheritableRequestContextListener extends RequestContextListener {
    private static final String REQUEST_ATTRIBUTES_ATTRIBUTE =
        InheritableRequestContextListener.class.getName() + ".REQUEST_ATTRIBUTES";

    @Override
    public void requestInitialized(ServletRequestEvent requestEvent) {
        System.out.println("111111111111111111");
        if (!(requestEvent.getServletRequest() instanceof HttpServletRequest)) {
            throw new IllegalArgumentException(
                    "Request is not an HttpServletRequest: " + requestEvent.getServletRequest());
        }
        HttpServletRequest request = (HttpServletRequest) requestEvent.getServletRequest();
        ServletRequestAttributes attributes = new ServletRequestAttributes(request);
        request.setAttribute(REQUEST_ATTRIBUTES_ATTRIBUTE, attributes);
        LocaleContextHolder.setLocale(request.getLocale());
        RequestContextHolder.setRequestAttributes(attributes, true);
    }
}

但这没有帮助。有人能帮忙吗。我使用的是springboot版本2.0.2.发布版

关于您的实现不起作用的原因有几个

Webflux是线程无关的,这意味着任何线程都可以在应用程序中随时处理任何事情。如果应用程序发现切换当前正在执行的线程是无效的,它将这样做

另一方面,Servlet应用程序为每个请求分配一个线程,并在整个执行过程中坚持该线程

ApplicationContext使用可以看到的ServletRequests,因此在Webflux应用程序中不可用。它反过来使用threadlocal将请求对象存储到指定的线程

在webflux中,您不能使用threadlocal,一旦应用程序切换线程,threadlocal中的所有内容都将消失。这就是为什么你得到空值

那么如何在线程之间传递数据呢

您需要做的是实现一个过滤器,该过滤器拦截请求,提取您想要的信息,并将其放置在反应上下文对象中

这里有一篇文章解决了这个问题


有几个原因可以解释为什么您的实现不起作用

Webflux是线程无关的,这意味着任何线程都可以在应用程序中随时处理任何事情。如果应用程序发现切换当前正在执行的线程是无效的,它将这样做

另一方面,Servlet应用程序为每个请求分配一个线程,并在整个执行过程中坚持该线程

ApplicationContext使用可以看到的ServletRequests,因此在Webflux应用程序中不可用。它反过来使用threadlocal将请求对象存储到指定的线程

在webflux中,您不能使用threadlocal,一旦应用程序切换线程,threadlocal中的所有内容都将消失。这就是为什么你得到空值

那么如何在线程之间传递数据呢

您需要做的是实现一个过滤器,该过滤器拦截请求,提取您想要的信息,并将其放置在反应上下文对象中

这里有一篇文章解决了这个问题


我明白你的意思。我试过了,但没有成功。获取错误,上下文为空。你能发布一些演示代码来展示上面的东西是如何工作的吗?用你尝试过的东西更新你的代码,或者问一个包含上下文代码的新问题,指出什么不起作用。我明白你的意思了。我试过了,但没有成功。获取错误,上下文为空。你可以发布一些演示代码来展示上面的东西是如何工作的吗?用你尝试过的更新你的代码,或者问一个新问题,其中包含你的上下文代码,指出什么不起作用。
@Configuration
public class InheritableRequestContextListener extends RequestContextListener {
    private static final String REQUEST_ATTRIBUTES_ATTRIBUTE =
        InheritableRequestContextListener.class.getName() + ".REQUEST_ATTRIBUTES";

    @Override
    public void requestInitialized(ServletRequestEvent requestEvent) {
        System.out.println("111111111111111111");
        if (!(requestEvent.getServletRequest() instanceof HttpServletRequest)) {
            throw new IllegalArgumentException(
                    "Request is not an HttpServletRequest: " + requestEvent.getServletRequest());
        }
        HttpServletRequest request = (HttpServletRequest) requestEvent.getServletRequest();
        ServletRequestAttributes attributes = new ServletRequestAttributes(request);
        request.setAttribute(REQUEST_ATTRIBUTES_ATTRIBUTE, attributes);
        LocaleContextHolder.setLocale(request.getLocale());
        RequestContextHolder.setRequestAttributes(attributes, true);
    }
}