我在J2EE项目中看到了以下代码。
public class RequestContext {
private final static ThreadLocal<RequestContext> contexts = new ThreadLocal<RequestContext>();
/* Initialization */
public static RequestContext begin(ServletContext ctx, HttpServletRequest req, HttpServletResponse res) {
RequestContext rc = new RequestContext();
..
contexts.set(rc);
return rc;
}
public static RequestContext get(){
return contexts.get();
}
}
看来通过ThreadLocal
和静态get
,我们可以轻松获取当前线程的当前RequestContext。
但是,这是一种常见做法吗?这是一种正确的方法吗?是否有可能发生内存泄漏?
Why the object created by ClassLoader do not have chance to garbage collect itself
答案 0 :(得分:2)
我在一些项目中看到过它,用于存储一些基础设施项目(例如用户唯一标识符),以跟踪特定会话的日志消息。
必须小心处理,因为如果您的代码在Java EE服务器上运行,则将汇集线程并将其重用于其他会话。如果你没有重置ThreadLocal状态,你最终会遇到意外数据干扰的麻烦(比如在一个Thread运行中的值与旧运行相对应)。
所以,在你的代码中我想念这个方法:
public static void reset() {
contexts.remove();
}
诅咒,它必须在某处使用:通常在初始化它的同一个地方(也许是WebApp过滤器?)
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
RequestContext.begin(ctx, request, response); //initialize
try {
//other stuff here
//forward request to next filter, or the servlet itself
chain.doFilter(request, response);
} finally {
RequestContext.reset();
}
}