Servlet 3 spec 和 ThreadLocal

据我所知,Servlet 3 规范引入了异步处理功能。除此之外,这意味着同一线程可以并且将被重新用于处理另一个并发的HTTP请求。这不是革命性的,至少对于以前与NIO合作过的人来说是这样。

无论如何,这导致了另一件重要的事情:没有ThreadLocal变量作为请求数据的临时存储。因为如果同一线程突然成为不同 HTTP 请求的承载线程,则请求本地数据将暴露给另一个请求。

所有这些都是我基于阅读文章的纯粹推测,我没有时间玩任何Servlet 3实现(Tomcat 7,GlassFish 3.0.X等)。

所以,问题:

  • 我假设这将不再是保留请求数据的便捷黑客行为是否正确?ThreadLocal
  • 有没有人玩过Servlet 3的任何实现,并尝试使用s来证明上述内容?ThreadLocal
  • 除了在HTTP会话中存储数据之外,您还有其他类似的易于访问的黑客攻击吗?

编辑:不要误会我的意思。我完全理解危险和成为黑客。事实上,我总是建议不要在类似的上下文中使用它。但是,信不信由你,线程上下文的使用频率远远超过你的想象。一个很好的例子是Spring's,根据其Javadoc:ThreadLocalOpenSessionInViewFilter

此筛选器使休眠会话可通过当前线程使用,事务管理器将自动检测到该线程。

这不是严格意义上的(没有检查来源),但听起来已经令人震惊。我可以想到更多类似的场景,而大量的Web框架使这更有可能发生。ThreadLocal

简而言之,许多人在这次黑客攻击之上建造了他们的沙堡,无论是否有意识。因此,斯蒂芬的答案是可以理解的,但并不完全是我所追求的。我想得到确认,是否有人实际上已经尝试过能够重现失败的行为,因此这个问题可以用作其他被同一问题困住的人的参考点。


答案 1

异步处理不应该打扰你,除非你明确要求它。

例如,如果 servlet 或请求的过滤器链中的任何过滤器未标有 .因此,您仍然可以对常规请求使用常规做法。<async-supported>true</async-supported>

当然,如果您确实需要异步处理,则需要使用适当的实践。基本上,当异步处理请求时,其处理被分解为多个部分。这些部分不共享线程本地状态,但是,您仍然可以在每个部分中使用线程本地状态,尽管您必须手动管理部件之间的状态。


答案 2

(警告:我没有详细阅读Servlet 3规范,所以我不能肯定地说该规范说明了您认为它的作用。我只是假设它确实如此...)

我假设ThreadLocal将不再是一个方便的黑客来保留请求数据,我是正确的吗?

使用总是一种糟糕的方法,因为当工作线程完成一个请求并在另一个请求上启动时,您总是冒着信息泄露的风险。将内容作为属性存储在对象中始终是一个更好的主意。ThreadLocalServletRequest

现在,您只是有了另一个理由以“正确”的方式做到这一点。

有没有人玩过Servlet 3的任何实现,并尝试使用ThreadLocals来证明上述内容?

这不是正确的方法。它只告诉您在测试的特定情况下特定实现的特定行为。你不能一概而论。

正确的方法是假设,如果规范说它可以...并设计您的Web应用程序以考虑它。

(不要害怕!显然,在这种情况下,默认情况下不会发生这种情况。Web 应用必须显式启用异步处理功能。如果您的代码充斥着线程局部变量,建议您不要这样做...)

除了在HTTP会话中存储数据之外,您还可以建议任何其他类似的易于访问的黑客攻击。

不。唯一正确的答案是将特定于请求的数据存储在 ServletRequest 或 ServletResponse 对象中。即使将其存储在HTTP会话中也可能是错误的,因为对于给定会话,可以同时有多个请求处于活动状态。