我已经在我的 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();
}
On RequestContextHolder.currentRequestAttributes()
,Spring Boot 给我带来了这个异常:
java.lang.IllegalStateException:未找到线程绑定请求:您是指实际 Web 请求之外的请求属性,还是在原始接收线程之外处理请求?如果您实际上在 Web 请求中进行操作并且仍然收到此消息,则您的代码可能在 DispatcherServlet/DispatcherPortlet 之外运行:在这种情况下,请使用 RequestContextListener 或 RequestContextFilter 公开当前请求。
我怎样才能获得当前的HttpServletRequest
在异步方法中?
如果您在方法上使用@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
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)