zoukankan      html  css  js  c++  java
  • 由SpringMVC中RequetContextListener说起

    零、引言

    RequetContextListener从名字结尾Listener来看就知道属于监听器。
    所谓监听器就是监听某种动作,在其开始(初始化)和结束(销毁)的时候进行某些操作。
    由此可以猜测:该类用于在RequetContext(请求上下文对象)创建和销毁的时候进行某些操作(哪些操作?结尾总结!)

    一、web.xml配置

    要使用该listener对象需要在web.xml中进行如下配置。
    <!-- 此监听器是监听HttpRequest对象,方便ContextHolderUtils程序调用HttpRequest对象 -->
    <listener>
    <description>request监听器</description>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>

    二、三个重要类解读

    2.1 RequetContextListener

    public class RequestContextListener implements ServletRequestListener {
        private static final String REQUEST_ATTRIBUTES_ATTRIBUTE =
                RequestContextListener.class.getName() + ".REQUEST_ATTRIBUTES";
        // 在请求进入的时候,初始化变量放入ThreadLocal<T>中
        @Override
        public void requestInitialized(ServletRequestEvent requestEvent) {
            //判定当前的requetEvent中获取的ServletRequest()对象是否是HttpServletRequet对象
            if (!(requestEvent.getServletRequest() instanceof HttpServletRequest)) {
                throw new IllegalArgumentException(
                        "Request is not an HttpServletRequest: " + requestEvent.getServletRequest());
            }
            //强制转型为 HttpServletRequest
            HttpServletRequest request = (HttpServletRequest) requestEvent.getServletRequest();
            // ServletRequestAttributes 保存了HttpServletRequet、Response、Session等变量
            ServletRequestAttributes attributes = new ServletRequestAttributes(request);
            request.setAttribute(REQUEST_ATTRIBUTES_ATTRIBUTE, attributes);
            LocaleContextHolder.setLocale(request.getLocale());
            //RequestContextHolder里面有一个ThreadLocal,当前线程共享
            RequestContextHolder.setRequestAttributes(attributes);
        }
        //在请求被销毁的时候,将在初始化时候的ThreadLocal变量清空。
        @Override
        public void requestDestroyed(ServletRequestEvent requestEvent) {
            ...
        }
    }

     2.2 RequetContextHolder

    public abstract class RequestContextHolder  {
        //ThreadLocal<T>变量用于保存当前线程的共享变量
        private static final ThreadLocal<RequestAttributes> requestAttributesHolder =
                new NamedThreadLocal<RequestAttributes>("Request attributes");
        private static final ThreadLocal<RequestAttributes> inheritableRequestAttributesHolder =
                new NamedInheritableThreadLocal<RequestAttributes>("Request context");
        /**
         * 将线程中的共享变量清除掉,会在RequetContextListner的destory()方法中调用。
         */
        public static void resetRequestAttributes() {
            //清空变量
            requestAttributesHolder.remove();
            inheritableRequestAttributesHolder.remove();
        }
        //过渡方法
        public static void setRequestAttributes(RequestAttributes attributes) {
            setRequestAttributes(attributes, false);
        }
        // 核心的方式:将RequetAttrubutes(Request/Response/Session)放入到ThreadLocal<T>中进行共享
        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();
                }
            }
        }

    2.3 ServletRequestAttributes

    public class ServletRequestAttributes extends AbstractRequestAttributes {
        private final HttpServletRequest request;
        private HttpServletResponse response;
        private volatile HttpSession session;
        private final Map<String, Object> sessionAttributesToUpdate = new ConcurrentHashMap<String, Object>(1);
    }

    三、使用方法

    从以上可以知道RuquetAttribute是放在了ThreadLocal中,则在该次请求中,可以在任意的代码位置中获取该该对象,由此拿到HttpServletRequet等对象。
    HttpServletRequest request =((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
    利用该方法可以在任意位置获取request对象.

    四、总结

    RequetContextListner主要作用就一个:
    将本次请求的 ServletRequestAttributes 对象 保存在ThreadLocal中,方便在某一次请求的任意代码位置获取(包括直接在service层获取)。
     
    ######################################LiuCF############转载注明出处###############2017年6月22日23:38:49###########################
     
     

    转载于:https://www.cnblogs.com/LiuChunfu/p/7067828.html

  • 相关阅读:
    导包路径
    django导入环境变量 Please specify Django project root directory
    替换django的user模型,mysql迁移表报错 django.db.migrations.exceptions.InconsistentMigrationHistory: Migration admin.0001_initial is applied before its dependen cy user.0001_initial on database 'default'.
    解决Chrome调试(debugger)
    check the manual that corresponds to your MySQL server version for the right syntax to use near 'order) values ('徐小波','XuXiaoB','男','1',' at line 1")
    MySQL命令(其三)
    MySQL操作命令(其二)
    MySQL命令(其一)
    [POJ2559]Largest Rectangle in a Histogram (栈)
    [HDU4864]Task (贪心)
  • 原文地址:https://www.cnblogs.com/twodog/p/12140239.html
Copyright © 2011-2022 走看看