15

我们目前有一个 Web 应用程序加载一个 Spring 应用程序上下文,它实例化一堆业务对象、DAO 对象和 Hibernate。我们希望与另一个 Web 应用程序共享此堆栈,以避免具有相同对象的多个实例。

我们研究了几种方法;使用 JMX 或 JNDI 或使用 EJB3 公开对象。

不同的方法都有自己的问题,我们正在寻找一种轻量级的方法。

关于如何解决这个问题的任何建议?

编辑:我收到了要求我详细说明的评论,所以这里是:

我们要解决的主要问题是我们只想拥有一个 Hibernate 实例。这是由于在运行多个使用相同数据源的客户端应用程序时,Hibernate 的二级缓存失效的问题。此外,业务/DAO/Hibernate 堆栈越来越大,因此不复制它更有意义。

首先,我们试图研究如何单独将业务层暴露给其他 Web 应用程序,Spring 以少量 XML 的价格提供了 JMX 包装。但是,我们无法将 JMX 实体绑定到 JNDI 树,因此我们无法从 Web 应用程序中查找对象。

然后我们尝试将业务层直接绑定到 JNDI。尽管 Spring 没有为此提供任何方法,但使用 JNDITemplate 绑定它们也很简单。但这导致了几个新问题: 1) 安全管理器拒绝访问 RMI 类加载器,因此一旦我们尝试调用 JNDI 资源上的方法,客户端就会失败。2) 一旦安全问题得到解决,JBoss 抛出 IllegalArgumentException: object is not an instance of declaring class。稍微阅读一下就会发现我们需要 JNDI 资源的存根实现,但这似乎很麻烦(也许 Spring 可以帮助我们?)

我们还没有过多地研究 EJB,但是在前两次尝试之后,我想知道我们想要实现的目标是否完全可能。

总结一下我们想要实现的目标:一个 JBoss 实例,几个 Web 应用程序利用 DAO 层和 Hibernate 之上的一组业务对象。

最好的祝福,

尼尔斯

4

9 回答 9

5

Web 应用程序是否部署在同一台服务器上?

我不能代表 Spring,但使用 Session Bean 将业务逻辑移入 EJB 层很简单。

应用程序组织是直截了当的。逻辑进入会话 Bean,这些会话 Bean 捆绑在单个 jar 中,作为带有 ejb-jar.xml 文件的 Java EE 工件(在 EJB3 中,这可能实际上是空的)。

然后将您的实体类捆绑到一个单独的 jar 文件中。

接下来,您会将每个 Web 应用程序构建到它们自己的 WAR 文件中。

最后,所有的 jars 和 war 都捆绑到一个 Java EE EAR 中,并带有关联的 application.xml 文件(同样,这可能非常小,只需枚举 EAR 中的 jars)。

此 EAR 被批量部署到应用服务器。

每个 WAR 实际上都是独立的——它们自己的会话、上下文路径等。但它们共享公共 EJB 后端,因此您只有一个二级缓存。

您还可以使用本地引用和调用语义来与 EJB 对话,因为它们位于同一服务器中。这里不需要远程调用。

我认为这很好地解决了您遇到的问题,并且在带有 EJB 3 的 Java EE 5 中非常简单。

此外,据我了解,您仍然可以在大部分工作中使用 Spring,但我不是 Spring 人,所以我不能谈论细节。

于 2008-11-06T15:40:38.013 回答
4

春天的父母上下文呢?看看这篇文章:

http://springtips.blogspot.com/2007/06/using-shared-parent-application-context.html

于 2009-05-11T16:07:59.397 回答
3

Terracotta可能很适合这里(披露:我是 Terracotta 的开发人员)。Terracotta 在 JVM 级别透明地集群 Java 对象,并与 Spring 和 Hibernate 集成。它是免费和开源的。

正如您所说,使用 L2 缓存的多个客户端 Web 应用程序的问题是使这些缓存保持同步。使用 Terracotta,您可以集群单个 Hibernate L2 缓存。每个客户端节点都使用它的集群缓存副本,并且 Terracotta 保持同步。 这个链接解释更多。

至于您的业务对象,您可以使用 Terracotta 的Spring 集成来集群您的 bean - 每个 Web 应用程序可以共享集群 bean 实例,并且 Terracotta 透明地保持集群状态同步。

于 2008-11-06T16:44:38.040 回答
2

实际上,如果您想要一个轻量级解决方案并且不需要事务或集群,只需使用 Spring 对 RMI 的支持。它允许使用最新版本中的简单注释远程公开 Spring bean。请参阅http://static.springframework.org/spring/docs/2.0.x/reference/remoting.html

于 2008-11-07T21:02:14.967 回答
2

你应该看看 Terracotta Reference Web Application - Examinator。它拥有您正在寻找的大部分组件——它有 Hibernate、JPA 和 Spring 以及 MySQL 后端。

它已预先调整为最多可扩展到 16 个节点、20k 个并发用户。

在这里查看:http ://reference.terracotta.org/examinator

于 2008-12-02T21:11:23.340 回答
1

到目前为止,感谢您的回答。我们还没有完全做到这一点,但我们现在已经尝试了一些事情,并且更清楚地看到了事情。这是一个简短的更新:

似乎最可行的解决方案是 EJB。但是,这将需要对我们的代码进行一些更改,因此我们现在不会完全实现该解决方案。我几乎很惊讶我们还没有找到一些 Spring 特性来帮助我们。

我们还尝试了 JNDI 路由,它以所有共享接口都需要存根结束。考虑到一切都在同一台服务器上,这感觉很麻烦。

昨天,我们在 JMX 方面取得了小小的突破。尽管 JMX 绝对不适合这种用途,但我们已经证明它可以做到——无需更改代码和最少的 XML(非常感谢 Spring 提供的 MBeanExporter 和 MBeanProxyFactoryBean)。这种方法的主要缺点是性能和我们的域类必须通过 JBoss 的 server/lib 文件夹共享的事实。即,我们必须从我们的 WAR 中删除一些依赖项并将它们移动到 server/lib,否则当业务层从我们自己的域模型返回对象时,我们会得到 ClassCastException。我完全理解为什么会发生这种情况,但这对于我们想要实现的目标并不理想。

我认为是时候进行一些更新了,因为看起来最好的解决方案需要一些时间来实施。完成这项工作后,我将在这里发布我们的发现。

于 2008-11-11T07:50:47.633 回答
1

Spring 确实有一个您可能感兴趣的集成点: EJB 3 injection 拦截器。这使您能够从 EJB 访问 spring bean。

于 2009-05-11T16:13:56.283 回答
0

我不确定您要解决什么问题;在一天结束时,每个 jvm 要么具有对象的复制实例,要么具有表示存在于另一个(逻辑)服务器上的对象的存根。

您可以设置第三个“业务逻辑”服务器,该服务器具有您的两个 Web 应用程序可以调用的远程 API。典型的解决方案是使用 EJB,但我认为 spring 在其堆栈中内置了远程处理选项。

另一种选择是使用某种形式的共享缓存架构......它将在服务器之间同步对象更改,但您仍然有两组实例。

于 2008-11-06T18:44:00.390 回答
-1

看看JBossCache。它允许您在多个 JVM 实例(相同或不同)之间轻松共享/复制数据映射。它易于使用,并且有很多线级协议选项(TCP、UDP 多播等)。

于 2008-11-06T15:29:11.203 回答