据我所知,Servlet 3规范引入了异步处理特性。除其他外,这将意味着同一个线程可以并且将被重用来处理另一个并发的HTTP请求。这并不是革命性的,至少对于以前和NIO合作过的人来说是这样的。
无论如何,这导致了另一件重要的事情:no 作为请求数据的临时存储。因为如果同一个线程突然成为另一个HTTP请求的载体线程,请求-本地数据将暴露在另一个请求中。
所有这些都是我基于阅读文章的推测,我没有时间使用任何Servlet 3实现(Tomcat 7、GlassFish 3.0.X等)。
所以,问题是:
ThreadLocal将不再是保存请求数据的方便的黑客?ThreadLocal来证明上述?f 216
编辑:没有误解我。我完全理解危险和ThreadLocal是一个黑客。事实上,我总是建议不要在类似的情况下使用它。然而,不管你信不信由你,线程上下文的使用比你想象的要频繁得多。一个很好的例子是Spring的OpenSessionInViewFilter,根据它的Javadoc:
此过滤器使Hibernate会话通过当前线程可用,事务管理器将自动检测该线程。
这并不是严格意义上的ThreadLocal (还没有检查源代码),但听起来已经令人震惊了。我可以想到更多类似的场景,而丰富的web框架使得这种可能性更大。
简单地说,很多人在这次黑客攻击的基础上建造了他们的沙堡,不管有没有意识。因此,斯蒂芬的回答是可以理解的,但并不完全是我想要的。我想确认是否有人真的尝试过,和能够再现的失败行为,因此这个问题可以用作其他被同样问题困住的人的参考点。
发布于 2011-02-21 00:00:14
(请注意:我还没有详细阅读Servlet 3规范,所以我不能肯定规范说出了您认为它所做的事情。我只是假设它确实.)
--我是否正确地认为,ThreadLocal将不再是保存请求数据的方便黑客?
使用ThreadLocal总是一种糟糕的方法,因为当一个工作线程完成一个请求而启动另一个请求时,您总是冒着信息泄漏的风险。将内容作为属性存储在ServletRequest对象中总是一个更好的主意。
现在,你有了另一个理由,用“正确”的方式去做。
有没有人玩过Servlet 3的任何一种实现,并试图使用ThreadLocals来证明上面的这些?
这不是正确的方法。它只告诉您在测试的特定情况下特定实现的特定行为。你不能概括。
正确的方法是假设它有时会发生如果规范说它可以.并设计你的网页应用程序来考虑它。
(不要害怕!显然,在这种情况下,默认情况下不会发生这种情况。您的webapp必须显式地启用异步处理功能。如果代码中充斥着线程局部变量,则建议您不要这样做.)
除了在HTTP中存储数据外,还有其他类似的易于访问的黑客您可能会提供建议。
不是的。唯一正确的答案是在ServletRequest或ServletResponse对象中存储特定于请求的数据。即使将它存储在HTTP会话中也可能是错误的,因为对于给定的会话,可以同时激活多个请求。
发布于 2011-03-02 04:02:53
注:黑客紧随其后。使用时要小心,否则就不要使用。
只要您继续了解代码在哪个线程中执行,就没有理由不能安全地使用ThreadLocal。
try {
tl.set(value);
doStuffUsingThreadLocal();
} finally {
tl.remove();
}这并不是说您的调用堆栈是随机关闭的。见鬼,如果您想在调用堆栈中设置深入的ThreadLocal值,然后进一步使用,您也可以对此进行黑客攻击:
public class Nasty {
static ThreadLocal<Set<ThreadLocal<?>>> cleanMe =
new ThreadLocal<Set<ThreadLocal<?>>>() {
protected Set<ThreadLocal<?>> initialValue() {
return new HashSet<ThreadLocal<?>>();
}
};
static void register(ThreadLocal<?> toClean) {
cleanMe.get().add(toClean);
}
static void cleanup() {
for(ThreadLocal<?> tl : toClean)
tl.remove();
toClean.clear();
}
}然后,在设置ThreadLocals时注册它们,并在某个地方使用finally子句进行清理。这都是你不应该做的可耻的傻事。对不起,我写的太晚了。
发布于 2011-03-02 09:56:48
我仍然想知道为什么人们使用腐朽的servlets来实现他们的servlet。我所做的:
HttpRequestHandler,它有用于请求、响应的私有字段和一个可以抛出异常的handle()方法,再加上一些实用方法来获取/设置参数、属性等。我很少需要5%-10%的servlet,所以这不是听起来那么多工作。在servlet处理程序中,创建这个类的一个实例,然后忘记servlet。HttpRequestHandler。这样,我就不需要servlet环境来测试我的代码了.这解决了我所有的问题,因为我可以在init()方法中获得DB会话和其他东西,或者在servlet和真正的处理程序之间插入一个工厂来执行更复杂的事情。
https://stackoverflow.com/questions/5060823
复制相似问题