> 文档中心 > 通过ThreadLocal记录上下文信息(记录用户信息实现全局操作)

通过ThreadLocal记录上下文信息(记录用户信息实现全局操作)

ThreadLocal为每一个线程都提供了变量的副本,并且变量在整个线程的生命周期有效,形成了线程与线程之间的隔离,只有同一个线程才能操作变量,是一种”以空间换时间”的形式,可以用来记录一些上下文数据。

ThreadLocal内部通过Map来储存每一个线程的变量副本,map的key就是threadLocal,value就是我们set的那个值,每次线程在get的时候,都从自己的变量中取值,所以肯定就不存在线程安全问题。
使用ThreadLocal后,一定要注意手动remove()否则会造成OOM异常。

场景如下:

ThreadLocal代码:

public class RequestHolder {    private static final ThreadLocal<SysUser> userHolder = new ThreadLocal<SysUser>();    public static void setUser(SysUser sysUser) { userHolder.set(sysUser);    }    public static SysUser getUser() { return userHolder.get();    }    public static void remove() { userHolder.remove();    }}

应用流程:
以下流程部分使用伪代码表示
1、拦截器获取用户信息
2、记录到ThreadLocal中
3、使用时通过get()方法获取值

// 1、拦截器获取用户信息// 2、记录到ThreadLocal中@Componentpublic class AuthenticationHandlerInterceptor implements HandlerInterceptor {    @Override    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { log.debug("进入拦截器,URL:{}", request.getServletPath()); // 加入用户全局信息 RequestHolder.setUser(userInfo); return true;    }    ....    ....}// 3、使用时通过get()方法获取值@RestController@RequestMappingpublic class Controller {   .....    @GetMapping("/test")    public String test() {    // 从ThreadLocal获取数据    RequestHolder.getUserId(); return "访问成功";    }   .....}