• SpringMVC中RequetContextListener


    来自:https://www.cnblogs.com/softidea/p/7068196.html

    零、引言 

    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

      //ServletRequestListener web中的监听器,该监听器主要在创建request,销毁request对象起作用
    public class RequestContextListener implements ServletRequestListener {
        private static final String REQUEST_ATTRIBUTES_ATTRIBUTE =
                RequestContextListener.class.getName() + ".REQUEST_ATTRIBUTES";
        // 在请求进入的时候,初始化变量放入ThreadLocal<T>中 ,创建request对象
        @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层获取)。
  • 相关阅读:
    jstl核心标签库
    乱码的解决
    eclipse 中 Servlet 模板代码(其实是代码提示模板)
    因为最近一直在和数据库打交道,所以做了几个小封装
    意外发现的大批量导入数据SqlBulkCopy类
    Http相关
    Tomcat相关
    对于反射中的invoke()方法的理解
    SqlCommandBuilder类是如何构建T-Sql语句
    模拟在内存中的数据库DataSet相关的类
  • 原文地址:https://www.cnblogs.com/But-you/p/9716950.html
Copyright © 2020-2023  润新知