springboot如何把HttpServletRequest传入到controller

HttpServletRequest是由如tomcat这种Servlet容器创建的。
Tomcat 创建的 Request 和 Response 的类结构图。

image.png

至于这个HttpServletRequest是怎么传到你对应的controller方法内的,实际上就是SpringMVC里面的DispatchServlet起的作用。这里先不展开,下面再讨论,先看一张图。

image.png

得到HttpServletRequest的三种方式

方式一:Controller方法参数

Controller的方法参数上写上HttpServletRequest,这样每次请求过来得到就是对应的HttpServletRequest

@GetMapping("/test")
public void test(HttpServletRequest request) {}

方式二:从RequestContextHolder上下文获取

    // 从请求上下文里获取Request对象
    ServletRequestAttributes requestAttributes = ServletRequestAttributes.class.
        cast(RequestContextHolder.getRequestAttributes());
    HttpServletRequest contextRequest = requestAttributes.getRequest(); 

方式三:依赖注入@Autowired

@Autowired
HttpServletRequest req;
 
@GetMapping("/test")
public void test(HttpServletRequest request) {}

注入的request何处来?

image.png

发现是注入其实是往WebApplicationContextUtils通过RequestObjectFactory拿值,跟踪

image

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

image.png

每次返回的其实是, RequestAttributes的实现类ServletWebRequest(ServletRequestAttributes)里的request. 因为RequestAttributes是属于threadLocal的,所以注入的request也是线程安全的了

2, spring何时设置的request对象?

HttpServlet实现类 FrameworkServlet-> service()->processRequst()

image

每次请求都会往里面设置最新的request, 设值

================================================================

我们可以在Spring的bean中轻松的注入HttpServletRequest,使用@Autowired HttpServletRequest request;就可以了。

但是,为什么我们可以直接这样用呢?

原因肯定是Spring在容器初始化的时候就将HttpServletRequest注册到了容器中

那么我们就查原码,发现在WebApplicationContextUtils.registerWebApplicationScopes(ConfigurableListableBeanFactory, ServletContext)中实现了这个功能。

这个方法是在AbstractApplicationContext.refresh()中进行调用的,也就是在Spring容器初始化的时候,将web相关的对象注册到了容器中。

具体可以看下面的原码图片:

image
image
image
image

附:

1. Spring能实现在多线程环境下,将各个线程的request进行隔离,且准确无误的进行注入,奥秘就是ThreadLocal

image

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

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容