【问题标题】:Spring boot async: get HttpServletRequest inside async methodSpring Boot async:在异步方法中获取 HttpServletRequest
【发布时间】:2019-05-05 19:59:28
【问题描述】:

我已经在我的 Spring Boot 应用程序中启用了异步功能:

@Configuration
@EnableAsync
public class BackOfficeConfiguration {}

我已经创建了这个异步方法:

@Async
public void importDocuments() {}

importDocuments 代码只是:

@Async
public void importDocuments() {
    // Do something

    // Get current request context
    ServletRequestAttributes requestAttributes = 
        (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
    HttpServletRequest request = requestAttributes.getRequest();
}

RequestContextHolder.currentRequestAttributes() 上,spring boot 让我遇到了这个异常:

java.lang.IllegalStateException:未找到线程绑定请求:您是指实际 Web 请求之外的请求属性,还是在原始接收线程之外处理请求?如果您实际上是在 Web 请求中操作并且仍然收到此消息,则您的代码可能在 DispatcherServlet/DispatcherPortlet 之外运行:在这种情况下,请使用 RequestContextListener 或 RequestContextFilter 来公开当前请求。

如何在异步方法中获取当前的HttpServletRequest

【问题讨论】:

  • 不要。将所需的对象/数据传递到方法中,或者为您的 Web 层使用适当的异步。

标签: spring spring-boot


【解决方案1】:

如果您在一个方法上使用@Async,这意味着该方法会抛出另一个新线程(单独的一个)。这意味着,它与您当前的请求无关。 (这是两条路)。如果您想从请求中获取一些数据,您必须从请求中获取您想要的数据并将其保留为副本。因为,完成后请求数据将被删除。如果您在那里传递了引用,则在访问 No thread-bound request found 之类的数据时会出现错误。您必须创建一个 Cloneable 对象并将数据填充到该对象中并在调用 Async 方法之前获取一个克隆,并通过传递该对象来调用 Async 方法。然后你有一个数据的副本,你可以在你的新线程中使用它(@Async 方法)。如下所示的 Cloneable 类。

public class CloneableClass implements Cloneable {
    //
    private ServletRequestAttributes requestAttributes;
    //getters
    //setters

    @Override
    public CloneableClass  clone() {
        try {
            CloneableClass clone = (CloneableClass) super.clone();
            return clone;
        } catch (CloneNotSupportedException e) {
            throw new AssertionError();
        }
    }

}

阅读更多https://docs.oracle.com/javase/8/docs/api/java/lang/Cloneable.html

【讨论】:

    猜你喜欢
    • 2023-03-28
    • 1970-01-01
    • 2015-12-10
    • 1970-01-01
    • 1970-01-01
    • 2020-01-13
    • 1970-01-01
    • 2020-09-15
    • 1970-01-01
    相关资源
    最近更新 更多