我有以下请求上下文类,该类用于收集某些信息以供将来在Servlet过滤器中处理:
public class ApplicationRequestContext {
private static final ThreadLocal<AppRequest> tl = new ThreadLocal<AppRequest>();
public static void begin(HttpServletRequest httpRequest) {
tl.set(getAppRequest(httpRequest));
}
public static void finish() {
tl.remove();
}
}
getAppRequest(httpRequest)
仅返回一个对象。然后在Servlet过滤器中...public class ApplicationServletFilter implements javax.servlet.Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
try {
ApplicationRequestContext.begin(httpRequest);
/* other stuff */
chain.doFilter(httpRequest, httpResponse);
} catch (Exception e) { /* … */ }
finally {
ApplicationRequestContext.finish();
}
}
}
我想知道,此设置是否可能有多个传入请求,以可能覆盖彼此的数据(
getAppRequest(httpRequest)
对象显然将是唯一的)?这甚至是线程安全的吗? 最佳答案
您必须记住,每个Thread
都有自己的ThreadLocal
-实际上,确切地说,是自己的ThreadLocal.ThreadLocalMap
(我使用的是OpenJDK作为示例)。
当名为ThreadLocal
的tl
调用其set()
method时,它基本上会创建一个新的ThreadLocalMap
并以tl
作为对create a ThreadLocalMap.Entry
的键的引用。
由于每个Servlet请求都使用一个唯一线程(从托管线程池或生成一个新线程,并且没有两个Servlet线程处理相同的请求),因此tl.set()
拥有该ThreadLocal
的新创建的作为对该Servlet ThreadLocalMap
的Thread
的引用。
现在,当ThreadLocal.ThreadLocalMap
is called时,我们只需获取Servlet tl.get()
的Thread
,然后执行lookup with ThreadLocalMap
以获取我们输入的值,例如ThreadLocalMap.getEntry()
。
这里要记住的要点是,是的,您正在使用一个名为getAppRequest(httpRequest)
的单个ThreadLocal
对象,但是每个tl
在这种情况下都是Servlet容器用来处理每个请求(包括其过滤器)的线程(s),将具有其自己的Thread
,并带有对此ThreadLocal.ThreadLocalMap
对象的[弱]引用作为其键。
因此,ThreadLocal
只是t1
(ThreadLocal.ThreadLocalMap.Entry
)表中的键,用于获取tl.ThreadLocalMap.Entry
的Thread
,这对于该线程是唯一的。因此,它是线程安全的,并且这些LocalThread.ThreadLocalMap
和begin()
调用基本上将数据放入每个finish()
中。
关于java - 该LocalThread可以覆盖其他Servlet请求的数据吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57154698/