由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

 

相关文章
|
1月前
|
前端开发 JavaScript Java
[SpringMVC]知识点
本文介绍了SpringMVC的基本概念、配置和使用方法。主要内容包括前端控制器、处理器映射器、处理器适配器、视图解析器的功能和配置,以及RESTful风格的请求方式和配置细节。此外,还涉及全局异常解析器和自定义类型转换器的实现。文章通过具体示例帮助读者理解SpringMVC的核心组件和工作流程。
36 0
[SpringMVC]知识点
|
7月前
|
JSON JavaScript 前端开发
SpringMVC知识点
SpringMVC知识概览:包括Restful风格的两种实现(推荐使用`@GetMapping`),参数传递如`@PathVariable`。此外,探讨了SpringMVC的转发与重定向,以及处理请求数据的多种方式,如匹配域名参数、使用`@RequestParam`和接收对象。解决乱码问题,可以通过自定义或SpringMVC内置的过滤器。还涉及JavaScript与JSON对象的转换。
52 2
|
7月前
|
JSON 前端开发 Java
学习 SpringMVC 必备的 4 大知识点
学习 SpringMVC 必备的 4 大知识点
|
设计模式 前端开发 Java
SpringMVC重温知识点
Spring MVC是一个基于Java的实现了MVC设计模式的请求驱动类型的轻量级Web框架,通过把Model,View,Controller分离,将web层进行职责解耦,把复杂的web应用分成逻辑清晰的几部分,简化开发,减少出错,方便组内开发人员之间的配合。
76 0
SpringMVC重温知识点
|
XML Java 数据格式
学习SpringMvc第三战-利用SpringMvc实现CRUD
学习SpringMvc第三战-利用SpringMvc实现CRUD
|
存储 JSON 前端开发
SpringMVC 程序开发:为什么要学SpringMVC?如何学SpringMVC?
SpringMVC 程序开发:为什么要学SpringMVC?如何学SpringMVC?
|
前端开发 Java 程序员
硬核!一文看懂SpringMVC
本文主要介绍 SprinMVC
121 0
|
XML 前端开发 Java
springmvc配置的全解析,致敬即将远去的mvc
springmvc配置的全解析,致敬即将远去的mvc
574 0
springmvc配置的全解析,致敬即将远去的mvc
|
SQL XML JSON
常见的SpringMVC的面试题,重点干货!!!
1、因为Spring使用了以下机制,通过容器控制所有Action对象和业务逻辑类的生命周期,由与上层不再控制下层的生命周期,层与层之间实现了完全脱耦,使程序运行起来效率更高,维护起来也方便。 (1)、IOC(inversion of control) 控制反转模式:控制反转是将组件间的依赖关系从程序内部提到外部来管理,由容器控制程序之间的(依赖)关系,而非传统实现中,由程序代码直接操控。 (2)、DI(dependency injection)依赖注入是指将组件的依赖通过外部以参数或其他形式注入;即组件之间的依赖关系由容器在运行期决定,由容器动态的将某种依赖关系注入到组件之中。
187 0
常见的SpringMVC的面试题,重点干货!!!
|
设计模式 JSON 前端开发
springmvc(一) springmvc框架原理分析和简单入门程序
springmvc这个框架真的非常简单,感觉比struts2还更简单,好好沉淀下来学习~
376 0
springmvc(一) springmvc框架原理分析和简单入门程序