java - Spring Async,如何在异步任务执行器中启用请求范围

标签 java spring multithreading spring-boot asynchronous

我尝试在 Spring 使用@Async,在我的服务中,我使用范围为session的bean,总是出现以下错误:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.classSession': Scope 'session' 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 session found and request already completed - cannot create new session!



如前所述,找不到 session ,请求已经完成。我实现了AsyncConfigurer以便覆盖ThreadPoolTask​​Executor:下面是我的代码

Controller :
@Autowired 
MyService myService;

@RequestMapping(value = "/doIt", method = RequestMethod.PUT)
public HttpEntity initiateCurrent(..){

myService.do();
...
}

我的服务
@Autowired 
ClassWithScopeSession classSession;

@Async("taskExecutor")
public void do(){
....
...
classSession.doService();
}

//覆盖ThreadPoolTask​​Executor
public class ContextAwareCallable<T> implements Callable<T> {
    private Callable<T> task;
    private RequestAttributes context;

    @Autowired
    private ApplicationContext appContext;

    public ContextAwareCallable(Callable<T> task, RequestAttributes context) {
        this.task = task;
        this.context = context;
    }

    @Override
    public T call() throws Exception {
        if (context != null) {
            RequestContextHolder.setRequestAttributes(context);
        }
        try {
            return task.call();
        } finally {
            RequestContextHolder.resetRequestAttributes();
        }
    }
}

public class ContextAwarePoolExecutor extends ThreadPoolTaskExecutor {
    @Override
    public <T> Future<T> submit(Callable<T> task) {
        return super.submit(new ContextAwareCallable(task, RequestContextHolder.currentRequestAttributes()));
    }

    @Override
    public <T> ListenableFuture<T> submitListenable(Callable<T> task) {
        return super.submitListenable(new ContextAwareCallable(task, RequestContextHolder.currentRequestAttributes()));
    }
}

@Configuration
@EnableAsync
public class ExecutorConfig  implements AsyncConfigurer {

    @Override
    @Bean(name="taskExecutor")
    public Executor getAsyncExecutor() {
        return new ContextAwarePoolExecutor();
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return null;
    }
}

我遵循了这个response

最佳答案

您需要改写execute方法:

@Override
public void execute(Runnable task) {
    super.execute(new ContextAwareCallable(task, RequestContextHolder.currentRequestAttributes()));
}

并将您的ContextAwareCallable更新为:
public class ContextAwareCallable implements Runnable {

private Runnable task;
private RequestAttributes context;

public ContextAwareCallable(Runnable task, RequestAttributes context) {
    this.task = task;
    this.context = context;
}

@Override
public void run() {
    if (context != null) {
        RequestContextHolder.setRequestAttributes(context);
    }

    task.run();
}

}

我不是专家,但是这种解决方案对我有用。

使用@Async注释方法后,它将在execute()类上运行ThreadPoolTaskExecutor方法,而不是submit()submitListenable()

在我的解决方案中,它返回CompletableFuture。这很奇怪,因为execute不会返回任何东西。

希望它能对某人有所帮助。

关于java - Spring Async,如何在异步任务执行器中启用请求范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52593404/

相关文章:

java - Eclipse Spring 安全警告 'unable to load namespacehandler'

c++ - 使用 C++11 线程确保每个线程都有机会在给定时间段内执行

c++ - pthread_key_t 与局部变量

java - java rx 中 Observable.defer 和 Observable.create 的区别

java - 在 Spring Boot 2.4 中用我的配置文件 dev 覆盖属性

java - 合并 JSON 数据时出现问题 -- ObjectMapper (HashMap)

c++ - as-if 规则是否会阻止编译器对全局/成员变量的访问进行重新排序?

java - 如何使用SDN仅在节点不存在时创建节点?

java - 可部署的 Spring Boot Wars OAuth2 拒绝异常

java - 定制@Scheduled Spring