ThreadLocal存放用户信息(springboot)

本文介绍了如何在微服务架构中利用ThreadLocal优化用户信息的传递。通过定义一个用户实体,创建ThreadLocal工具类进行存取操作,并在拦截器中管理ThreadLocal的生命周期。拦截器在请求开始时将用户信息放入ThreadLocal,在请求结束时移除,确保信息的安全性。此外,还提供了一个用户信息操作接口,方便在业务代码中直接使用。这种方式简化了用户信息在方法间传递的复杂性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

场景:

接手一个项目,用户信息是用Feign调用用户中心获取,方法之间相互调用使用用户信息很麻烦(1,通过接口传参,2,再次调用Feign)。所以使用ThreadLocal存放用户信息

1,定义用户实体:

@ApiModel("登录用户信息")
@Data
public class FeginUser implements Serializable {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "用户ID")
    private String id;
    @ApiModelProperty(value = "用户名")
    private String name;
   
    @ApiModelProperty(value = "密码")
    @JsonIgnore
    private String upass;
}

2,定义工具类操作ThreadLocal(存放,获取,删除用户信息)

  public class ThreadLocalUtil {

        /**
         * 保存用户对象的ThreadLocal  在拦截器操作 添加、删除相关用户数据
         */
        private static final ThreadLocal<FeginUser> userThreadLocal = new ThreadLocal<FeginUser>();

        /**
         * 添加当前登录用户方法  在拦截器方法执行前调用设置获取用户
         * @param user
         */
        public static void addCurrentUser(FeginUser user){
            userThreadLocal.set(user);
        }

        /**
         * 获取当前登录用户方法
         */
        public static FeginUser getCurrentUser(){
            return userThreadLocal.get();
        }


        /**
         * 删除当前登录用户方法  在拦截器方法执行后 移除当前用户对象
         */
        public static void remove(){
            userThreadLocal.remove();
        }
    }

3,拦截器:1,访问接口时将用户信息放入ThreadLocal,2,访问结束时候删除ThreadLocal中信息(线程放入线程池并不一定会销毁)

@Component
@Slf4j
public class UserInfoInterceptor implements HandlerInterceptor  {

    @Autowired
    private UserInfoUtil userInfoUtil;

    /**
     * 请求执行前执行的,将用户信息放入ThreadLocal
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        FeginUser user;
        try{
             user = userInfoUtil.getUser();
        }catch (CustomException e){
            log.info("***************************用户未登录, ThreadLocal无信息***************************");
            return true;
        }
        if (null!=user) {
            log.info("***************************用户已登录,用户信息放入ThreadLocal***************************");
            ThreadLocalUtil.addCurrentUser(user);
            return true;
        }
        log.info("***************************用户未登录, ThreadLocal无信息***************************");
        return true;
    }

    /**
     * 接口访问结束后,从ThreadLocal中删除用户信息
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        log.info("***************************接口调用结束, 从ThreadLocal删除用户信息***************************");
        ThreadLocalUtil.remove();
    }

4,配置拦截器。

@Configuration
@ComponentScan
public class MyAppConfigurer extends WebMvcConfigurationSupport {

    @Autowired
    private UserInfoInterceptor userInfoInterceptor;

    /**
     * 拦截器,将用户信息放入threadLocal
     *
     * @param registry
     */
    @Override
    protected void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(this.userInfoInterceptor).addPathPatterns("/**");
        super.addInterceptors(registry);
    }

}

5,定义用户信息具体操作接口:

为了类实现接口后直接使用(不定义为基础类,是因为类单继承)

public interface IBaseUserInfo {
    default Boolean isLogin() {
        return ThreadLocalUtil.getCurrentUser() != null;
    }

    default FeginUser getUser() {
        return ThreadLocalUtil.getCurrentUser();
    }

    default String getUserId() {
        if (ThreadLocalUtil.getCurrentUser() != null) {
            return ThreadLocalUtil.getCurrentUser().getId();
        }
        return null;
    }

}

6,使用:(代码中第二种使用方法,不需要定义接口)

@Service
public class ApplylServiceImpl implements IBaseUserInfo {
    

    public void applyUserInfo() {
        /**
         * 1,实现接口后,直接使用
         */
        FeginUser user1 = getUser();
        /**
         * 2,不实现接口,调用ThreadLocalUtil
         */
        FeginUser user2 = ThreadLocalUtil.getCurrentUser();
    }

}
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值