Mybatis-plus 可以实现字段自动填充功能,我通常会把多个表中共同字段抽离到了一个公共实体类中,如创建时间,创建人员,更新时间,更新人员等等,但是如何获取当前用户信息填入创建人员,更新人员字段?
ThreadLocal可以帮助我解决这个问题,我使用的的是JWT token 验证登陆状态,在每次Http请求时Header都会附带token,token中就会附带用户信息,当我们验证完后把用户信息set进Threadlocal,就可以在同一个线程中通过ThreadLocal获取用户信息。
ThreadLocal理解

ThreadLocal是线程安全的,它可以确保多线程访问时每个线程只能访问到自己的线程私有变量。它的线程隔离机制是通过把共享变量的副本存储到Thread.threadLocals实现,每个线程只能访问自己的副本,就能避免线程安全问题。

ThreadLocal实际上就是一个操作Thread.threadLocals的外壳。Thread.threadLocals变量是一个keyvalueMap,Thread创建的时候默认初始化threadLocals为null,在ThreadLocal首次读或写的时候初始化threadLocals。ThreadLocalMap是ThreadLocal中的静态内部类,ThreadLocalMap通过Entry键值对的方式存储数据,是一个定制化的Map。
ThreadLocal源码分析
set()
1 2 3 4 5 6 7 8 9 10 11 12
   | public void set(T value) {   			         Thread t = Thread.currentThread();   			         ThreadLocalMap map = getMap(t);   			         if (map != null)             map.set(this, value);         else           	             createMap(t, value);     }
 
  | 
 
我们可以发现ThreadLocal set的方法是对Thread.threadLocals这个定制化的Map进行操作
getMap()
1 2 3 4
   | ThreadLocalMap getMap(Thread t) {   	     return t.threadLocals; }
 
  | 
 
createMap()
1 2 3 4
   | void createMap(Thread t, T firstValue) {   	     t.threadLocals = new ThreadLocalMap(this, firstValue); }
 
  | 
 
get()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
   | public T get() {   		      Thread t = Thread.currentThread();   		      ThreadLocalMap map = getMap(t);   		      if (map != null) {          ThreadLocalMap.Entry e = map.getEntry(this);        	          if (e != null) {              @SuppressWarnings("unchecked")              T result = (T)e.value;              return result;          }      }   		      return setInitialValue();  }
 
  | 
 
setInitialValue()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
   |    private T setInitialValue() {      	        T value = initialValue();      	        Thread t = Thread.currentThread();      	        ThreadLocalMap map = getMap(t);      	        if (map != null)            map.set(this, value);        else                      createMap(t, value);        return value;    }
  protected T initialValue() {        return null;    }
 
  | 
 
remove()
1 2 3 4 5 6 7
   | public void remove() {   				         ThreadLocalMap m = getMap(Thread.currentThread());         if (m != null)                         m.remove(this);     }
 
  |