Java/Spring MVC:向子线程提供请求上下文 [英] Java/Spring MVC: provide request context to child threads
问题描述
我有一个问题,我想将Spring WebMVC应用程序的某些进程外包到单独的线程中.这很容易并且有效,直到我想使用使用全局请求的类userRightService为止.这在线程中不可用,我们遇到了一个问题,这几乎是可以理解的.
I have the Problem, that I want to outsource some processes of my Spring WebMVC application into separate Threads. That was easy enough and works, until I want to use a class, userRightService, which uses the global request. That's not available in the threads, and we get a problem, that's pretty much understandable.
这是我的错误:
java.lang.RuntimeException:
org.springframework.beans.factory.BeanCreationException: Error creating bean
with name 'scopedTarget.userRightsService': 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: Cannot ask for request attribute -
request is not active anymore!
好的,足够清楚.我正在尝试通过实施以下解决方案来保留请求上下文:
Okay, clear enough. I am trying to keep the request context by implementing this solution:
这是我的可运行类:
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class myThread implements Runnable {
private RequestAttributes context;
public DataExportThread(RequestAttributes context) {
this.context = context;
}
public void run() {
RequestContextHolder.setRequestAttributes(context);
产生它的地方:
final DataExportThread dataExportThread =
new myThread(RequestContextHolder.currentRequestAttributes());
final Thread thread = new Thread(myThread);
thread.setUncaughtExceptionHandler((t, e) -> {...});
thread.start();
据我了解,我们将currentRequestAttributes存储在线程中,然后在运行时将其还原为currentRequestAttributes ...对我来说听起来很可靠,但错误仍然存在.我认为在为我的案例调整解决方案时犯了一些错误.也许有人可以帮助我找到错误.
As far as I understood, we store the currentRequestAttributes in the thread and then, when running, we restore them currentRequestAttributes... sounded solid to me, but the error is still there. I think I made some mistake adapting the solution for my case. maybe someone can help me finding the error.
在我尝试使用不同解决方案的大量stackoverflow线程之前(请参见下文),因此我可以尝试其他方法,但是对于我来说,这似乎是最清晰,最简单的方法,所以我希望有人可以帮助我发现错误在实施中进行解释,或者解释为什么这是错误的方法.
Before I went through a lot of stackoverflow-threads with different solutions (see below), so I could try something else next, but this one seemed the clearest and simplest to me, so I hope someone could help me finding the mistake in the implementation or explain why it's the wrong approach.
- 范围会话"未激活对于当前线程; IllegalStateException:找不到线程绑定请求
- 在多线程中访问请求范围的Bean网络应用程序
- 使用请求实际的Web请求之外的作用域Bean
- ExecutorService线程未继承的InheritableThreadLocal值
- 如何在异步任务执行器中启用请求范围
- 为应用程序中的所有线程设置ThreadContext
- Spring mvc请求跨线程的作用域上下文
- Scope 'session' is not active for the current thread; IllegalStateException: No thread-bound request found
- Accessing request scoped beans in a multi-threaded web application
- Using a request scoped bean outside of an actual web request
- InheritableThreadLocal value not inherited by ExecutorService threads
- How to enable request scope in async task executor
- Setting ThreadContext for all threads in application
- Spring mvc request scope context across threads
我已经尝试过此方法,但没有成功:
I already tried this one without success:
这很重要:
<org.springframework-version>4.3.4.RELEASE</org.springframework-version>
BTW:我知道以某种方式重组应用程序会更好,线程中不需要该请求,但是在这种情况下这很复杂,我真的希望我能避免这种情况.
BTW: I know that it would be better to restructure the application in a way, that the request is not needed in the thread but that's very complicated in that case and I really hope I could avoid this.
-
Edit1:
无法在线程中创建的Bean是这样启动的:
The Bean which can not be created in the thread starts like this:
@Service("userRightsService")
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class UserRightsService {
-
Edit2:
我也尝试过这个:
但是上下文始终是空的...
But context is always empty...
推荐答案
对于正在搜索的用户.借助Master_Ex的提示,我找到了解决方案:
For those, who are searching. With the help of Master_Ex's hints I found a solution:
在可运行环境中:
private HttpServletRequest request;
public void run() {
final RequestContextListener rcl = new RequestContextListener();
final ServletContext sc = request.getServletContext();
rcl.requestInitialized(new ServletRequestEvent(sc, request));
然后在UserRightService中,我调用一个执行以下操作的函数:
And in the UserRightService I make a call to a function which does the following:
SecurityContext context = SecurityContextHolder.getContext();
Authentication auth = context.getAuthentication();
context.setAuthentication(getDataExportAuthentication(exportingUser));
@Master_Ex的谢谢,您的帖子非常有帮助.很抱歉,我来不及给您赏金,否则我会把它标记为正确的赏金.
@Master_Ex's Thank You, your post was very helpful. So sorry that I am too late to give you the bounty, otherwise I would have marked it as the correct one.
这篇关于Java/Spring MVC:向子线程提供请求上下文的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!