今天,我发现可以将HttpServletRequest
自动连接到任意的单例Spring bean中。
@Component
public class MyComponent {
private final HttpServletRequest servletRequest;
public MyComponent(HttpServletRequest servletRequest) {
this.servletRequest = servletRequest;
}
}
字符串
我还没有找到权威的来源,但从我在网上搜索到的信息来看,这实际上是一个委托给运行线程的实际HttpServletRequest
的 Package 器。
例如,2012年的this blog post指出:
那么当多个请求来到这个服务时,对应于用户请求的正确的httpServletRequest是如何注入到这个服务对象中的呢?答案是,一个真实的HttpServletRequest并没有真正注入,只是注入了一个代理。代理在内部是对RequestContextHolder的引用,在某个时候将HttpServletRequest绑定到一个threadlocal变量。
我还不清楚这是Spring的核心特性、Spring MVC的特性还是Sping Boot 提供的特性。
我还没有找到任何权威的消息来源(例如在Spring文档,Spring内部,或Spring发行说明中)解释这是一个受支持的特性,并解释它是如何工作的。我猜它在那里,但我没有运气找到它。如果我要使用这样的特性,我更希望有这样的背景,这样我就可以推理出何时以及如何最好地使用它,以及何时避免它。
此功能的文档在哪里?
注意事项:这是一个类似于Inject HttpServletRequest into Controller的问题,但是,这是在询问这种方法的缺陷以及它是如何工作的,而不是解决它在哪里或如何被文档化或以其他方式指定的问题。
3条答案
按热度按时间chhqkbe11#
为
HttpServletRequest
自动配置代理的可能性是SpringMVC的一部分,遗憾的是它没有正确地文档化。你能找到的关于它的最好的信息是在
spring-web:3.0.0
的一些发行说明中。例如,看看release notes of 3.0.0.M4,特别是在这个问题上,Juergen Hoeller(String的主要开发者之一)谈到了这个版本以来它是如何工作的。另外,请随时检查源代码(WebApplicationContextUtils,RequestContextHolder),它们都有很好的文档记录。
vojdkbi02#
你得到的另一个答案涵盖了这个特性在哪里有(没有)文档记录;它还涵盖了这个特性的支持程度,因为它指出这个特性现在已经到了第三个主要版本,这使得它似乎不太可能很快消失。
不过,你让我对它的工作原理很感兴趣,所以我想我会把我的发现写下来。(不是构造函数注入),但它的很多内容也适用于其他用例。下面是详细的描述,链接到特定的代码行,但首先有一个执行摘要:几乎没有任何代码是专门针对
HttpServletRequest
的,而专门针对HttpServletRequest
的代码是涉及的最简单的代码。即使它这样做,我认为,如果您愿意在应用程序上下文预刷新方面做些手脚,您也可以自己重新创建它。所以,细节:当上下文刷新时,
WebApplicationContextUtils
转到DefaultListableBeanFactory
并说“如果有人问你他们在哪里可以得到ServletRequest,你可以使用这个RequestObjectFactory
回答他们“。稍后在同一上下文刷新期间,同一个bean工厂正在创建bean。当它到达@Component
时,它看到它需要自动连接HttpServletRequest
。因为这是一个接口,它从RequestObjectFactory
构造java.lang.reflect.Proxy
,并将 that 分配给@Autowired
字段。稍后,servlet容器接收对应用程序的servlet的请求,并通过应用程序的过滤器链发送它。该链中的一个过滤器是
RequestContextFilter
,它设置RequestContextHolder
的请求属性。请注意,该类使用ThreadLocal
s;由于每个请求都在不同的线程中处理,因此没有其他线程会改变请求属性。晚些时候(但仍在处理相同的请求),
@Component
的方法被调用。它又调用@Autowired HttpServletRequest
字段上的方法。该字段包含一个代理,所以方法调用被分派到创建代理时使用的调用处理程序。(参见上面两段的“构造”链接。)调用处理程序根据RequestObjectFactory
的getObject
方法返回的任何内容调用该方法;最后,该方法可以访问servlet容器设置的请求。cbjzeqam3#
根据spring-framework#26201的要求,这是从Spring 6.1.3开始记录的。
每个进样请求/会话直接引用:
作为工厂作用域的替代方案,Spring
WebApplicationContext
还支持HttpServletRequest
、HttpServletResponse
、HttpSession
、WebRequest
和(如果存在JSF)FacesContext
和ExternalContext
到Spring管理的bean中,只是通过类型-Spring通常会为这样的请求和会话对象注入代理,这具有优势在单例bean和可序列化bean中工作,类似于工厂范围bean的范围代理。