如何让一个状态对 "session" 中的所有 beans 可用?
How to make a state available to all beans in a "session"?
我有以下设计。当客户端向服务器发出请求时,服务器会创建一个状态来保存各种信息。有各种无状态和有状态的 bean 需要读取和写入此状态。参考这张不专业的图:
ComputationCycle
class 是处理开始并分阶段进行的地方。在每个阶段,它都会调用其他 Manager
classes(其行为类似于实用程序 classes)来帮助计算(图表仅显示 1 个阶段)。正在从 CC class 和管理器读取和写入状态,两者都是无状态的。
State
包含有状态的 Employee
、Department
和 Car
classes(在一些不相关的数据结构中)。这些 classes 也可以调用 Manager
classes。这是通过一个简单的 @Inject Manager1
完成的。 CC 使用管理器的方式相同。
我的问题是如何从无状态 classes(以及 Car
、Department
和Employee
class也是,虽然我认为解决一个就会解决另一个)。我无法将有状态 bean 注入无状态 bean。那么在客户端发出请求并开始计算周期后,如何访问与此请求相关的状态?
一个解决方案是将状态传递给无状态 classes 中的每个方法,但这确实很麻烦而且臃肿,因为所有方法都会有一个 "idiotic" State 参数。
我怎样才能让这个设计按照我想要的方式工作?
买家当心,ThreadLocal 可能会执行您想要的操作,以及静态访问器。但是,如果您不非常小心地删除请求末尾的每个条目,则此 class 很容易导致内存泄漏。此外,您似乎正在使用 EJB;我假设它们都在同一个 JRE 中。在类似的情况下,我经常使用 ThreadLocal,而且我没有遇到任何问题。我使用 SerletContextListener 在上下文关闭时使对 ThreadLocal 的静态引用为空,尽管这在某些较旧的 Web 应用程序服务器上存在问题,因此我在尝试使用它之前确保 ThreadLocal 存在。
EJB 可以"talk" 跨服务器相互。听起来您的所有 EJB 都是本地的 运行 在相同的上下文中。
创建一个 class 来保存您的状态。
扩展 ThreadLocal——您可以匿名执行此操作——并将 initialValue() 覆盖为 return 您的 class.
的新实例
创建实用程序 class 以将 ThreadLocal 作为静态字段保存。不要将其设置为 final 创建调用 ThreadLocal.get() 和 remove() 的静态获取和删除方法。创建一个在上下文关闭时调用的静态 destroy() 方法——请参阅 ServletContextListener。
I can't inject a stateful bean into a stateless bean.
你绝对可以通过这种方式注入依赖。
如果有状态 bean 是@RequestScoped,则在该线程上对无状态 bean 的任何调用命中 CDI 注入的上下文引用(iow 代理)都会找到有状态 bean 的正确实例。
只要你使用 CDI,你就不需要为试图将东西藏在你自己的 threadlocals 中而烦恼。
我有以下设计。当客户端向服务器发出请求时,服务器会创建一个状态来保存各种信息。有各种无状态和有状态的 bean 需要读取和写入此状态。参考这张不专业的图:
ComputationCycle
class 是处理开始并分阶段进行的地方。在每个阶段,它都会调用其他 Manager
classes(其行为类似于实用程序 classes)来帮助计算(图表仅显示 1 个阶段)。正在从 CC class 和管理器读取和写入状态,两者都是无状态的。
State
包含有状态的 Employee
、Department
和 Car
classes(在一些不相关的数据结构中)。这些 classes 也可以调用 Manager
classes。这是通过一个简单的 @Inject Manager1
完成的。 CC 使用管理器的方式相同。
我的问题是如何从无状态 classes(以及 Car
、Department
和Employee
class也是,虽然我认为解决一个就会解决另一个)。我无法将有状态 bean 注入无状态 bean。那么在客户端发出请求并开始计算周期后,如何访问与此请求相关的状态?
一个解决方案是将状态传递给无状态 classes 中的每个方法,但这确实很麻烦而且臃肿,因为所有方法都会有一个 "idiotic" State 参数。
我怎样才能让这个设计按照我想要的方式工作?
买家当心,ThreadLocal 可能会执行您想要的操作,以及静态访问器。但是,如果您不非常小心地删除请求末尾的每个条目,则此 class 很容易导致内存泄漏。此外,您似乎正在使用 EJB;我假设它们都在同一个 JRE 中。在类似的情况下,我经常使用 ThreadLocal,而且我没有遇到任何问题。我使用 SerletContextListener 在上下文关闭时使对 ThreadLocal 的静态引用为空,尽管这在某些较旧的 Web 应用程序服务器上存在问题,因此我在尝试使用它之前确保 ThreadLocal 存在。
EJB 可以"talk" 跨服务器相互。听起来您的所有 EJB 都是本地的 运行 在相同的上下文中。
创建一个 class 来保存您的状态。
扩展 ThreadLocal——您可以匿名执行此操作——并将 initialValue() 覆盖为 return 您的 class.
的新实例创建实用程序 class 以将 ThreadLocal 作为静态字段保存。不要将其设置为 final 创建调用 ThreadLocal.get() 和 remove() 的静态获取和删除方法。创建一个在上下文关闭时调用的静态 destroy() 方法——请参阅 ServletContextListener。
I can't inject a stateful bean into a stateless bean.
你绝对可以通过这种方式注入依赖。
如果有状态 bean 是@RequestScoped,则在该线程上对无状态 bean 的任何调用命中 CDI 注入的上下文引用(iow 代理)都会找到有状态 bean 的正确实例。
只要你使用 CDI,你就不需要为试图将东西藏在你自己的 threadlocals 中而烦恼。