从Java代码获取HttpServletRequest(请求)对象

我需要在Java代码中获取请求对象。 出于某些原因,我无法将此对象传递给我的代码。 有什么方法可以说: getCurrentHTTPServletRequest

我可以安全地假设我处于Servlet环境中。

那么你应该把它传下来,如果你需要的话。 你做的其他事情基本上都是丑陋的。

可以使用ThreadLocal变量 – 在获取请求时基本上为该特定线程设置上下文,然后稍后再获取它。 只要您只需要处理正在处理它的线程中的请求,并且只要您不进行任何时髦的异步请求处理,这将起作用。 然而,它很脆弱,正是出于这些原因。

但是,我强烈建议您明确说明您的依赖项。 要么传递servlet请求,要么只传递你需要的位。

假设您无法将请求对象传递给调用堆栈,则需要某种共享机制,这不是理想的,但有时是必要的。

Spring为此提供了RequestContextFilter 。 它使用ThreadLocal ,并允许代码通过RequestContextHolder获取当前请求。 请注意,此filter要求您使用Spring的任何其他部分:

Servlet 2.3通过LocaleContextHolder和RequestContextHolder将请求公开给当前线程的filter。 要在web.xml中注册为filter。

此filter主要用于第三方servlet,例如JSF FacesServlet。 在Spring自己的Web支持中,DispatcherServlet的处理就足够了。

如果您打算使用ThreadLocal ,那么最好使用现有的,有效的解决方案,而不是冒险陷入漏洞, ThreadLocal代码容易出错。

Jon Skeet几乎说了一切,但是对他的建议进行了一次澄清“只需要你需要的位” – 如果你需要传递请求参数,但是你不需要依赖HttpServletRequest ,那就传递request.getParameterMap()

并在ThreadLocal选项上扩展一点 – 您可以拥有一个处理所有传入请求的Filter ,并在一个。中设置请求

 public final static ThreadLocal httpServletRequestTL = new ThreadLocal(); 

因为您在每个请求上设置它(小心使用filter映射),所以您不必担心servlet容器线程池 – 您将始终拥有当前请求。

PS这是skaffman提出的弹簧实用程序背后的逻辑 – 我和他一起推荐稳定的组件,而不是制作自己的组件。

没有servlet API可以做到这一点。 但是,Tomcat确实提供了一个API调用来执行此操作,

 HttpServletRequest request = (HttpServletRequest)org.apache.catalina.core.ApplicationFilterChain.getLastServicedRequest(); 

这将把最后一个请求传递给servlet,以便从当前线程进行服务。

为此,Tomcat必须处于“严格的Servlet合规性”模式。 如果没有,则需要通过添加此JVM参数来启用它:

 org.apache.catalina.STRICT_SERVLET_COMPLIANCE=true 

假设顶级servlet确实是一些与业务相关的疯狂原因的禁忌,那么仍然可以选择定义ServletFilter来预先查看请求并将其填充到ThreadLocal中。 假设web.xml不是神圣不可侵犯的。

但我同意Jon Skeet的说法,这会非常难看。 我会对此进行编码,然后尝试找一份不同的工作。 🙂

实际上,鉴于filter可以完全取消接收servlet的控制,你可以使用这种技术将代码转移到你自己的servlet,做你想做的任何事情,然后运行另一个“官方”servlet。 ..或沿着这些方向的任何其他东西。 其中一些解决方案甚至可以让您正确,可靠地处理您的请求数据。