由SpringMVC中RequetContextListener说起

简介: 零、引言 RequetContextListener从名字结尾Listener来看就知道属于监听器。 所谓监听器就是监听某种动作,在其开始(初始化)和结束(销毁)的时候进行某些操作。 由此可以猜测:该类用于在RequetContext(请求上下文对象)创建和销毁的时候进行某些操作(哪些操作?结尾总结!) 一、web.xml配置 要使用该listener对象需要在web.xml中进行如下配置。

 

零、引言

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层获取)。

http://www.cnblogs.com/LiuChunfu/p/7067828.html

 

相关文章
|
2月前
|
XML 前端开发 Java
深入理解SpringMVC工作原理,像大牛一样手写SpringMVC框架
对于SpringMVC相信诸位并不陌生,这是Java开发过程中使用最频繁的框架,在你的项目中可能不一定用MyBatis,但绝对会使用SpringMVC,因为操作数据库还有Hibernate、JPA等其他ORM框架选择,但SpringMVC这个框架在其领域中,可谓是独领风骚
|
10月前
|
XML Java 数据格式
学习SpringMvc第三战-利用SpringMvc实现CRUD
学习SpringMvc第三战-利用SpringMvc实现CRUD
|
存储 缓存 Java
JavaWeb开发 Servlet技术详解(二)
JavaWeb开发 Servlet技术详解(二)
|
Java 应用服务中间件 Apache
|
设计模式 容器
JavaWeb开发 Servlet技术详解(五)
JavaWeb开发 Servlet技术详解(五)
|
存储 安全 前端开发
JavaWeb开发 Servlet技术详解(四)
JavaWeb开发 Servlet技术详解(四)
|
存储 JSON 应用服务中间件
JavaWeb开发 Servlet技术详解(三)
JavaWeb开发 Servlet技术详解(三)
|
存储 JSON 前端开发
SpringMVC 程序开发:为什么要学SpringMVC?如何学SpringMVC?
SpringMVC 程序开发:为什么要学SpringMVC?如何学SpringMVC?
|
前端开发 Java 数据库连接
Spring MVC框架:第一章:SpringMVC概述及初步体会SpringMVC使用过程
Spring MVC框架:第一章:SpringMVC概述及初步体会SpringMVC使用过程
113 0
Spring MVC框架:第一章:SpringMVC概述及初步体会SpringMVC使用过程
|
前端开发 Java 程序员
硬核!一文看懂SpringMVC
本文主要介绍 SprinMVC
108 0