Java EE与独立应用程序

8
我正在处理一个项目,需要构建多个“独立”的模块连接到一个数据库。这些模块主要是后台业务流程,没有太多的前端。除了一个网络模块展示数据和允许基本CRUD功能。对于此,我们计划使用以下技术:
  • JPA2(使用hibernate-jpa实现)
  • CDI(使用spring实现)
  • JSF2 + primefaces(用于我们的Web模块)
最初的计划是每个模块创建一个带有主方法的jar文件,并通过服务包装器将其安装为(Windows)服务。对于我们的Web模块,我们将使用Glassfish或JBoss来运行它。然而,最近Java EE浮现在我们的脑海中。我们可以在Java EE容器(如Glassfish或JBoss)中运行所有模块,而不仅仅是我们的Web模块。如果我们选择Java EE,以下是一些问题:
  1. 我们是否仍然可以使用spring的CDI?还是应该转换为EJB3?
  2. 当我们从容器中使用JPA而不是独立模块时,对于JPA会产生什么影响?有区别吗?
  3. 由于我们的大多数模块与Web无关,因此在Java EE容器中运行它们仍然有意义吗?
3个回答

3
如果所有模块(批处理+实时)都与一个产品相关,则将它们捆绑在一起是一个好的方法。因此,这是我的建议:
1. 将所有模块捆绑到单个 ear 中。 2. 使用 Java EE 6 并且摆脱 spring。CDI 旨在用于 Java EE 中。对于批处理操作,尝试利用 Asynchronous EJBs 或 MDB。
针对您的具体问题的答案:
- 我们仍然可以/应该使用 CDI 和 Spring 吗?还是应该切换到 EJB3? CDI 也可以不使用 EJB。无论如何,摆脱 Spring,因为我认为它对您的简单项目没有增加价值。
- 当我们从容器中而不是独立模块中使用 JPA 时,会有什么后果?有什么区别吗? 除了您可以从 JNDI 获取 DataSource 外,没有区别。
- 由于我们的大多数模块与 Web 无关,是否仍然有意义在 Java EE 容器中运行它们?

只要没有性能问题,将批处理和实时方面捆绑在一个产品中确实是有意义的。


能否在独立的Java应用程序中使用CDI? - amphibient
你并没有真正解释为什么“只要您没有看到任何性能问题,捆绑批处理和实时方面到单个产品中确实是有意义的”,也就是说,与独立运行相比,在应用程序服务器内运行它所涉及的额外复杂性的好处是什么。 - amphibient
@foampile 相关模块通常依赖于相同的核心模块。因此将它们捆绑在一起是有意义的。我不确定在应用服务器中运行的复杂性在哪里?MDB 用于异步处理,并在应用服务器的上下文中运行。 - Aravind Yarram
这是事实,然而,我认为更有价值的是努力朝着面向服务的架构和基于组件的模型的方向发展,这些可以在不同的平台上使用,而不是紧密耦合看似可以分离的模块。这只是我的个人观点。我认为你的立场很有道理,但它可能会阻碍模块之间的分离。 - amphibient
@foampile SOA中的服务应该是粗粒度的,即在业务功能级别上。此外,只有当客户端需要服务时,SOA才适用。在这种情况下,它是一个自包含的应用程序。没有业务驱动因素的情况下应用原则实际上是不必要的。 - Aravind Yarram
显示剩余3条评论

3
其他人已经指出了一些优点,那么如果您将后台进程部署到与您的Web应用程序相同的JVM中,这里有一些缺点。
- 启动和停止运行Web模块的服务器意味着您启动和停止后台进程,这可能对您来说是一个问题或不是问题。 - 如果后台进程消耗大量内存或CPU,则与所有三个应用程序共享堆可能会影响您的Web应用程序,或者如果Web应用程序消耗大量资源,则可能会影响后台进程。 - Web应用程序可能需要以可通过Internet访问的方式部署,但是如果后台进程没有必要,则可能愉快地运行而无需任何对网络的访问。因此,为什么要将后台进程暴露在Internet上。 - 当您升级应用程序服务器、框架或配置时,它意味着需要测试三件事情,如果后台进程正在运行,则可以将它们与Web应用程序分开进行升级。 - 在容器外部开发和测试代码更简单。在容器中运行您的后台进程意味着后台进程具有更复杂的开发环境,您必须等待服务器启动,开始依赖于容器资源,然后必须从单元测试中进行模拟...等等。
JPA在容器内外都是相同的。唯一的区别是如何获取EntityManager,这可以使用Spring进行配置,使其在容器内外都相同。CDI应该可以在容器外运行。
主要区别将是如何使用数据库事务,例如使用Spring事务与ejb事务。
更新:回答您在评论中的问题:在JPA中,EntityManager不是线程安全的,因此在Java EE服务器中,每个线程每个持久性单元将有一个实体管理器。 EntityManager的创建和关闭由应用程序服务器为您管理。每个实体管理器都有一个缓存。可以配置跨多个实体管理器的二级缓存。 在容器外运行时,您将不得不自己管理JPA实体管理器的数量,这将取决于后台进程中的线程数量和您想要拥有的事务边界数。如果您查看名为“Pro JPA2”的书籍,则有一部分讨论了在容器内或外运行的详细信息。
在我的应用程序中,我没有后台进程,但是每个需要实体管理器的类都使用@PersistenceContext EntityManager em进行注入,并且Spring会负责使其在容器内外都正常工作。 Spring 3.1具有名为“profiles”的功能,可以轻松地使相同的代码在容器内外运行,而无需更改任何代码行。 我不是CDI用户,所以我不知道CDI是否具有与Spring 3.1 profiles功能等效的功能。

谢谢你也向我展示了缺点!关于entitymanager,使用JEE,我们只有1个实例,而不是独立应用中每个JVM(/模块)都有1个实例?这会影响hibernate的缓存吗? - Robe Elckers
请注意,如果您只是使用两个不同的容器,一个用于批处理,一个用于Web,则几乎所有的缺点都会消失。实际上,对于每个事物使用一个容器。具有CDI、JPA等统一标准容器的优点是巨大的。至于开发生产力,Eclipse也可以提供与Java EE容器类似的周转时间。唯一需要修改的是关闭批处理容器的HTTP监听器。拒绝Spring或任何非标准的东西--Java EE 7已经获得批准,并且您将获得一堆好处。 - necromancer
另外,容器本质上是一个JVM,因此,如果您只是关闭网络侦听器,那么您正在运行批处理Java进程。 - necromancer

1

在常见的情况下,与独立的Java程序相比,运行在应用服务器中是有意义的,原因如下:

1)您可以使用CDI和Spring,因为EJB3也基于类似的概念。 2)就JPA而言,没有任何区别,只是如果您需要在以后向应用程序添加更多负载,则可以通过添加运行相同应用程序的更多机器来增加负载-但请注意,这是一项非常重要的工作,因此它取决于业务需求来做出选择。 3)与独立的Java应用程序相比,应用服务器具有内置的安全性、可靠性、管理性和可扩展性等优势。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接