除了EAR和EJB之外,我从Java EE应用服务器上得到什么东西,我没有像Tomcat那样在servlet容器中获得?
我们使用Tomcat托pipe基于WAR的应用程序。 除了org.apache.catalina.authenticator.SingleSignOn,我们是符合servlet容器的J2EE应用程序。
我们被要求转向商业Java EE应用服务器。
- 改变的第一个缺点是我看到的是成本。 不pipe应用程序服务器的收费如何,Tomcat都是免费的。
- 其次是复杂性。 我们不使用EJB和EAR特性(当然不是,我们不能),也没有使用它们。
那么我没有看到什么好处呢?
有什么缺点,我没有提到?
提到的是…
- JTA – Java事务API – 我们通过数据库存储过程来控制事务。
- JPA – Java持久性API – 我们使用JDBC和再次存储的过程来坚持。
- JMS – Java消息服务 – 我们使用XML over HTTP进行消息传递。
这很好,请多多关照!
除非你想要EJB,否则你不需要一个完整的J2EE服务器(商业与否)。
您可以拥有绝大多数J2EEfunction(如JTA,JPA,JMS,JSF),而没有完整的堆栈J2EE服务器。 整个堆栈j2ee的唯一好处是容器将以你的名义声明性地pipe理所有这些。 随着EJB3的出现,如果你需要容器pipe理的服务,使用一个是件好事。
您也可以免费使用Glasfish,Geronimo或JBoss等完整的堆栈服务器。
例如,您也可以在Tomcat内部运行带有embedded式Glasfish的embedded式j2ee容器pipe理服务。
如果您想使用会话bean,消息bean,定时器bean,那么您可能需要一个EJB容器,即使是集群和故障转移。
我build议pipe理层根据function需要考虑升级。 这些EJB容器中的一些可能恰好使用embedded式Tomcat作为他们的networking服务器,
一些pipe理者只是喜欢付钱。 要求他们考虑一个城市住房捐赠或只是去东亚银行。
当我们的目标是Java EE 6将Apache Tomcatauthentication为Apache TomEE时 ,为了最终通过Java EE 6 TCK,我们需要填补一些空白。
不是一个完整的清单,但有些亮点即使是现有的答案也可能不明显。
没有TransactionManager
交易pipe理对于任何authentication的服务器都是必需的。 在任何Web组件(servlet,filter,listener,jsf managed bean)中,你都应该能够获得一个UserTransaction
像这样:
-
@Resource UserTransaction transaction;
您应该可以使用javax.transaction.UserTransaction
来创build事务。 您在该交易范围内所涉及的所有资源都应该注册在该交易中。 这包括但不限于以下目的:
-
javax.sql.DataSource
-
javax.persistence.EntityManager
-
javax.jms.ConnectionFactory
-
javax.jms.QueueConnectionFactory
-
javax.jms.TopicConnectionFactory
-
javax.ejb.TimerService
例如,如果在一个servlet中启动一个事务,那么:
- 更新数据库
- 将JMS消息发送到主题或队列
- 创build一个计时器稍后的工作
..然后其中一个失败,或者你只是select在UserTransaction
上调用rollback()
,那么所有这些东西都被撤消。
没有连接池
要清楚的是有两种连接池:
- 具有事务感知的连接池
- 非事务感知的连接池
Java EE规范并不严格要求连接池,但是如果您有连接池,则应该是事务处理,否则您将失去事务pipe理。
这意味着什么基本上是:
- 同一事务中的每个人都应该具有来自池的相同连接
- 无论是否有人调用
close()
或DataSource
上的其他方法,在事务完成(提交或回滚)之前,连接都不应返回到池中。
在Tomcat中用于连接池的通用库是commons-dbcp。 我们也想在TomEE中使用它,但是它不支持事务感知的连接池,所以我们实际上把这个function添加到了commons-dbcp(yay,Apache),并且在commons-dbc版本1.4中。
请注意,将commons-dbcp添加到Tomcat还不足以获得事务性连接池。 您仍然需要事务pipe理器,并且您仍然需要容器来通过Synchronization
对象来完成注册与TransactionManager
连接。
在Java EE 7中,有一些关于添加标准方式来encryption数据库密码的讨论,并将它们与应用程序一起打包在安全文件或外部存储中。 这将是Tomcat不支持的另一个function。
没有安全集成
WebServices安全性,JAX-RS SecurityContext,EJB安全性,JAASlogin和JAAC都是安全性概念,默认情况下,即使您单独添加像CXF,OpenEJB等库,也不会在Tomcat中“挂钩”。
这些API当然都假设在Java EE服务器中一起工作。 为了让所有这些合作并在Tomcat Realm
API上进行合作,我们不得不做了相当多的工作,以便人们可以使用所有现有的Tomcat Realm
实现来驱动他们的“Java EE”安全性。 这实际上仍然是Tomcat的安全性,它只是非常好的集成。
JPA集成
是的,您可以将JPA提供程序放到.war文件中,并在没有Tomcat帮助的情况下使用它。 用这种方法你不会得到:
-
@PersistenceUnit EntityManagerFactory
注入/查找 -
@PersistenceContext EntityManager
注入/查找 - 一个
EntityManager
连接到一个事务感知的连接池 - JTApipe理的
EntityManager
支持 - 扩展的持久化上下文
JTA-Managed EntityManager
基本上意味着同一个事务中的两个对象想要使用一个EntityManager
将看到相同的EntityManager
并且不需要显式传递EntityManager
。 所有这些“通过”都是由容器为你完成的。
这是如何实现的? 简单来说,你从容器中获得的EntityManager
是假的。 这是一个包装。 当你使用它的时候,它会在真正的EntityManager
的当前事务中查找,并将该调用委托给该EntityManager
。 这是神秘的EntityManager.getDelegate()
方法的原因,所以用户可以得到真正的 EntityManager,如果他们想要使用任何非标准的API。 这样做,当然要非常小心,永远不要保留对委托EntityManager
的引用,否则会产生严重的内存泄漏。 当事务完成时,委托EntityManager
通常会被刷新,closures,清理并丢弃。 如果你仍然坚持一个引用,你将阻止该EntityManager
垃圾回收以及可能的所有数据。
- 持有从容器中获得的
EntityManager
的引用总是安全的 - 持有对
EntityManager.getDelegate()
的引用并不安全 - 要非常小心地持有对通过
EntityManager
自己创build的EntityManager
的引用 – 您对其pipe理负全部责任。
CDI集成
我不想过分简化CDI,但是我觉得它有点太大了,许多人没有认真看待 – 这是在很多人的“某天”列表:)所以这里只是一些亮点我认为一个“networking人”会想知道。
你知道所有的投入,并让你在一个典型的Web应用程序做? 整天拉入和离开HttpSession
? 使用String
键和不断铸造你从HttpSession
获得的对象。 你可能会使用实用程序代码来为你做。
CDI也有这个实用程序代码,它被称为@SessionScoped
。 任何用@SessionScoped
注解的对象都可以在HttpSession
进行放置和跟踪。 您只需通过@Inject FooObject
请求将对象注入到您的Servlet中,CDI容器将以跟我描述EntitityManager
的事务跟踪相同的方式跟踪“真实”FooObject实例。 Abracadabra,现在你可以删除一堆代码:)
在HttpServletRequest
上执行任何getAttribute
和setAttribute
? 那么,你可以用同样的方式用@RequestScoped
删除它。
当然有@ApplicationScoped
来消除你可能在ServletContext
上做的getAttribute
和setAttribute
调用
为了让事情更酷,像这样跟踪的任何对象都可以实现一个@PostConstruct
,它在bean创build时被调用,当所有的“scope”完成时,会通知@PreDestroy
方法(会话结束,请求结束,该应用程序正在closures)。
CDI可以做更多的事情,但这足以让任何人想重新写一个旧的Web应用程序。
一些挑剔的东西
在Java EE 6中添加了一些没有添加的Tomcats控制台。 他们不需要大的解释,但却占了大部分的“填补空白”。
- 支持
@DataSourceDefinition
- 支持全局JNDI(
java:global
,java:app
,java:module
) - 枚举注入通过
@Resource MyEnum myEnum
和 - 类注入通过
@Resource Class myPluggableClass
和 - 支持
@Resource(lookup="foo")
小的一点,但它可以是非常有用的定义应用程序中的DataSource
以便携的方式,共享JNDI条目之间的Web应用程序,并拥有简单的权力说:“看这个东西,并注入”
结论
如上所述,不是一个完整的列表。 没有提到EJB,JMS,JAX-RS,JAX-WS,JSF,Bean Validation等有用的东西。 但是当人们谈论Tomcat是什么和不知道的时候,至less有一些事情会被忽视。
另请注意,您可能认为“Java EE”可能与实际定义不符。 使用Web Profile,Java EE已经萎缩了。 这是故意要解决的“Java EE太重,我不需要所有”。
如果您将EJB从Webconfiguration文件中截取出来,请执行以下操作:
- Java Servlets
- Java ServerPages(JSP)
- Java ServerFaces(JSF)
- Java事务API(JTA)
- Java持久性API(JPA)
- Java上下文和dependency injection(CDI)
- Beanvalidation
这是一个非常有用的堆栈。
如果您被要求转移到商业J2EE服务器,原因可能与J2EE堆栈无关,但是与非技术性的考虑。
技术支持是一个你没有用Tomcat获得的商业化J2EE产品所获得的东西。
这可能不是您的考虑因素,具体取决于您的Web应用程序应该满足的服务级别。 在尝试找出Tomcat的问题时,你的应用程序是否可以closures,或者这会成为一个主要问题?
有一些免费的J2EE服务器,例如JBoss和Glassfish,成本不一定是一个负面影响。
您的问题假设(J2EE = Servlet + EJB + EAR),因此,如果您不使用EJB或EAR,那么使用任何比Servlet容器更多的东西是没有意义的。 事实根本就不是这样,J2EE包含了更多的东西。 例子包括:
- JTA – Java事务API
- JPA – Java持久性API
- JMS – Java消息传递规范
- JSF – 用于从组件构build用户界面的技术
欢呼声,唐纳
实际上,有大量的包和库可用,几乎没有一个EJB容器提供了无法添加到现代servlet容器(ala Tomcat)的东西。 所以,如果你想要任何这些function,你可以让他们“点菜”,这样说成本就是把这个function集成到你的应用程序的过程。
如果你现在没有“遗漏”任何这些function,那么从实际的angular度来看,你可能不需要它们。
所有人都说,现代的EJB容器真的很好,并且预先集成了所有这些服务,使得它们在你想要的时候更容易使用。 有时使用附近的function就足以让人们在应用程序中探索它的潜力,而不像看到function的整合过程成为应用的障碍。
由于免费的EJB容器的质量,很难想象如何购买一个可用的,特别是考虑到你现在没有真正的需求。
不过,我真的鼓励你真正得到一个,并玩弄它并探索平台。 Glassfish很容易入门,而且非常好,应该很容易地把你的WAR(或者做很小的调整)。
通常在运行Tomcat和EJB容器之间,问题是为什么不使用一个? 专门为Glassfish而言,我发现它比Tomcat更易于使用,它的主要区别在于,它可以比Tomcat具有适度更大的内存占用(特别是对于小型应用程序),但在大型应用程序中,您甚至不会注意到。 对我来说,记忆力不是什么大不了的,对于其他人来说,这可能是一个问题。
它为我提供了所有这些不错function的单一来源,而无需抓取第三方选项的networking。