由SpringMVC中RequetContextListener说起

摘要:
描述>请求侦听器<监听器类>org.springframework.web.context.request.RequestContextListener<LocaleContextHolder.setLocale(request.getLocale());

零、引言

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

免责声明:文章转载自《由SpringMVC中RequetContextListener说起》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇vivo机器如何无需root激活XPOSED框架的流程重建win7桌面图标缓存下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

java之内部类详解

      序言         有位小同学要我写一篇这个的总结,我说那好吧,那就动手写总结一下这个内部类的知识,感觉这个在面试中也会经常遇到,内部类、反射、集合、IO流、异常、多线程、泛型这些重要的基础知识大家都比较容易记不住。大概是自己平常用的比较少,所以经常性的会忘记,现在通过博文的方式记录下来,以后忘记可以回过头来自己看。             ...

Jmeter获取数据库值并作为参数请求(转载)

转载自:https://www.cnblogs.com/mawenqiangios/p/11088672.html 01Jmeter连接数据库 1、添加JDBC Connection Configuration (右键测试计划-->配置元件-->JDBC Connection Configuration) 2、配置数据库连接信息,其中 Data...

对象的创建与OOP-Klass模型

1、JVM中OOP-KLASS模型 在JVM中,使用了OOP-KLASS模型来表示java对象,即:1.jvm在加载class时,会创建instanceKlass,表示其元数据,包括常量池、字段、方法等,存放在方法区;instanceKlass是jvm中的数据结构;2.在new一个对象时,jvm创建instanceOopDesc,来表示这个对象,存放在堆区...

java 类变量初始化顺序

假定有一个类定义如下: package com.zhang; public final class Girl { // static代码块1 private static String sex = "female"; // 成员方法代码块1 private String name = "anonymous";...

Asp.Net Core 缓存的使用(译)

原文:http://www.binaryintellect.net/articles/a7d9edfd-1f86-45f8-a668-64cc86d8e248.aspx环境:Visual Studio 2017, Asp.Net Core 1.1. 缓存机制主要是为了提高性能。在ASP.NET Web Forms 及 ASP.NET MVC中可以直接使用缓...

ansible-乱

工作机制:ssh 无客户端 工作方式: 1,CMDB 2,公有云私有云API 3,使用ad-hoc 4,ansible-playbook ansible 执行命令,底层调用传输连接模块,将命令或文件传输至远程服务器的/tmp目录,远程执行,操作完后删除,返回结果。 配置文件 /etc/ansible 功能;inventory 主机信息配置 工具功能 /us...