是否可以从ServletContext获取HttpServletRequest?
答案 0 :(得分:7)
是否可以从ServletContext获取HttpServletRequest?
没有。
ServletContext
代表应用程序。该应用程序可以涵盖许多会话和请求。但是您无法通过ServletContext
获取“当前正在运行”的请求或会话。有关servlet和范围如何工作的详细信息,请参阅此相关答案:How do servlets work? Instantiation, sessions, shared variables and multithreading。
遗憾的是,您不清楚需要此解决方案的具体功能要求。你在某个感兴趣的类的实例中显然有一个ServletContext
,但不是HttpServletRequest
。很难提出一个答案,显示正确的方法如何在这样的类的实例中抓取HttpServletRequest
。像JSF和Spring MVC这样的体面MVC框架有办法在你想要的任何类中获取与当前线程相关联的HttpServletRequest
。
如果您没有使用MVC框架因此无法使用其功能,那么您可以通过servlet将请求(和响应)作为ThreadLocal<T>
存储在当前线程中来手动实现过滤
这是一个启动示例,这个线程本地上下文类的外观如何:
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).
}
您可以在servlet filter中创建(并关闭!!),如下所示。
@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);
}
}
请注意,收盘非常重要。否则线程在完成其工作后将被污染,并将被回收用于不同的请求甚至完全不同的目的。如果您尚未使用Java 7,因此无法使用上述try-with-resources语句,请使用try-finally
块。
然后,在由同一个线程/请求调用的任何工件(即其他过滤器,任何servlet,由这些工件直接调用的任何bean / classes(in)等)中,您可以获得HttpServletRequest
与当前线程相关联如下:
YourContext context = YourContext.getCurrentInstance();
HttpServletRequest request = context.getRequest();
// ...
或者,更好地创建委托方法,具体取决于您要对当前请求做什么,例如获取请求区域设置:
YourContext context = YourContext.getCurrentInstance();
Locale requestLocale = context.getRequestLocale();
// ...
作为一个真实世界的例子,Java EE的MVC框架JSF通过FacesContext
提供了这种可能性。
FacesContext context = FacesContext.getCurrentInstance();
Locale requestLocale = context.getExternalContext().getRequestLocale();
// ...