【问题标题】:Java EE vs StandaloneJava EE 与独立
【发布时间】:2012-11-15 07:26:51
【问题描述】:

我正在开展一个项目,我们需要构建多个连接到一个数据库的“独立”模块。这些模块主要是后台业务流程,所以前端不多。除了一个显示数据并允许基本 CRUD 功能的 Web 模块。为此,我们计划使用以下技术:

  • JPA2(使用 hibernate-jpa 实现)
  • CDI(使用 spring 实现)
  • JSF2 + primefaces(用于我们的网络模块)

最初的计划是为每个模块创建一个 jar 文件(使用 main 方法)并通过服务包装器将其安装为(Windows)服务。对于我们的 Web 模块,我们将使用 Glassfish 或 JBoss 来运行它。然而,最近我们想到了 Java EE。我们可以在 Glassfish 或 JBoss 等 Java EE 容器中运行我们的所有模块,而不仅仅是我们的 Web 模块。关于我们使用 Java EE 的案例的一些问题:

  1. 我们还能/应该将 CDI 与 spring 一起使用吗?还是我们应该切换到 EJB3?
  2. 当我们在容器而不是独立模块中使用 JPA 时,它会产生什么后果?有什么区别吗?
  3. 由于我们的大多数模块都与 Web 无关,在 Java EE 容器中运行它们是否仍然有意义?

【问题讨论】:

    标签: spring hibernate jakarta-ee jpa cdi


    【解决方案1】:

    其他人已经指出了一些优点,因此如果您将后台进程部署到与您的 Web 应用程序相同的 jvm 中,这里有一些缺点。

    • 启动和停止运行 Web 模块的服务器意味着您启动和停止后台进程,这对您来说可能是也可能不是问题。
    • 如果后台进程消耗大量内存或 cpu,那么您将与所有三个应用程序共享堆,这可能会影响您的 Web 应用程序,或者如果 Web 应用程序消耗大量资源,则可能会影响后台进程。
    • 可能需要以可通过 Internet 访问的方式部署 Web 应用程序,但后台进程可能很乐意在没有任何网络访问权限的情况下运行。那么,如果不需要,为什么要将后台进程公开给互联网。
    • 当您升级应用程序服务器、框架或配置时,这意味着要测试三件事,如果后台进程自行运行,您可以在 Web 应用程序的单独发布周期中升级它们。
    • 在容器外开发和测试代码更简单。在容器内运行后台进程意味着后台进程的开发环境更加复杂,您必须等待服务器启动,您的启动取决于容器中的资源,然后您必须模拟表单单元测试......等等。

    JPA 在容器内部和外部是相同的。唯一的区别是您如何获得 EntityManager,这可以使用 Spring 配置为在容器内外都相同。 CDI 应该可以在容器外运行。

    主要区别在于您如何使用数据库进行事务处理,例如使用 Spring 事务与 ejb 事务。

    更新: 要从评论中回答您的问题:在 JPA 中,EntityManager 不是线程安全的,因此在 Java EE 服务器中,每个线程的每个持久性单元将有一个实体管理器。实体管理器的创建和关闭由应用服务器为您管理。每个实体管理器中都有一个缓存。可以配置跨越多个实体管理器的二级缓存。在容器外运行时,您必须自己管理 JPA 实体管理器的数量,这将取决于您的后台进程中的线程数和您想要拥有的事务边界。如果您查看一本名为“Pro JPA2”的书,其中有一节讨论了在容器内部或外部运行的细节。

    在我的应用程序中,我没有后台进程,但是每个需要实体管理器的类只需使用@PersistenceContext EntityManager em; 将其注入,spring 会负责使其在容器内外都能正常工作。 Spring 3.1 有一个称为配置文件的特性,它使得在容器外部运行相同的代码而不改变一行代码变得微不足道。我不是 CDI 用户,所以我不知道 CDI 是否具有与 spring 3.1 配置文件功能等效的功能。

    【讨论】:

    • 感谢您也向我展示了缺点!关于实体管理器,对于 JEE,我们不是只有 1 个实例,而不是独立的,每个 JVM(/模块)我们将有 1 个实例?这会对休眠缓存有影响吗?
    • 以防万一有人认真对待这一点,请注意,如果您仅使用两个不同的容器,一个用于批处理,一个用于 Web,几乎所有缺点都会消失。事实上,每件事都使用一个容器。拥有 CDI、JPA 的统一标准容器的优点是巨大的。至于开发生产力,eclipse 也可以提供与 java ee 容器类似的周转。唯一需要的修改是关闭批处理容器的 http 侦听器。对 spring 或任何非标准的东西说不——java ee 7 已经获得批准,你会得到一大堆好东西。
    • @RobeEleckers 另外一个容器本质上是一个 jvm,所以如果你只是关闭网络监听器,你正在运行一个批处理 java 进程。
    【解决方案2】:

    如果所有模块(批处理 + 实时)都与一个产品相关,那么将它们捆绑在一起是一种好方法。所以这是我的建议

    1. 将所有模块捆绑到一个耳朵中。
    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?
    • 您还没有真正解释为什么“只要您没有看到任何性能问题,将单个产品的批处理和实时方面捆绑在一起是有意义的”,即有什么好处与在应用服务器中运行它而不是独立运行它的额外复杂程度相关。
    • @foampile 相关模块通常依赖于同一组核心模块。因此,将它们捆绑在一起是有意义的。我不确定在应用服务器中运行的复杂性是什么? MDB 用于异步处理,它们在 appserver 的上下文中运行。
    • @foampile 是的 CDI 可以在独立应用程序中使用。查看 Weld 的文档了解如何操作。
    • 确实如此,但是,我发现在努力实现 SOA 和基于组件的模型方面更有优势,可以在不同的平台上使用,而不是紧密耦合看似可分离的模块。只是我的 0.02 美元。我认为你的立场确实有道理,但是它可能会阻碍模块的分离
    【解决方案3】:

    出于常见原因,例如

    ,在应用程序服务器而不是独立的 java 程序中运行是有意义的

    1) 您可以将 CDI 与 spring 一起使用,因为 EJB3 也基于类似的概念。 2) 就 JPA 而言,没有区别,只是如果您以后需要向应用程序添加更多容量,可以通过添加更多运行相同应用程序的机器来添加负载 - 但是,请注意,这是一个非微不足道的工作量,因此取决于业务需求来做出选择 3) 应用服务器胜过独立应用程序,因为其内置的安全性、可靠性、管理和可扩展性优于独立的 Java 应用程序。

    【讨论】:

      猜你喜欢
      • 2015-05-27
      • 1970-01-01
      • 2016-07-22
      • 1970-01-01
      • 1970-01-01
      • 2011-12-25
      • 1970-01-01
      • 2015-09-01
      • 1970-01-01
      相关资源
      最近更新 更多