Spring boot

springboot如何把HttpServletRequest传

2020-11-19  本文已影响0人  三也视界

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

上一篇下一篇

猜你喜欢

热点阅读