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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1849089/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 23:17:30  来源:igfitidea点击:

Get the HttpServletRequest (request) object from Java code

javaservlets

提问by aseem

I need to get hold of the request object in Java code. I can't pass this object down to my code for certain reasons. Is there any way I can say something like: getCurrentHTTPServletRequest?

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

It is safe for me to assume that I am in a Servlet Context.

我可以安全地假设我处于 Servlet 上下文中。

采纳答案by Jon Skeet

Well you shouldpass it down if you need it. Anything else you do is going to be ugly, basically.

好吧,如果你需要它,你应该把它传下来。基本上,你做的任何其他事情都会变得丑陋。

You coulduse a ThreadLocalvariable - basically set the context for that particular thread when you get the request, and then fetch it later on. That will work so long as you only need to get at the request within the thread that's processing it - and so long as you don't do any funky asynchronous request handling. It's brittle though, for precisely those reasons.

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

However, I would stronglyadvise you to be explicit about your dependencies instead. Either pass the servlet request down, or just the bits that you need.

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

回答by Carl Smotricz

Assuming the top-level servlet really is taboo for some crazy business-related reason, there is still the option of defining a ServletFilterto pre-view the request and stuff it into a ThreadLocal. Assuming that the web.xmlis not also sacrosanct.

假设顶级 servlet 由于某些与业务相关的疯狂原因确实是禁忌,仍然可以选择定义 aServletFilter来预览请求并将其填充到 ThreadLocal 中。假设这web.xml也不是神圣不可侵犯的。

But I agree with Jon Skeet in that this would be very ugly. I'd code this up and then try to find a different job. :)

但我同意 Jon Skeet 的观点,因为这会非常丑陋。我会对此进行编码,然后尝试寻找不同的工作。:)

Actually, given the fact that a filter can totally wrest away control from the receiving servlet, you could use this technique to divert the code to a servlet of your own, do whatever you want, and THEN run the other, "official" servlet... or anything else along those lines. Some of those solutions would even allow you to deal correctly and robustly with your request data.

实际上,考虑到过滤器可以完全从接收 servlet 手中夺取控制权,您可以使用这种技术将代码转移到您自己的 servlet,做任何您想做的事情,然后运行另一个“官方”servlet。 .. 或任何其他类似的东西。其中一些解决方案甚至可以让您正确而稳健地处理您的请求数据。

回答by Bozho

Jon Skeet said practically everything, but one clarification to his advice "just the bits that you need" - if you need your request parameters passed down, but you don't need a dependency on HttpServletRequest, pass request.getParameterMap().

Jon Skeet 几乎说了所有,但对他的建议的一个澄清是“只是你需要的部分” - 如果你需要传递你的请求参数,但你不需要依赖于HttpServletRequest, pass request.getParameterMap()

And extending a bit on the ThreadLocaloption - you can have a Filterwhich handles all incoming requests, and sets the request in a

并在ThreadLocal选项上扩展一点- 你可以有一个Filter处理所有传入请求,并将请求设置为

public final static ThreadLocal<HttpServletRequest> httpServletRequestTL =
      new ThreadLocal<HttpServletRequest>();

Because you are setting it on each request (careful with the filter mapping), you won't have to worry about the servlet-container thread pool - you will always have the currentrequest.

因为您是在每个请求上设置它(小心过滤器映射),所以您不必担心 servlet-container 线程池 - 您将始终拥有当前请求。

P.S. this is the logic behind the spring utility proposed by skaffman - I join him recommending the stable component, rather than making your own.

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

回答by skaffman

Assuming you're not able to pass the request object down the call stack, then some kind of sharing mechanism becomes necessary, which is not ideal, but sometimes necessary.

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

Springprovides the RequestContextFilterfor just this purpose. It uses ThreadLocal, and allows the code to fetch the current request via RequestContextHolder. Note that this filter does notrequire you to use any other part of Spring:

Spring提供RequestContextFilter就是为了这个目的。它使用ThreadLocal,并允许代码通过RequestContextHolder获取当前请求。请注意,这个过滤器并不能要求你使用Spring的任何其他部分:

Servlet 2.3 Filter that exposes the request to the current thread, through both LocaleContextHolder and RequestContextHolder. To be registered as filter in web.xml.

This filter is mainly for use with third-party servlets, e.g. the JSF FacesServlet. Within Spring's own web support, DispatcherServlet's processing is perfectly sufficient.

Servlet 2.3 过滤器,通过 LocaleContextHolder 和 RequestContextHolder 向当前线程公开请求。在 web.xml 中注册为过滤器。

此过滤器主要用于第三方 servlet,例如 JSF FacesServlet。在 Spring 自己的 web 支持中,DispatcherServlet 的处理是完全足够的。

If you're going to use ThreadLocal, then better to use an existing, working solution, rather than risk bugs creeping in, which ThreadLocalcode is prone to.

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

回答by ZZ Coder

There is no servlet API to do this. However, Tomcat does provide an API call to do this,

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

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

This will get the last request passed to a servlet for servicing from the current thread.

这将获取传递给 servlet 以从当前线程提供服务的最后一个请求。

For this to work, the Tomcat must be in "Strict Servlet Compliance" mode. If not, you need to enable it by adding this JVM parameter:

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

org.apache.catalina.STRICT_SERVLET_COMPLIANCE=true