如何从ServletContext获取HttpServletRequest?

Joh*_*ter 0 java servlets

是否可以从ServletContext获取HttpServletRequest?

Bal*_*usC 7

是否可以从ServletContext获取HttpServletRequest?

没有.

ServletContext代表的应用程序.该应用程序可以涵盖许多会话和请求.但是你无法通过获得"当前正在运行"的请求或会话ServletContext.有关servlet和作用域如何工作的详细信息可以在相关的答案中找到:servlet如何工作?实例化,会话,共享变量和多线程.

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

如果您没有使用MVC框架因此无法使用其功能,那么您可以ThreadLocal<T>通过servlet过滤器将请求(和响应)存储为当前线程中来手动实现此功能.

这是一个启动示例,这个线程本地上下文类是如何看起来的:

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).    
}
Run Code Online (Sandbox Code Playgroud)

您可以在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);
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,结束非常重要.否则线程在完成其工作后将被污染,并将被回收用于不同的请求甚至完全不同的目的.如果您还没有使用Java 7,因此无法使用上面的try-with-resources语句,那么请使用try-finally块.

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

YourContext context = YourContext.getCurrentInstance();
HttpServletRequest request = context.getRequest();
// ...
Run Code Online (Sandbox Code Playgroud)

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

YourContext context = YourContext.getCurrentInstance();
Locale requestLocale = context.getRequestLocale();
// ...
Run Code Online (Sandbox Code Playgroud)

作为一个真实的例子,Java EE的MVC框架JSF提供了这种可能性FacesContext.

FacesContext context = FacesContext.getCurrentInstance();
Locale requestLocale = context.getExternalContext().getRequestLocale();
// ...
Run Code Online (Sandbox Code Playgroud)