美文网首页
SpringMvc获取HttpServletRequest 对象

SpringMvc获取HttpServletRequest 对象

作者: 不迷烟火 | 来源:发表于2020-02-05 21:01 被阅读0次

SpringMvc获取HttpServletRequest 对象的方式

1.@Autowired 方式
2.public void Test(HttpServletRequest request1, HttpServletResponse resp,HttpSession session1) 方式
3.((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest(); 方式
4.Global.getHttpServletRequest(); 方式,该方式基于 第三种做的封装



@Autowired
HttpServletRequest request的原理

拿到这个注解首先会很疑惑几个问题,如下
1.request这个对象是什么时候注册的?
2.每次请求都会有一个新的request,怎么能保证这个就是对应的每次请求的request
3.是否线程安全
下面就对这个问题进行一一解答
1.request这个对象是什么注册的?
SpringMvc的ApplicationContext是XmlWebApplicationContext
XmlWebApplicationContext继承AbstractRefreshableWebApplicationContext
现在重点在于AbstractRefreshableWebApplicationContext的postProcessBeanFactory的方法
调用链如下
AbstractRefreshableWebApplicationContext.postProcessBeanFactory
==> WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
==> {
    beanFactory.registerScope(WebApplicationContext.SCOPE_REQUEST, new RequestScope());
    beanFactory.registerScope(WebApplicationContext.SCOPE_SESSION, new SessionScope());
    // 重点就是这一行了
    beanFactory.registerResolvableDependency(ServletRequest.class, new RequestObjectFactory());
    beanFactory.registerResolvableDependency(ServletResponse.class, new                ResponseObjectFactory());
    beanFactory.registerResolvableDependency(HttpSession.class, new SessionObjectFactory());
    beanFactory.registerResolvableDependency(WebRequest.class, new WebRequestObjectFactory());
}
1.首先HttpServletRequest注入
new RequestObjectFactory().getObject()
   //为社么调用getObject()?, 代码见AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType))
    ==> currentRequestAttributes().getRequest();
    ==>  { 
        currentRequestAttributes() 方法。
        RequestAttributes requestAttr = RequestContextHolder.currentRequestAttributes();
        if (!(requestAttr instanceof ServletRequestAttributes)) {
            throw new IllegalStateException("Current request is not a servlet request");
        }
        return (ServletRequestAttributes) requestAttr;
    }
所以主要是RequestContextHolder,从RequestContextHolder类可以看到主要用到了ThreadLocal,ThreadLocal主要可以保存当前的变量
那么问题又来了HttpServletRequest是何时放入RequestContextHolder中的。

2.有多个地方HttpServletRequest都可以进入RequestContextHolder中
 {
   1. FrameworkServlet(DispatcherServlet继承的它).processRequest
   ==> initContextHolders() ==> RequestContextHolder
   2. RequestContextListener (每次Http请求都会触发) 并将HttpServletRequest请求放入RequestContextHolder中
 }
 有个坑 就是文件上传用的是MultipartHttpServletRequest 而注入的是RequestFacade不是同一个,所以文件上传通过方法入参比较好,也就是第二种方法
3.由于采用的是ThreadLocal,HttpServletRequest维护到了当前所在的线程当中,所以是线程安全的。




实现ObjectFactory注入的时候调用getObject获取到对应的bean,和FactoryBean有点像
findAutowireCandidates
==> resolvableDependencies 
==> AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType)
==> factory.getObject();

相关文章

网友评论

      本文标题:SpringMvc获取HttpServletRequest 对象

      本文链接:https://www.haomeiwen.com/subject/iojexhtx.html