我需要在Java代码中获取请求对象。出于某些原因,我无法将此对象传递给我的代码。有什么方法可以说:getCurrentHTTPServletRequest
?
我可以安全地假设我处于Servlet环境中。
答案 0 :(得分:18)
如果你需要,你应该传递它。你做的任何其他事情都会变得很丑陋。
你可以使用ThreadLocal
变量 - 基本上在你收到请求时设置该特定线程的上下文,然后再获取它。只要您只需要处理正在处理它的线程中的请求,并且只要您不执行任何时髦的异步请求处理,这将起作用。但是,正是因为这些原因,它很脆弱。
但是,我会强烈建议您明确说明您的依赖关系。要么传递servlet请求,要么只传递你需要的位。
答案 1 :(得分:9)
假设你无法将请求对象传递给调用堆栈,那么就需要某种共享机制,这不是理想的,但有时是必要的。
Spring仅为此目的提供了RequestContextFilter。它使用ThreadLocal
,并允许代码通过RequestContextHolder获取当前请求。请注意,此过滤器不要求您使用Spring的任何其他部分:
Servlet 2.3公开的过滤器 请求到当前线程,通过 LocaleContextHolder和 RequestContextHolder。要注册 作为web.xml中的过滤器。
此过滤器主要用于 第三方servlet,例如JSF FacesServlet的。在Spring自己的网站中 支持,DispatcherServlet的 处理就足够了。
如果您要使用ThreadLocal
,那么最好使用现有的,有效的解决方案,而不是冒险陷入错误,ThreadLocal
代码容易出错。
答案 2 :(得分:4)
HttpServletRequest
,则传递{ {1}}。
在request.getParameterMap()
选项上稍微扩展一下 - 你可以有ThreadLocal
处理所有传入的请求,并在
Filter
因为您在每个请求上设置它(小心使用过滤器映射),所以您不必担心servlet容器线程池 - 您将始终拥有当前请求。 / p>
P.S。这是skaffman提出的spring实用程序背后的逻辑 - 我和他一起推荐稳定的组件,而不是制作自己的组件。
答案 3 :(得分:4)
没有servlet API可以做到这一点。但是,Tomcat确实提供了一个API调用来执行此操作,
HttpServletRequest request = (HttpServletRequest)org.apache.catalina.core.ApplicationFilterChain.getLastServicedRequest();
这会将最后一个请求传递给servlet,以便从当前线程进行维护。
为此,Tomcat必须处于“Strict Servlet Compliance”模式。如果没有,则需要通过添加此JVM参数来启用它:
org.apache.catalina.STRICT_SERVLET_COMPLIANCE=true
答案 4 :(得分:0)
假设顶级servlet确实是一些与业务相关的疯狂原因的禁忌,那么仍然可以选择定义ServletFilter
来预先查看请求并将其填充到ThreadLocal中。假设web.xml
也不是神圣不可侵犯的。
但我同意Jon Skeet的说法,这会非常难看。我会对此进行编码,然后尝试找一份不同的工作。 :)
实际上,鉴于过滤器可以完全夺走接收servlet的控制权,你可以使用这种技术将代码转移到你自己的servlet,做你想做的任何事情,然后运行另一个,“官方“servlet ......或者其他任何东西。其中一些解决方案甚至可以让您正确,可靠地处理您的请求数据。