除了 EAR 和 EJB 之外,我从 Java EE 应用服务器中得到了什么,而这些服务器是我没有在像 Tomcat 这样的 servlet 容器中得到的?

我们使用Tomcat来托管我们基于WAR的应用程序。我们是符合servlet容器的J2EE应用程序,除了org.apache.catalina.authenticator.SingleSignOn。

我们被要求迁移到商用 Java EE 应用程序服务器。

  1. 我看到的改变的第一个缺点是成本。无论应用服务器收取多少费用,Tomcat 都是免费的。
  2. 其次是复杂性。我们既不使用 EJB 也不使用 EAR 功能(当然不是,我们不能),也没有错过它们。

那么我没有看到的好处是什么呢?

我没有提到的缺点是什么?


提到的是...

  1. JTA - Java Transaction API - 我们通过数据库存储过程控制事务。
  2. JPA - Java Persistence API - 我们使用JDBC和存储过程来持久化。
  3. JMS - Java Message Service - 我们使用 XML over HTTP 进行消息传递。

这很好,请更多!


答案 1

当我们着手将Java EE 6认证Apache Tomcat为Apache TomEE时,以下是为了最终通过Java EE 6 TCK而必须填补的一些空白。

不是一个完整的列表,而是一些亮点,即使有现有的答案也可能不明显。

无事务管理器

任何经过认证的服务器都绝对需要事务管理。在任何Web组件(servlet,filter,listener,jsf托管bean)中,你应该能够像这样注入:UserTransaction

  • @Resource UserTransaction transaction;

您应该能够使用 来创建交易记录。您在该事务范围内涉及的所有资源都应在该事务中注册。这包括但不限于以下对象:javax.transaction.UserTransaction

  • javax.sql.DataSource
  • javax.persistence.EntityManager
  • javax.jms.ConnectionFactory
  • javax.jms.QueueConnectionFactory
  • javax.jms.TopicConnectionFactory
  • javax.ejb.TimerService

例如,如果在 servlet 中启动事务,则:

  • 更新数据库
  • 向主题或队列触发 JMS 消息
  • 创建计时器以在以后的某个时间点执行工作

..然后其中一件事情失败了,或者你只是选择调用,那么所有这些事情都被撤消了。rollback()UserTransaction

无连接池

需要明确说明的是,有两种类型的连接池:

  • 事务感知连接池
  • 非事务感知连接池

Java EE 规范并不严格要求连接池,但是如果您有连接池,它应该是事务感知的,否则您将失去事务管理。

这基本上意味着:

  • 同一事务中的每个人都应具有来自池的相同连接
  • 在事务完成(提交或回滚)之前,不应将连接返回到池中,无论是否调用了 某人或 上的任何其他方法。close()DataSource

Tomcat 中用于连接池的一个常见库是 commons-dbcp。我们也想在TomEE中使用它,但是它不支持事务感知连接池,所以我们实际上将该功能添加到commons-dbcp(yay,Apache)中,并且它从commons-dbc版本1.4开始就存在。

请注意,将 commons-dbcp 添加到 Tomcat 仍然不足以获得事务性连接池。您仍然需要事务管理器,并且仍然需要容器来执行与 via 对象注册连接的管道。TransactionManagerSynchronization

在 Java EE 7 中,有关于添加一种标准方法来加密数据库密码,并将它们与应用程序一起打包在安全文件或外部存储器中。这将是Tomcat不支持的另一个功能。

无安全集成

WebServices Security、JAX-RS SecurityContext、EJB Security、JAAS login 和 JAAC 都是在 Tomcat 中默认不“挂接”的安全概念,即使您单独添加 CXF、OpenEJB 等库也是如此。

当然,这些 API 都假定在 Java EE 服务器中协同工作。我们必须做很多工作才能让所有这些合作,并在Tomcat API之上做到这一点,以便人们可以使用所有现有的Tomcat实现来驱动他们的“Java EE”安全性。它实际上仍然是Tomcat的安全性,它只是很好地集成在一起。RealmRealm

联合保护区集成

是的,您可以将 JPA 提供程序拖放到 .war 文件中,并在没有 Tomcat 帮助的情况下使用它。使用这种方法,您将无法获得:

  • @PersistenceUnit EntityManagerFactory注入/查找
  • @PersistenceContext EntityManager注入/查找
  • 连接到事务感知连接池的EntityManager
  • JTA 托管支持EntityManager
  • 扩展的持久性上下文

JTA-Managed基本上意味着同一事务中希望使用一个的两个对象都将看到相同的内容,并且不需要显式传递。所有这些“传递”都是由容器为您完成的。EntityManagerEntityManagerEntityManagerEntityManager

这是如何实现的?很简单,你从容器中得到的是假的。它是一个包装器。使用它时,它会在当前事务中查找 real,并将调用委托给该 。这就是神秘方法的原因,因此用户可以根据需要获得真正的EntityManager,并使用任何非标准API。当然,这样做要非常小心,永远不要保留对委托的引用,否则您将遇到严重的内存泄漏。事务完成时,委托通常将被刷新、关闭、清理和丢弃。如果您仍然保留引用,则可以防止对该引用进行垃圾回收,并可能阻止对它所包含的所有数据进行垃圾回收。EntityManagerEntityManagerEntityManagerEntityManager.getDelegate()EntityManagerEntityManagerEntityManager

  • 始终可以安全地保存对从容器中获取的引用EntityManager
  • 它不安全地持有引用EntityManager.getDelegate()
  • 要非常小心地持有你自己通过一个 - 你100%负责它的管理。EntityManagerEntityManagerFactory

CDI 集成

我不想过度简化CDI,但我发现它有点太大了,很多人都没有认真看过 - 它在“有一天”的名单上,很多人:)所以这里只是一些亮点,我认为一个“网络人”会想知道。

您知道在典型的Web应用程序中进行的所有放置和操作吗?整天把东西拉进拉出?用于从 中获得的关键和连续转换对象。您可能已经使用实用程序代码来为您执行此操作。HttpSessionStringHttpSession

CDI也有这个实用程序代码,它被称为。任何带有注释的对象都会被放入并跟踪到 中。您只需请求通过将对象注入到您的 Servlet 中,CDI 容器将以与我描述的 事务跟踪相同的方式跟踪 “真正的”FooObject 实例。Abracadabra,现在你可以删除一堆代码:)@SessionScoped@SessionScopedHttpSession@Inject FooObjectEntitityManager

做任何和上 ?好吧,您也可以以相同的方式删除它。getAttributesetAttributeHttpServletRequest@RequestScoped

当然,还有消除您可能正在做的和电话@ApplicationScopedgetAttributesetAttributeServletContext

为了使事情变得更酷,任何像这样跟踪的对象都可以实现一个在创建bean时调用的,并在所述“scope”完成时通知一个方法(会话已完成,请求结束,应用程序关闭)。@PostConstruct@PreDestroy

CDI可以做得更多,但这足以让任何人都想重写一个旧的Web应用程序。

一些挑剔的事情

Java EE 6 中添加了一些在 Tomcats 驾驶室中没有添加的内容。它们不需要大的解释,但确实占了“填补空白”的很大一部分。

  • 支持@DataSourceDefinition
  • 支持全局 JNDI (, 、java:globaljava:appjava:module)
  • 通过和@Resource MyEnum myEnum
  • 通过 和 进行类注入@Resource Class myPluggableClass
  • 支持@Resource(lookup="foo")

次要的一点,但是在应用程序中以可移植的方式进行定义,在Web应用程序之间共享JNDI条目,并具有简单的功能来表示“查找此内容并注入它”,这可能非常有用。DataSource

结论

如前所述,不是一个完整的列表。没有提到EJB,JMS,JAX-RS,JAX-WS,JSF,Bean Validation和其他有用的东西。但至少对人们谈论雄猫是什么和不是什么时经常被忽视的事情有一些想法。

另请注意,您可能认为的“Java EE”可能与实际定义不符。随着Web Profile的出现,Java EE已经萎缩。这是故意解决“Java EE太重了,我不需要所有这些”。

如果您从 Web 配置文件中删除 EJB,那么您将留下以下内容:

  • Java Servlets
  • Java ServerPages (JSP)
  • Java ServerFaces (JSF)
  • Java Transaction API (JTA)
  • Java Persistence API (JPA)
  • Java Contexts and Dependency Injection (CDI)
  • 豆类验证

这是一个非常有用的堆栈。


答案 2

除非您想要 EJB 正确,否则您不需要全栈 J2EE 服务器(商业或非商用)。

您可以拥有大多数 J2EE 功能部件(如 JTA、JPA、JMS、JSF),而无需全栈 J2EE 服务器。全栈 j2ee 的唯一好处是容器将以声明方式代表您管理所有这些内容。随着 EJB3 的出现,如果您需要容器托管服务,使用一个容器托管服务是一件好事。

您还可以免费拥有全栈服务器,如Glasfish,Geronimo或JBoss。

例如,您还可以在Tomcat内部运行嵌入式glasfish的嵌入式j2ee容器托管服务。

如果要使用会话 Bean、消息 Bean、定时器 Bean,即使您具有集群和故障转移功能,也可能需要一个 EJB 容器。

我建议管理层根据功能需求考虑升级。其中一些EJB容器可能只是使用嵌入式Tomcat作为他们的Web服务器,所以什么给!

有些经理只是喜欢为事情付钱。要求他们考虑捐赠城市避难所,或者只是去BEA。


推荐