HttpServletRequest是由如tomcat這種Servlet容器創(chuàng)建的。
Tomcat 創(chuàng)建的 Request 和 Response 的類(lèi)結(jié)構(gòu)圖。

至于這個(gè)HttpServletRequest是怎么傳到你對(duì)應(yīng)的controller方法內(nèi)的,實(shí)際上就是SpringMVC里面的DispatchServlet起的作用。這里先不展開(kāi),下面再討論,先看一張圖。

得到HttpServletRequest的三種方式
方式一:Controller方法參數(shù)
在Controller的方法參數(shù)上寫(xiě)上HttpServletRequest,這樣每次請(qǐng)求過(guò)來(lái)得到就是對(duì)應(yīng)的HttpServletRequest。
@GetMapping("/test")
public void test(HttpServletRequest request) {}
方式二:從RequestContextHolder上下文獲取
// 從請(qǐng)求上下文里獲取Request對(duì)象
ServletRequestAttributes requestAttributes = ServletRequestAttributes.class.
cast(RequestContextHolder.getRequestAttributes());
HttpServletRequest contextRequest = requestAttributes.getRequest();
方式三:依賴(lài)注入@Autowired
@Autowired
HttpServletRequest req;
@GetMapping("/test")
public void test(HttpServletRequest request) {}
注入的request何處來(lái)?

發(fā)現(xiàn)是注入其實(shí)是往WebApplicationContextUtils通過(guò)RequestObjectFactory拿值,跟蹤

返回的是RequestContextHolder里的值. 追蹤RequestContextHolder

每次返回的其實(shí)是, RequestAttributes的實(shí)現(xiàn)類(lèi)ServletWebRequest(ServletRequestAttributes)里的request. 因?yàn)镽equestAttributes是屬于threadLocal的,所以注入的request也是線(xiàn)程安全的了
2, spring何時(shí)設(shè)置的request對(duì)象?
HttpServlet實(shí)現(xiàn)類(lèi) FrameworkServlet-> service()->processRequst()

每次請(qǐng)求都會(huì)往里面設(shè)置最新的request, 設(shè)值
================================================================
我們可以在Spring的bean中輕松的注入HttpServletRequest,使用@Autowired HttpServletRequest request;就可以了。
但是,為什么我們可以直接這樣用呢?
原因肯定是Spring在容器初始化的時(shí)候就將HttpServletRequest注冊(cè)到了容器中。
那么我們就查原碼,發(fā)現(xiàn)在WebApplicationContextUtils.registerWebApplicationScopes(ConfigurableListableBeanFactory, ServletContext)中實(shí)現(xiàn)了這個(gè)功能。
這個(gè)方法是在A(yíng)bstractApplicationContext.refresh()中進(jìn)行調(diào)用的,也就是在Spring容器初始化的時(shí)候,將web相關(guān)的對(duì)象注冊(cè)到了容器中。
具體可以看下面的原碼圖片:




附:
1. Spring能實(shí)現(xiàn)在多線(xiàn)程環(huán)境下,將各個(gè)線(xiàn)程的request進(jìn)行隔離,且準(zhǔn)確無(wú)誤的進(jìn)行注入,奧秘就是ThreadLocal

2. Spring中還可以直接注入ApplicationContext