java 如何从 ServletContext 获取 HttpServletRequest?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31492792/
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-11-02 18:41:39  来源:igfitidea点击:

How can I get HttpServletRequest from ServletContext?

javaservlets

提问by JohnWinter

Is it possible to get HttpServletRequest from the ServletContext?

是否可以从 ServletContext 获取 HttpServletRequest?

回答by BalusC

Is it possible to get HttpServletRequest from the ServletContext?

是否可以从 ServletContext 获取 HttpServletRequest?

No.

不。

The ServletContextrepresents the application. The application can cover many sessions and requests. But you can't get the "currently running" request or session via the ServletContext. Detail on how servlets and scopes work can be found in this related answer: How do servlets work? Instantiation, sessions, shared variables and multithreading.

ServletContext代表的应用程序。该应用程序可以涵盖许多会话和请求。但是您无法通过ServletContext. 可以在此相关答案中找到有关 servlet 和范围如何工作的详细信息:servlet 如何工作?实例化、会话、共享变量和多线程

You're unfortunately not clear on the concrete functional requirement where you need this solution. You apparently have a ServletContextat hands somehow in an instance of the class of interest, but not a HttpServletRequest. It's hard to propose an answer showing the right way how to grab the HttpServletRequestin an instance of such class anyway. Decent MVC frameworks like JSF and Spring MVC have ways to grab the HttpServletRequestassociated with the current thread in any class you want.

不幸的是,您不清楚需要此解决方案的具体功能要求。您显然ServletContext在感兴趣的类的实例中以某种方式拥有一个,但没有一个HttpServletRequest. HttpServletRequest无论如何,很难提出一个答案,显示如何以正确的方式在此类类的实例中获取。像 JSF 和 Spring MVC 这样的体面的 MVC 框架有办法HttpServletRequest在你想要的任何类中获取与当前线程相关联的。

In case you're not using a MVC framework and thus can't use its facilities, then you can achieve this manually by storing the request (and response) as a ThreadLocal<T>in the current thread via a servlet filter.

如果您没有使用 MVC 框架,因此无法使用它的工具,那么您可以ThreadLocal<T>通过 servlet 过滤器将请求(和响应)存储为当前线程中的 a 来手动实现这一点。

Here's a kickoff example how such a thread local context class can look like:

这是这样一个线程本地上下文类的启动示例:

public final class YourContext implements AutoCloseable {

    private static ThreadLocal<YourContext> instance = new ThreadLocal<>();

    private HttpServletRequest request;
    private HttpServletResponse response;

    private YourContext(HttpServletRequest request, HttpServletResponse response) {
        this.request = request;
        this.response = response;
    }

    public static YourContext create(HttpServletRequest request, HttpServletResponse response) {
        YourContext context = new YourContext(request, response);
        instance.set(context);
        return context;
    }

    public static YourContext getCurrentInstance() {
        return instance.get();
    }

    @Override    
    public void close() {
        instance.remove();
    }

    // ... (add methods here which return/delegate the request/response).    
}

You can create (and close!!) it in a servlet filteras below.

您可以在servlet 过滤器中创建(并关闭!!)它,如下所示。

@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException {
    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) res;

    try (YourContext context = YourContext.create(request, response)) {
        chain.doFilter(request, response);
    }
}

Do note that closing is very important. Otherwise the thread will get polluted after it has done its job and will be recycled for a different request or even a completely different purpose. In case you aren't on Java 7 yet and thus can't use try-with-resourcesstatement as above, then use a try-finallyblock.

请注意,关闭非常重要。否则线程在完成工作后会被污染,并且会被回收用于不同的请求甚至完全不同的目的。如果您尚未使用 Java 7,因此无法使用上述try-with-resources语句,请使用try-finally块。

Then, in any artifact which is invoked by the same thread/request (i.e. other filters, any servlets, any beans/classes (in)directly invoked by those artifacts, etc), you can obtain the HttpServletRequestassociated with the current thread as below:

然后,在由同一线程/请求调用的任何工件中(即其他过滤器、任何 servlet、由这些工件直接调用的任何 bean/类(in)等),您可以获得HttpServletRequest与当前线程相关联的,如下所示:

YourContext context = YourContext.getCurrentInstance();
HttpServletRequest request = context.getRequest();
// ...

Or, better create a delegate method, depending on whatever you'd like to do with the current request, such as obtaining the request locale:

或者,更好地创建一个委托方法,这取决于您想对当前请求做什么,例如获取请求区域设置:

YourContext context = YourContext.getCurrentInstance();
Locale requestLocale = context.getRequestLocale();
// ...

As a real world example, Java EE's MVC framework JSFoffers exactly this possibility via FacesContext.

作为一个真实的例子,Java EE 的 MVC 框架JSF通过FacesContext.

FacesContext context = FacesContext.getCurrentInstance();
Locale requestLocale = context.getExternalContext().getRequestLocale();
// ...