ThreadLocal的应用--用户信息上下文记录


就拿用户上下文信息保存来说。

场景

现在有一个场景,客户端请求新建一个短链接的分组,用户只需要输入一个分组名,然后确认即可创建分组。(全局唯一的分组 ID 这些都是由后端进行处理的)。如下请求:

而且,我们分组和用户名要进行关联,不然我们怎么知道某个用户下的分组有哪些,或者说短链接分组的归属是谁?

  • 然后呢,问题来了,我们这个用户名参数是由前端传递嘛,那前端浏览器总不能一直存储用户信息吧,不安全。
  • 或者说让用户手动传递用户名,然后后端验证是否是同一个用户然后再执行请求?这对用户的体验肯定非常不好,(我就是创建个分组而已,你连我是谁都不知道?)

解决方法

这就可以使用 ThreadLocal 对象,在用户发第一次请求时,拦截器拦截后的处理中,就可以把用户信息作为 value,当前线程 ID 作为 key 存储在 ThreadLocalMap 中,这个 ThreadLocalMap 是封装在 ThreadLocal 中的一个 map 结构,其类似 HashMap,可以存储用户信息对象。

之后在需要获取用户名的时候,只要用用户上下文对象,通过 get 拿到要用的用户信息。


如下是封装的一个 UserContext 类,包含 set,get,remove等 方法。

package org.ktpro.shortlink.admin.common.biz.user;
import com.alibaba.ttl.TransmittableThreadLocal;
import java.util.Optional;

/**
 * 用户上下文
 */
public final class UserContext {

	//实现ThreadLoal泛型
    private static final ThreadLocal<UserInfoDTO> USER_THREAD_LOCAL = new TransmittableThreadLocal<>();

    /**
     * 设置用户至上下文
     *
     * @param user 用户详情信息
     */
    public static void setUser(UserInfoDTO user) {
        USER_THREAD_LOCAL.set(user);
    }
    
    /**
     * 获取上下文中用户 ID
     *
     * @return 用户 ID
     */
    public static String getUserId() {
        UserInfoDTO userInfoDTO = USER_THREAD_LOCAL.get();
        return Optional.ofNullable(userInfoDTO).map(UserInfoDTO::getUserId).orElse(null);
    }
    
    /**
     * 获取上下文中用户名称
     *
     * @return 用户名称
     */
    public static String getUsername() {
        UserInfoDTO userInfoDTO = USER_THREAD_LOCAL.get();
        return Optional.ofNullable(userInfoDTO).map(UserInfoDTO::getUsername).orElse(null);
    }

    /**
     * 获取上下文中用户真实姓名
     *
     * @return 用户真实姓名
     */
    public static String getRealName() {
        UserInfoDTO userInfoDTO = USER_THREAD_LOCAL.get();
        return Optional.ofNullable(userInfoDTO).map(UserInfoDTO::getRealName).orElse(null);
    }


    /**
     * 清理用户上下文
     */
    public static void removeUser() {
        USER_THREAD_LOCAL.remove();
    }
}

文章作者: KTpro
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 KTpro !
评论
  目录