- 定义TaskDecorator实例
public class ContextCopyingDecorator implements TaskDecorator { @Override public Runnable decorate(Runnable runnable) { try { RequestAttributes context = RequestContextHolder.currentRequestAttributes(); Map<String,String> previous = MDC.getCopyOfContextMap(); SecurityContext securityContext = SecurityContextHolder.getContext(); return () -> { try { RequestContextHolder.setRequestAttributes(context); runnable.run(); } finally { RequestContextHolder.resetRequestAttributes(); } }; } catch (IllegalStateException e) { return runnable; } } }
- 线程池使用TaskDecorator
@Configuration public class AppConfig { @Bean public TaskExecutor taskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(corePoolSize); executor.setMaxPoolSize(maxPoolSize); executor.setQueueCapacity(queueCapacity); executor.setThreadNamePrefix("MyExecutor-"); // for passing in request scope context executor.setTaskDecorator(new ContextCopyingDecorator()); executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); executor.setWaitForTasksToCompleteOnShutdown(true); executor.initialize(); return executor; } }
- 存在问题
从父线程取出的RequestContextHolder对象,此为持有线程上下文的request容器,将其设置到子线程中,按道理只要对象还存在强引用, 就不会被销毁,但由于RequestContextHolder的特殊性,在父线程销毁的时候,会触发里面的resetRequestAttributes方法(即清除threadLocal里面的信息, 即reques中的信息会被清除),此时即使RequestContextHolder这个对象还是存在,子线程也无法继续使用它获取request中的数据了
- 完善思路
既然是RequestContextHolder的特殊性,那我们就让绕过他的销毁清除,思路不变,还是继续使用threadLocal来传递我们需要使用到的变量, 在父线程装饰前将所需变量取出来,然后在子线程中设置到threadLocal,业务使用的时候从threadLocal中取即可。
- 完善代码
public class ContextCopyingDecorator implements TaskDecorator { @Override public Runnable decorate(Runnable runnable) { try { HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); String ua = request.getHeader("user-agent"); return () -> { try { ThreadLocalData.setUa(ua); runnable.run(); } finally { //清除线程threadLocal的值 ThreadLocalData.remove(); } }; } catch (IllegalStateException e) { return runnable; } } }
- 参考:https://www.jianshu.com/p/d000a0a44956
版权声明:本文为yichengjie_c原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。