春季MVC与JBoss与雄猫 - 优势/实践

好。这又是一个行业实践的问题。

  • Tomcat = Web Container
  • JBoss,WebLogic等=其中有Web容器的应用程序服务器(对于JBoss,其分叉的Tomcat)

Spring不需要像JBoss这样的Appplication Server。如果我们使用JMS等企业服务,我们可以使用RabbitMQ,ApacheMQ等独立系统。

  1. 问题是,为什么人们仍然使用JBoss和其他应用程序服务来纯粹基于弹簧的应用程序?
  2. 通过使用应用程序服务器,Spring可以利用哪些优势?喜欢对象池?应用程序服务器提供哪些特定优势?它们是如何配置的?
  3. 如果不是为了弹簧,那么应用程序服务器还用于Spring/Hibernate等堆栈的其他目的吗?(使用案例)

答案 1

实际上,我会说监听 JMS 可能是使用应用程序服务器的最佳理由。独立的消息代理不能解决此问题,因为您仍然需要一个侦听消息的组件。最好的方法是使用MDB。从理论上讲,你可以使用Spring MessageListenerContainer。然而,这有几个缺点,比如JMS只支持阻塞读取,因此Spring需要启动它自己的线程,这是完全不支持的(即使在Tomcat中),并且可以破坏事务,安全性,命名(JNDI)和类加载(反过来可以破坏远程处理)。JCA 资源适配器可以自由地做任何它想做的事情,包括通过 WorkManager 启动线程。除了 JMS(或其他目标)之外,可能还使用了一个数据库,此时您需要 XA 事务和 JTA,换句话说,就是应用程序服务器。是的,您可以将其修补到 servlet 容器中,但是此时它与应用程序服务器无法区分。

恕我直言,反对应用程序服务器的最大原因是,在规范发布后需要数年时间(反过来也需要数年时间),直到severs实现该规范并解决最严重的错误。直到现在,在EE 7即将发布之前,我们才有EE 6服务器开始出现,这些服务器并没有完全充满错误。这变得滑稽到一些供应商不再修复其EE 6系列中的错误,因为他们已经忙于即将推出的EE 7系列。

编辑

最后一段的长篇解释:

Java EE在很多地方都依赖于所谓的上下文信息。未作为参数从服务器/容器显式传递到应用程序但隐式“在那里”的信息。例如,用于安全检查的当前用户。当前事务或连接。用于查找类以延迟加载代码或反序列化对象的当前应用程序。或者用于执行 JNDI 查找的当前组件(servlet、EJB 等)。所有这些信息都在服务器/容器在调用组件(servlet、EJB 等)之前设置的线程局部变量中。如果您创建自己的线程,那么服务器/容器就不知道它们,并且依赖于此信息的所有功能都不再起作用。您可以通过在您生成的线程中不使用任何这些功能来逃脱这一点。

一些链接

http://www.oracle.com/technetwork/java/restrictions-142267.html#threads http://www.ibm.com/developerworks/websphere/techjournal/0609_alcott/0609_alcott.html#spring-4

如果我们检查 Servlet 3.0 规范,我们会发现:

2.3.3.3 异步处理

Java Enterprise Edition 功能,如第 15-174 页上的第 15.2.2 节 “Web 应用程序环境”和第 15.3.1 节 “在 EJBTM 调用中传播安全身份”(第 15-176 页)等功能,仅对执行初始请求的线程或通过 AsyncContext.dispatch 方法将请求分派到容器时可用。Java Enterprise Edition 功能可能可用于通过 AsyncContext.start(Runnable) 方法直接在响应对象上运行的其他线程。

这是关于异步处理的,但相同的限制也适用于自定义线程。

public void start(Runnable r) - 此方法使容器调度一个线程(可能来自托管线程池)来运行指定的 Runnable。容器可以将适当的上下文信息传播到 Runnable。

同样,异步处理但相同的限制也适用于自定义线程。

15.2.2 Web 应用程序环境

这种类型的 servlet 容器在开发人员创建的线程上执行时应支持此行为,但当前不需要这样做。此规范的下一个版本将添加此类要求。请开发人员注意,不建议将此功能用于应用程序创建的线程,因为它是不可移植的。

不可移植意味着它可以在一台服务器中,但不能在另一台服务器中。

当您希望在MDB之外使用JMS接收消息时,您可以使用以下四种方法:javax.jms.MessageConsumer

  • #receiveNoWait()你可以在容器线程中做到这一点,它不会阻塞,但就像偷看一样。如果没有消息存在,则只返回 。这不太适合收听消息。null
  • #receive(long)你可以在容器线程中做到这一点,它确实会阻塞。您通常不会不想在容器线程中执行阻塞等待。同样不是很好适合听消息。
  • #receive(),这可能会无限期地阻塞。同样不是很好适合听消息。
  • #setMessageListener()这是你想要的,当消息到达时,你会得到一个回调。但是,除非库可以挂接到应用程序服务器,否则这不会是容器线程。与应用程序服务器的挂钩只能通过 JCA 连接到资源适配器。

所以,是的,它可能有效,但它不能保证,有很多东西可能会坏掉。


答案 2

你是对的,你并不需要一个真正的应用程序服务器(实现所有的Java EE规范)来使用Spring。人们不使用像JBoss这样的真正的Java EE应用程序的最大原因是,在冷启动时,#$@#%的速度很慢,这使得开发变得很痛苦(热部署仍然不能很好地工作)。

你可以看到有两个阵营:

  • Java EE
  • 弹簧框架。

其中一个阵营相信规范/委员会过程,另一个阵营相信仁慈的独裁者/有机OSS过程。两者都有“议程”的人。

你可能不会得到一个非常好的公正的答案,因为这两个阵营很像Emacs vs VIM战争

回答您的问题与弹簧偏差

  1. 因为它从理论上讲会购买您较少的供应商锁定(尽管我发现情况恰恰相反)。
  2. Spring最大的优势是AspectJ AOP。到目前为止。
  3. 我想看到菲利普的答案了。

(咆哮的开始)

由于@PhilippeMarschall为Java EE辩护,我会说我已经完成了Tomcat + RabbitMQ + Spring路线,并且运行良好。如果你想要正确的JTA + JMS,@PhilippeMarschall讨论是有效的,但是使用Sprig AMQP进行适当的设置以及像Postgresql这样的良好事务数据库,这不是一个问题。此外,他对消息队列事务未绑定/同步到平台事务的看法是不正确的,因为Spring支持这一点(恕我直言,@Transactional AOP更优雅)。此外,AMQP也明显优于JMS。

(咆哮结束)


推荐