Spring:如何将 HttpServletRequest 注入到请求范围的 bean 中?

Posted

技术标签:

【中文标题】Spring:如何将 HttpServletRequest 注入到请求范围的 bean 中?【英文标题】:Spring: how do I inject an HttpServletRequest into a request-scoped bean? 【发布时间】:2011-03-20 05:44:05 【问题描述】:

我正在尝试在 Spring 中设置 request-scoped bean。

我已成功设置,因此每个请求都会创建一次 bean。现在,它需要访问 HttpServletRequest 对象。

由于每个请求都会创建一次 bean,我认为容器可以轻松地将请求对象注入到我的 bean 中。我该怎么做?

【问题讨论】:

【参考方案1】:

Spring 通过 ServletRequestAttributes 类型的 wrapper 对象公开当前的 HttpServletRequest 对象(以及当前的 HttpSession 对象)。这个包装器对象绑定到ThreadLocal,通过调用static方法RequestContextHolder.currentRequestAttributes()获得。

ServletRequestAttributes 提供了方法getRequest() 获取当前请求,getSession() 获取当前会话和其他方法获取存储在两个范围中的属性。以下代码虽然有点难看,但应该可以让您在应用程序的任何位置获取当前请求对象:

HttpServletRequest curRequest = 
((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
.getRequest();

注意RequestContextHolder.currentRequestAttributes()方法返回一个接口,需要类型转换为实现该接口的ServletRequestAttributes


Spring Javadoc: RequestContextHolder | ServletRequestAttributes

【讨论】:

注入是很好的解决方案,但我发现 MockMvc 测试注入 HttpServletRequest 的 Spring 验证器存在问题。因此,如果您希望模拟测试和生产代码都正常运行,这应该是选择。 @Neyko 为什么会这样?对于模拟测试(单元测试?),你可以注入模拟 HttpServletRequest 或任何你想要的......不是吗?或者你可以使用 MockHttpServletRequest 我猜? 在单例范围的服务实例中使用安全吗?【参考方案2】:

请求范围的 bean 可以与请求对象自动装配。

private @Autowired HttpServletRequest request;

【讨论】:

有老式的 XML 方法吗? 对我不起作用(spring mvc 3.1)-也许还有更多需要做的事情?采用 Samit 的解决方案。 问题是当您使用 MockMvc 和这种注入测试验证器时,您会遇到问题。在这种情况下可能会首选其他解决方案 也可以将 HttpServletRequest 自动装配到非请求范围的 bean 中,因为对于 HttpServletRequest,Spring 将生成一个代理 HttpServletRequest,它知道如何获取请求的实际实例。因此,即使您的控制器是单例范围的,自动连接请求也是安全的。 警告 Spring 自动装配将无法运行测试。【参考方案3】:

按照here 的建议,您也可以将HttpServletRequest 作为方法参数注入,例如:

public MyResponseObject myApiMethod(HttpServletRequest request, ...) 
    ...

【讨论】:

以上是关于Spring:如何将 HttpServletRequest 注入到请求范围的 bean 中?的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot-全局异常处理

在 Servlet-Spring 中强制浏览器下载

使用 Spring,我可以创建一个可选的路径变量吗?

Spring:如果 url 的安全性设置为无,则检查代码

Struts2的值栈和对象栈

关于DispatcherServlet的一些说明