关于 RequestContextHolder
RequestContextHolder
可以获取当前的HttpServletRequest
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
.getRequestAttributes()).getRequest();
实现原理 ThreadLocal
ThreadLocal是一个本地线程副本变量工具类。主要用于将私有线程和该线程存放的副本对象做一个映射,各个线程之间的变量互不干扰,在高并发场景下,可以实现无状态的调用,特别适用于各个线程依赖不同的变量值完成操作的场景。
在每个线程的内部存在一个数据结构为Map的ThreadLocals变量,以<ThreadLocal,Value>的形式保存着线程变量和其对应的值。
对于不同的线程,每次获取副本值时,别的线程并不能获取到当前线程的副本值,形成了副本的隔离,互不干扰。
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);//当前线程为入参,获取当前线程的threadLocals变量
if (map != null)
//入参为this,也就是说key为ThreadLocal对象
map.set(this, value);
else
createMap(t, value);
}
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);//当前线程为入参,获取当前线程的threadLocals
if (map != null) {
//入参为this,也就是说key为ThreadLocal
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;//threadLocals为线程的变量
}
private Entry getEntry(ThreadLocal<?> key) {
int i = key.threadLocalHashCode & (table.length - 1);
Entry e = table[i];
if (e != null && e.get() == key)
return e;
else
return getEntryAfterMiss(key, i, e);//避免内存泄漏,下文有提。
}
Set():
- 获取到当前线程的ThreadLocals ,类型为Map
- 将这个值放到这个Map的结构变量中,key为ThreadLocal对象,value为所存放的值。
Get():
- 获取到当前线程的ThreadLocals
- 以ThreadLocal对象为Key获取Value值
因为ThreadLocal对象作为Map的key ,所以一个ThreadLocal对象只能存放一个值,当存放多个时,会将新值覆盖旧值。