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對象只能存放一個值,當存放多個時,會將新值覆蓋舊值。