【问题标题】:How to make a state available to all beans in a "session"?如何使“会话”中的所有 bean 都可以使用状态?
【发布时间】:2017-07-22 01:34:03
【问题描述】:

我有以下设计。当客户端向服务器发出请求时,服务器会创建一个包含各种信息的状态。有各种无状态和有状态 bean 需要读取和写入此状态。参考这张不专业的图:

ComputationCycle 类是处理开始和分阶段工作的地方。在每个阶段,它都会调用其他 Manager 类(其行为类似于实用程序类)来帮助计算(图表仅显示 1 个阶段)。状态正在从 CC 类和管理器中读取和写入,两者都是无状态的。

State 包含有状态的EmployeeDepartmentCar 类(在一些不相关的数据结构中)。这些类也可以调用Manager 类。这是由一个简单的@Inject Manager1 完成的。与 CC 使用管理器的方式相同。

我的问题是如何从无状态类(以及 CarDepartmentEmployee 类中访问有状态状态(及其包含的类),尽管我认为解决一个将解决另一个) .我无法将有状态 bean 注入无状态 bean。那么在客户端发出请求并开始计算周期后,如何访问与该请求相关的状态?

一种解决方案是将状态传递给无状态类中的每个方法,但这确实很麻烦和臃肿,因为所有方法都会到处都有一个“愚蠢的”状态参数。

我怎样才能让这个设计按照我想要的方式工作?

【问题讨论】:

  • 也许我误导了您的设计,但是将@Stateful 注入@Stateless 不是正确的方法。你最终会得到不可预测的结果。正如其他人指出的那样,使用@Singleton 可能会获得更好的结果。
  • @Leonardo covener 回答说我可以这样做。他错了吗?
  • 网络上有很多资源表明这是一种错误的方法。这是一个堆栈溢出问题,回答了您的疑问:access existing instance stateful inside stateless, java ee 6
  • @Leonardo 我在他的回答 cmets 中也指出了这一点。他建议@Inject 而不是@EJB 以及@RequestScoped 应该可以工作。另外,这是ee7。你不同意他的回答吗?

标签: java jakarta-ee ejb cdi


【解决方案1】:

我无法将有状态 bean 注入无状态 bean。

你完全可以通过这种方式注入依赖。

如果有状态 bean 是 @RequestScoped,则在该线程上对无状态 bean 的任何调用都会命中 CDI 注入的上下文引用(iow 代理),将找到通往有状态 bean 正确实例的途径。

只要您使用 CDI,您就无需费心尝试将内容隐藏在自己的 threadlocals 中。

【讨论】:

  • 这是个好消息,但我阅读了this Q&A。错了吗?
  • 它指的是旧的 EE 注入和 EJB 中的无状态/有状态。所以,我认为这至少在你的上下文中是错误的。不幸的是,我不是每天都在使用 EE,所以我无法快速验证或在示例中演示它。但对我来说,让 bean 进入长寿命范围是完全没问题的。
  • 如果你的无国籍人像单身,这里有一个相关的q stackoverflow.com/questions/35624313/…
  • 我不认为我的无状态应该是单例,因为使它们无状态的全部意义在于池中的任何实例都可以应答任何调用,因此它对性能更好。如果我让他们成为单身人士,我将不得不等待它每次发布。我认为这就是它的工作原理。
  • 啊,我也明白你对这些版本的意思——他们使用的是@EJB,而不是@Inject。没想到差别这么大。
【解决方案2】:

买家要小心,ThreadLocal 可能会做你想做的事,还有一个静态访问器。但是,如果您在请求结束时不非常小心地删除每个条目,则此类很容易导致内存泄漏。此外,您似乎正在使用 EJB;我假设它们都在同一个 JRE 中。我在类似的情况下使用了相当多的 ThreadLocal,我没有遇到任何问题。当上下文关闭时,我使用 SerletContextListener 将 ThreadLocal 的静态引用清空,尽管这在一些较旧的 Web 应用服务器上存在问题,因此我在尝试使用它之前确保 ThreadLocal 存在。

EJB 可以跨服务器“对话”。听起来你所有的 EJB 都在本地运行在同一个上下文中。

创建一个保存你的状态的类。

扩展 ThreadLocal - 您可以匿名执行此操作 - 并覆盖 initialValue() 以返回您的类的新实例。

创建一个实用程序类以将 ThreadLocal 作为静态字段保存。不要让它最终创建调用 ThreadLocal.get() 和 remove() 的静态获取和删除方法。创建一个在上下文关闭时调用的静态 destroy() 方法——请参阅 ServletContextListener。

【讨论】:

  • “相同的 JRE”是什么意思?这是在 JBoss 中运行的 WAR。请求使用 JAX-RS 进入,它会产生一个线程,上面所有的事情都会发生。事实上,每个这样的线程的状态都是独一无二的,所以 ThreadLocal 似乎是正确的。你能解释或展示我将如何使用它吗?
猜你喜欢
  • 2013-08-02
  • 1970-01-01
  • 2015-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-18
  • 2010-12-13
  • 2023-04-03
相关资源
最近更新 更多