从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。 ..或沿着这些方向的任何其他东西。 其中一些解决方案甚至可以让您正确,可靠地处理您的请求数据。