【已解决】Spring Security中,多线程操作导致上下文丢失

一 、问题

某个功能因涉及的表比较多,想改成多线程异步操作。

但是在功能实现过程中,问题出来了

在登入完成后项目在请求中封装了HospitalId在请求域中,然后继承项目封装好的BaseService可以在Service层直接调用this.getHospitalId()获取值

当开启多线程的时候this.getHospitalId()会报错 空指针异常

正常操作是

//开启线程前获取请求
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
//每一个线程都来共享之前的请求数据
RequestContextHolder.setRequestAttributes(requestAttributes);

但这样还是会空指针

二、解决方法

使用了Spring Security获取的请求就变了

//在主线程中获取安全上下文
SecurityContext securityContext = SecurityContextHolder.getContext();
//将主线程中的安全上下文设置到子线程中的ThreadLocal中
SecurityContextHolder.setContext(securityContext);
// 清除操作
// 将调用者中的安全上下文设置到当前业务子线程中的ThreadLocal中。
SecurityContextHolder.clearContext();

第三步的清除操作必不可少,不然会导致异步线程的安全上下文传播到线程池中,而如果该线程为线程池的核心线程,下次该线程执行时又没有设置安全上下文,则会获取到错误的信息(也就是这次设置的安全上下文信息)

三、原因

因为Spring Security的安全上下文默认是存储在ThreadLocal(也就是线程本地)的,启动其他线程执行的时候,就会丢失掉上下文信息。

你可能感兴趣的:(java,Spring,Security,多线程)