English 中文(简体)
在使用JBoss和Spring的Java Web应用程序之间共享业务对象实例的最佳方法是什么?
原标题:
  • 时间:2008-11-06 09:54:26
  •  标签:

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

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

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

有任何解决此问题的建议吗?

编辑:我收到了要求我稍微详细解释一点的评论,所以在这里我就开始解释:

我们想要解决的主要问题是我们希望只有一个 Hibernate 实例。这是由于在使用相同数据源的多个客户端应用程序运行时,Hibernate 的第二级缓存无效的问题。另外,业务/DAO/Hibernate 技术栈越来越大,因此不重复它更加明智。

首先,我们尝试查看仅暴露业务层如何与其他Web应用程序交互,Spring提供JMX封装以极小的XML代价。但是,我们无法将JMX实体绑定到JNDI树,因此我们无法从Web应用程序中查找对象。

然后我们尝试将业务层直接绑定到JNDI。尽管Spring没有提供任何方法进行此操作,但使用JNDITemplate进行绑定也很简单。但是这引发了一些新问题:1)安全管理器拒绝访问RMI类加载器,因此一旦我们尝试在JNDI资源上调用方法,客户端就失败了。2)一旦解决了安全问题,JBoss抛出了IllegalArgumentException:对象不是声明类的实例。稍微阅读一下发现,我们需要JNDI资源的存根实现,但这似乎很麻烦(也许Spring可以帮助我们吗?)。

我们还没有深入研究EJB,但在前两次尝试后,我在想我们所尝试的是否可能实现。

总体来说,我们所试图实现的是:一个JBoss实例,多个Web应用程序,在DAO层和Hibernate之上利用一套业务对象的堆栈。

最好的祝愿,

尼尔斯

最佳回答

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

我不能代表Spring发言,但是使用Session Beans将业务逻辑移动到EJB层非常简单。

应用程序的组织方式很简单。逻辑放入会话Bean中,这些会话Bean作为Java EE工件捆绑在一个单独的jar文件中,其中包含一个ejb-jar.xml文件(在EJB3中,这可能基本为空)。

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

接下来,您将为每个Web应用程序构建一个自己的WAR文件。

最后,所有的jar包和war包都被捆绑成一个Java EE EAR包,附带有相应的application.xml文件(同样地,这个文件可能非常简单,只是简单地列出EAR包中的jar包)。

这个EAR文件是批发部署到应用服务器上的。

每个WAR都是有效独立的-它们有自己的会话、自己的上下文路径等等。但它们共享常见的EJB后端,因此您只有一个单独的第二级缓存。

您还可以使用本地引用和调用语义与 EJB 进行通信,因为它们位于同一服务器上。这里不需要远程调用。

我认为这很好地解决了你所遇到的问题,而且在 Java EE 5 中使用 EJB 3 很简单。

此外,据我了解,您仍然可以在很多工作中使用Spring,但我不是一位Spring专家,因此无法就详情发表意见。

问题回答

What about spring parentContext? Check out this article:

使用共享的父应用程序上下文

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

正如你所说,多个客户端Web应用程序使用L2缓存的问题是保持这些缓存同步。通过Terracotta,您可以集群单个Hibernate L2缓存。每个客户端节点都使用其聚集缓存的副本,并且Terracotta使其保持同步。此链接提供更多信息:http://www.terracotta.org/web/display/orgsite/Hibernate+Integration#HibernateIntegration-UsingSecondLevelCacheorDetachedInstancesMode

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

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

你应该看看Terracotta参考Web应用程序 - Examinator。它具有你正在寻找的大多数组件 - 它具有用MySQL后端的Hibernate、JPA和Spring。

它已经预调至最多可以扩展到16个节点和20,000个并发用户。

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

谢谢您目前为止的回答。我们还没有完全达成目标,但是我们已经尝试了一些方法,现在事情更加清晰了。这是一个简短的更新:

看起来最具可行性的解决方案是 EJB。但是,这将需要对我们的代码进行一定的更改,因此我们不会立即完全实现该解决方案。我几乎感到惊讶,我们竟然没有找到一些 Spring 特性来帮助我们解决这个问题。

我们还尝试过JNDI路线,但最终需要为所有共享接口创建存根。考虑到所有内容都在同一台服务器上,这感觉非常麻烦。

昨天,我们在JMX方面有了一些小的突破。虽然JMX绝对不是为这种用途而设计的,但我们已经证明可以做到-并且没有代码更改和最少的XML(非常感谢Spring的MBeanExporter和MBeanProxyFactoryBean)。这种方法的主要缺点是性能和我们的域类必须通过JBoss服务器/ lib文件夹共享的事实。也就是说,我们必须从我们的WAR中删除一些依赖项并将它们移动到server / lib中,否则当业务层从我们自己的域模型返回对象时,我们会收到ClassCastException。我完全理解为什么会发生这种情况,但这并不是我们正在努力实现的理想状态。

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

Spring确实有一个集成点可能会引起你的兴趣:EJB 3注入拦截器。这使您能够从EJB中访问Spring beans。

我真的不确定你正在尝试解决什么问题;最终,每个 JVM 要么具有对象的重复实例,要么具有代表存在于另一个(逻辑)服务器上的对象的存根。

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

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

看一下JBossCache。它允许你轻松地在多个JVM实例(同一台机器或不同机器)之间共享/复制数据映射。它易于使用,并且具有许多线协议选项(TCP,UDP组播等)。





相关问题
热门标签