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();
网友评论