异步任务获取springSecurity主线程上下文信息失败

一、首先配置好的@Async线程池配置类

@EnableAsync
@Configuration
public class AsyncTaskConfig implements AsyncConfigurer { @Override public Executor getAsyncExecutor() { ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); taskExecutor.setCorePoolSize(1);// 最小线程数 taskExecutor.setMaxPoolSize(10);// 最大线程数 taskExecutor.setQueueCapacity(25);// 等待队列 taskExecutor.setWaitForTasksToCompleteOnShutdown(true);// 等待所有任务结束后再关闭线程池  taskExecutor.initialize(); return taskExecutor; } }

在注解@Async中调用的方法中如果使用security来获取用户信息应该是获取不到的,原因是异步任务开启了新线程,所以用的登录信息不能在子线程获取,只能在主线程获取,因为securityContextHolder默认将用户信息保存在了ThreadLocal

主线程Security信息,即调用异步方法之前线程:

 

子线程security信息,即调用异步方法之后信息,可以看到getUserInfo为null,什么也没获取到,并且当前线程名如果在线程池配置 的话也会显示自定义命名

 

 

 比如在开始的AsyncTaskConfig配置文件中在配置线程池时加入前缀:

executor.setThreadNamePrefix("-TaskExecutor-");

 

 在上面可以通过debug看到线程的用户信息为null,所以需要我们手动往里传入主线程的信息:

解决办法:新建公共方法,在调用异步方法之前获取到userInfo,将userInfo作为参数输出如异步方法中,异步方法中调用setUserInfo方法

    private static final ThreadLocal<UserInfo> context = new ThreadLocal<UserInfo>();
    
    public void setUserInfo(){
        UserInfo currentThreadUserInfo = SecurityHelper.getUserInfo();
        context.set(currentThreadUserInfo);
    }

在使用完之后,调用clearUserInfo清空信息:

    private static final ThreadLocal<UserInfo> context = new ThreadLocal<UserInfo>();

    public void setUserInfo(){
        UserInfo currentThreadUserInfo = SecurityHelper.getUserInfo();
        context.set(currentThreadUserInfo);
    }

    public void clearUserInfo(){
        context.remove();
    }

 

posted @ 2020-12-31 16:03  木马不是马  阅读(1718)  评论(0编辑  收藏  举报