• 源码分析之RequestContextHolder


    先看源码

    /*
     * Copyright 2002-2012 the original author or authors.
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    package org.springframework.web.context.request;
    
    import javax.faces.context.FacesContext;
    
    import org.springframework.core.NamedInheritableThreadLocal;
    import org.springframework.core.NamedThreadLocal;
    import org.springframework.util.ClassUtils;
    
    /**
     * Holder class to expose the web request in the form of a thread-bound
     * {@link RequestAttributes} object. The request will be inherited
     * by any child threads spawned by the current thread if the
     * {@code inheritable} flag is set to {@code true}.
     *
     * <p>Use {@link RequestContextListener} or
     * {@link org.springframework.web.filter.RequestContextFilter} to expose
     * the current web request. Note that
     * {@link org.springframework.web.servlet.DispatcherServlet} and
     * {@link org.springframework.web.portlet.DispatcherPortlet} already
     * expose the current request by default.
     *
     * @author Juergen Hoeller
     * @author Rod Johnson
     * @since 2.0
     * @see RequestContextListener
     * @see org.springframework.web.filter.RequestContextFilter
     * @see org.springframework.web.servlet.DispatcherServlet
     * @see org.springframework.web.portlet.DispatcherPortlet
     */
    public abstract class RequestContextHolder  {
    
        private static final boolean jsfPresent =
                ClassUtils.isPresent("javax.faces.context.FacesContext", RequestContextHolder.class.getClassLoader());
    
        private static final ThreadLocal<RequestAttributes> requestAttributesHolder =
                new NamedThreadLocal<RequestAttributes>("Request attributes");
    
        private static final ThreadLocal<RequestAttributes> inheritableRequestAttributesHolder =
                new NamedInheritableThreadLocal<RequestAttributes>("Request context");
    
    
        /**
         * Reset the RequestAttributes for the current thread.
         */
        public static void resetRequestAttributes() {
            requestAttributesHolder.remove();
            inheritableRequestAttributesHolder.remove();
        }
    
        /**
         * Bind the given RequestAttributes to the current thread,
         * <i>not</i> exposing it as inheritable for child threads.
         * @param attributes the RequestAttributes to expose
         * @see #setRequestAttributes(RequestAttributes, boolean)
         */
        public static void setRequestAttributes(RequestAttributes attributes) {
            setRequestAttributes(attributes, false);
        }
    
        /**
         * Bind the given RequestAttributes to the current thread.
         * @param attributes the RequestAttributes to expose,
         * or {@code null} to reset the thread-bound context
         * @param inheritable whether to expose the RequestAttributes as inheritable
         * for child threads (using an {@link InheritableThreadLocal})
         */
        public static void setRequestAttributes(RequestAttributes attributes, boolean inheritable) {
            if (attributes == null) {
                resetRequestAttributes();
            }
            else {
                if (inheritable) {
                    inheritableRequestAttributesHolder.set(attributes);
                    requestAttributesHolder.remove();
                }
                else {
                    requestAttributesHolder.set(attributes);
                    inheritableRequestAttributesHolder.remove();
                }
            }
        }
    
        /**
         * Return the RequestAttributes currently bound to the thread.
         * @return the RequestAttributes currently bound to the thread,
         * or {@code null} if none bound
         */
        public static RequestAttributes getRequestAttributes() {
            RequestAttributes attributes = requestAttributesHolder.get();
            if (attributes == null) {
                attributes = inheritableRequestAttributesHolder.get();
            }
            return attributes;
        }
    
        /**
         * Return the RequestAttributes currently bound to the thread.
         * <p>Exposes the previously bound RequestAttributes instance, if any.
         * Falls back to the current JSF FacesContext, if any.
         * @return the RequestAttributes currently bound to the thread
         * @throws IllegalStateException if no RequestAttributes object
         * is bound to the current thread
         * @see #setRequestAttributes
         * @see ServletRequestAttributes
         * @see FacesRequestAttributes
         * @see javax.faces.context.FacesContext#getCurrentInstance()
         */
        public static RequestAttributes currentRequestAttributes() throws IllegalStateException {
            RequestAttributes attributes = getRequestAttributes();
            if (attributes == null) {
                if (jsfPresent) {
                    attributes = FacesRequestAttributesFactory.getFacesRequestAttributes();
                }
                if (attributes == null) {
                    throw new IllegalStateException("No thread-bound request found: " +
                            "Are you referring to request attributes outside of an actual web request, " +
                            "or processing a request outside of the originally receiving thread? " +
                            "If you are actually operating within a web request and still receive this message, " +
                            "your code is probably running outside of DispatcherServlet/DispatcherPortlet: " +
                            "In this case, use RequestContextListener or RequestContextFilter to expose the current request.");
                }
            }
            return attributes;
        }
    
    
        /**
         * Inner class to avoid hard-coded JSF dependency.
          */
        private static class FacesRequestAttributesFactory {
    
            public static RequestAttributes getFacesRequestAttributes() {
                FacesContext facesContext = FacesContext.getCurrentInstance();
                return (facesContext != null ? new FacesRequestAttributes(facesContext) : null);
            }
        }
    
    }

    里面定义了final修饰的ThreadLocal,对此可以再了解下《Java源码分析》:ThreadLocal /ThreadLocalMap

    今天520,晚上有约,还是先干活,改天再来完善.

  • 相关阅读:
    Linux Ubuntu系统的安装||grub启动字符界面
    linux 第一个qt程序 以及 linux qt cannotfind lgL的解决
    linux ftp 文件传输的搭建 以qt上传为例
    linux gcc 安装和第一个hello world脚本
    python bug debug
    python 元组的概念以及 math 模块
    移动端调试
    移动终端学习2:触屏原生js事件及重力感应
    input file 类型为excel表格
    gulp构建工具的安装
  • 原文地址:https://www.cnblogs.com/goujh/p/9063427.html
Copyright © 2020-2023  润新知