对于RequestContextHolder产生的一些关于ThreadLocal还有SpringMVC的理解

今天下午在看代码的时候,发现Spring中写了一个切面方法,来验证请求的token头。

中间获取每次请求的request对象时,并没有从controller中获取,而是直接用了一个类去获取request,当时有些疑惑,直接获取如何保证每次获取的request对象是当前的请求对象。

于是搜索了一番相关文章,对于@controller还有ThreadLoal有了一定的理解,所以在此记录一下。

在Service中直接获取request的方式,如下

public static HttpServletRequest getRequest() {
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
				.getRequestAttributes()).getRequest();
		return request;
	}

每次请求都会产生一个新的线程,而requestAttributes是一个ThreadLocal属性,属于线程内变量,各个线程之间互不干扰。

自己推断了一下,每次RequestContextHolder,getRequestAttributes获取的都是当前执行的请求线程的requestAttributes,也就获取了当前请求的request。

要弄明白这个问题首先就得弄懂ThreadLocal的用法。

ThreadLocal内部有一个ThreadlLocalMap内部类,每个Thread线程内部都有一个ThreadLocalMap对象。

每创建一个ThreadLocal变量,都会在调用这个属性的Thread的ThreadLocalMap中存入一个副本。

key值为ThreadLocal,value为实际使用的变量

每次取用的时候,会根据当前线程,去取当前线程中的ThreadLocalMap,然后取出这个线程变量。

如下为ThreadLocal的get()

 /**
     * Returns the value in the current thread's copy of this
     * thread-local variable.  If the variable has no value for the
     * current thread, it is first initialized to the value returned
     * by an invocation of the {@link #initialValue} method.
     *
     * @return the current thread's value of this thread-local
     */
    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();
    }

getMap()方法取出线程中的ThreadLocalMap

    /**
     * Get the map associated with a ThreadLocal. Overridden in
     * InheritableThreadLocal.
     *
     * @param  t the current thread
     * @return the map
     */
    ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }

 

createMap()创建当前线程的ThreadLocalMap

    /**
     * Create the map associated with a ThreadLocal. Overridden in
     * InheritableThreadLocal.
     *
     * @param t the current thread
     * @param firstValue value for the initial entry of the map
     */
    void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }

 

同时Thread中的ThreadLocalMap属性如下:

对于RequestContextHolder产生的一些关于ThreadLocal还有SpringMVC的理解_第1张图片

你可能感兴趣的:(问题备注)