Spring多线程Scope问题-scopedTarget.requestScopedBean

参考: ‘scopedTarget.requestScopedBean’: Scope ‘request’ is not active for the current thread - 知乎

问题描述

1
2
3
4
5
org.springframework.beans.factory.support.ScopeNotActiveException: 
Error creating bean with name 'scopedTarget.requestScopedBean':
Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException:
No thread-bound request found:
Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.

错误原因:RequestScope的Bean的作用域是限定在当前线程内的,使用多线程开启子线程,子线程是无法获得RequestScope的Bean的值的,所以如果子线程涉及的代码里如果用到父线程中的RequestScope的Bean,就因为这个Bean=null而抛出如上异常。

解决方案

设置上下文到子线程

1
2
3
4
5
6
7
8
9
10
private CompletableFuture<String> testTask() {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
return CompletableFuture.supplyAsync(() -> {
RequestContextHolder.setRequestAttributes(requestAttributes);
return "success";
}).exceptionally(e -> {
log.error("[{}] error occurred: {}", requestScopeBean.getRequestId(), e.getMessage());
return e.getMessage();
});
}