项目相关背景:
项目场景:前端发送了请求,由于响应时间较长,所以要采用异步,但是异步时由于数据库分库的原因,设置当前线程的头信息失败,导致入库失败
问题描述
这样设置线程的请求头会失败
@DS("#dynamic")
@Async("transaction")
@Override
public void doSomting(Entity vos, HttpHeaders headers) {
CurrentHeadersUtil.setHeaders(headers);
//这是设置线程的请求头会失败
}
原因分析:
因为异步时会重新起一个线程,子线程跟父线程不在同一个线程池中,在
CurrentHeadersUtil.setHeaders时,并没有把当前的线程头信息赋值给子线程
解决方案:
在线程池中主动手动把线程头信息赋值给子线程
//当前用到的线程池
@Bean("transaction")
public TaskExecutor icbctaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//一些常规参数
executor.setCorePoolSize(8);
executor.setMaxPoolSize(30);
executor.setQueueCapacity(30);
executor.setThreadNamePrefix("newThreadPool_");
//主要解决问题点就是这里,手动赋值头信息
executor.setTaskDecorator(new ThreadPoolConfig.ContextDecorator());
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.setKeepAliveSeconds(60);
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setAwaitTerminationSeconds(60);
executor.initialize();
return executor;
}
//这里是具体操作
static class ContextDecorator implements TaskDecorator {
ContextDecorator() {
}
public Runnable decorate(Runnable runnable) {
try {
RequestAttributes context = RequestContextHolder.getRequestAttributes();
HttpHeaders headers = CurrentHeadersUtil.getHeaders();
return () -> {
try {
//上下文和头信息都要赋值
if (context != null) {
RequestContextHolder.setRequestAttributes(context);
}
if (headers != null) {
CurrentHeadersUtil.setHeaders(headers);
}
runnable.run();
} finally {
RequestContextHolder.resetRequestAttributes();
}
};
} catch (Exception var4) {
var4.printStackTrace();
return runnable;
}
}
}
这是我的理解,有问题请指出



