zoukankan      html  css  js  c++  java
  • SpringMVC之RequestContextHolder分析

    看源码的时候发现可以在service获取requestresponse,正常来说在service层是没有request的,然而直接从controlller传过来的话解决方法太粗暴,后来发现了SpringMVC提供的RequestContextHolder来研究一下,并借此对SpringMVC的结构深入了解一下

    1.RequestContextHolder的使用

    RequestContextHolder顾名思义,持有上下文的Request容器.使用是很简单的,具体使用如下:

    RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
    //RequestContextHolder.getRequestAttributes();
    //从session里面获取对应的值
    String str = (String) requestAttributes.getAttribute("name",RequestAttributes.SCOPE_SESSION);
    HttpServletRequest request = ((ServletRequestAttributes)requestAttributes).getRequest();
    HttpServletResponse response = ((ServletRequestAttributes)requestAttributes).getResponse();
    

    看到这一般都会想到几个问题:

    request和response怎么和当前请求挂钩?
    request和response等是什么时候设置进去的?

    2.解决疑问

    2.1 request和response怎么和当前请求挂钩?

    首先分析RequestContextHolder这个类,里面有两个ThreadLocal保存当前线程下的request

    //得到存储进去的request
    private static final ThreadLocal<RequestAttributes> requestAttributesHolder =
    new NamedThreadLocal<RequestAttributes>("Request attributes");
    //可被子线程继承的request
    private static final ThreadLocal<RequestAttributes> inheritableRequestAttributesHolder =
    new NamedInheritableThreadLocal<RequestAttributes>("Request context");
    

    再看getRequestAttributes()方法,相当于直接获取ThreadLocal里面的值,这样就保证了每一次获取到的Request是该请求的request.

    public static RequestAttributes getRequestAttributes() {
            RequestAttributes attributes = requestAttributesHolder.get();
            if (attributes == null) {
                attributes = inheritableRequestAttributesHolder.get();
            }
            return attributes;
        }
    

    2.2request和response等是什么时候设置进去的?

    找这个的话需要对springMVC结构的DispatcherServlet的结构有一定了解才能准确的定位该去哪里找相关代码.

    要分析的的就是三个类,简单看下源码

    1. HttpServletBean 进行初始化工作

    2. FrameworkServlet 初始化 WebApplicationContext,并提供service方法预处理请

    3. DispatcherServlet 具体分发处理.

    那么就可以在FrameworkServlet查看到该类重写了service(),doGet(),doPost()...等方法,这些实现里面都有一个预处理方法processRequest(request, response);,所以定位到了我们要找的位置

    查看processRequest(request, response);的实现,具体可以分为三步:

    1. 获取上一个请求的参数
    2. 重新建立新的参数
    3. 设置到XXContextHolder
    4. 父类的service()处理请求
    5. 恢复request
    6. 发布事
    我会写代码+代码改变世界=我会改变世界! 为什么要改变世界? 如果无法改变世界,那么,世界就会改变我......
  • 相关阅读:
    软件工程实践2017结对项目——第一次作业
    软件工程实践2017第二次作业
    软件工程实践2017第一次作业
    [LeetCode] 72. Edit Distance(最短编辑距离)
    [LeetCode] 342. Power of Four(位操作)
    [LeetCode] 477. Total Hamming Distance(位操作)
    [LeetCode] 421. Maximum XOR of Two Numbers in an Array(位操作)
    [LeetCode] 260. Single Number III(位操作)
    [LeetCode] 137. Single Number II (位操作)
    IntelliJ IDEA快捷键
  • 原文地址:https://www.cnblogs.com/chougoushi/p/13432370.html
Copyright © 2011-2022 走看看