什么时候使用Spring或者EJB3或者全部使用它们是必要的还是方便的?
JSF2 + Spring + EJB3的混合使用或者这些的任意组合,我有点困惑。 我知道Spring的一个主要特性是dependency injection,但是使用JSF托pipe的bean,我可以使用@ManagedBean
和@ManagedProperty
并获得dependency injectionfunction。 有了EJB3,我更加困惑的是什么时候将它与JSF一起使用,或者甚至有什么理由使用它。
那么,在什么样的情况下使用Spring + JSF2或者EJB3 + JSF2会是一个好主意呢?
到目前为止,我只使用JSF2创build了一些小型的Web应用程序,而不需要使用Spring或EJB3。 不过,我在很多地方都看到人们在一起工作。
首先,Spring和EJB(+ JTA)是相互竞争的技术,通常不能在同一个应用程序中一起使用。 select一个或另一个。 Spring 或 EJB(+ JTA)。 我不会告诉你select哪一个,我只会告诉你一些历史和事实,以便你更容易作出决定。
他们试图解决的主要问题是提供具有自动事务pipe理的业务服务层API。 想象一下,你需要触发多个SQL查询来执行一个单一的业务任务(例如下订单),其中一个失败了,那么你当然会喜欢所有的事情都回滚,所以DB保持在同一个状态就像以前一样,好像完全没有任何事情发生。 如果您没有使用事务,则数据库将处于无效状态,因为第一批查询实际上已成功。
如果您熟悉基本的JDBC,那么您应该知道这可以通过closures连接上的自动提交,然后依次触发这些查询,然后在其中执行catch (SQLException)
a执行rollback()
。 然而,每次实施都是非常繁琐的 。
使用Spring和EJB(+ JTA),单一(无状态)业务服务方法调用在默认情况下作为单个完整事务进行透明计数。 这样你根本不用担心事务pipe理。 您不需要手动创buildEntityManagerFactory
,也不需要显式调用em.getTransaction().begin()
,而且您可以在将业务服务逻辑紧密耦合到JSF辅助bean类中和/或使用RESOURCE_LOCAL
JPA中的JTA
。 例如,您可以使用以下的EJB类来利用JPA:
@Stateless public class OrderService { @PersistenceContext private EntityManager em; @EJB private ProductService productService; public void placeOrder(Order newOrder) { for (Product orderedproduct : newOrder.getProducts()) { productService.updateQuantity(orderedproduct); } em.persist(newOrder); } }
如果你有一个@EJB private OrderService orderService;
在你的JSF支持bean中调用orderService.placeOrder(newOrder);
在操作方法中,将执行单个完整事务。 如果例如其中一个updateQuantity()
调用或persist()
调用失败并出现exception,那么它将回滚到目前为止执行的任何updateQuantity()
调用,并使数据库保持干净清爽的状态。 当然,你可以在你的JSF支持bean中捕获这个exception,并显示一个faces消息。
值得注意的是,“Spring”是一个相当大的框架,它不仅与EJB竞争,还与CDI和JPA竞争。 以前,在黑暗的J2EE时代,EJB 2.x的实现是非常糟糕的(上面的EJB 3.x OrderService
例子在EJB 2.x中需要至less5倍多的代码和一些XML代码)。 Spring提供了一个更好的select,它需要更less的Java代码(但仍然是许多XML代码)。 J2EE / EJB2从Spring学到了教训,并提供了Java EE 5,它提供了比Spring更光滑的新EJB3 API,并且完全不需要XML。
Spring还提供IoC / DI(控制反转;dependency injection)。 这是在由XMLconfiguration的J2EE时代期间,这可能会相当困难。 如今spring也使用注释,但仍然需要一些XML。 由于Java EE 6在学习了Spring的教训之后,提供了CDI提供相同的DIfunction,但是不需要任何XML。 使用Spring DI @Component
/ @Autowired
和CDI @Named
/ @Inject
您可以实现JSF用@ManagedBean
/ @ManagedProperty
所做的一样,但是Spring DI和CDI提供了更多的优点:例如,您可以编写拦截器进程或后处理托pipebean创build/销毁或托pipebean方法调用,您可以创build自定义作用域,生产者和使用者,可以在范围较宽的实例中注入一个较窄范围的实例。
Spring还提供了基本上与JSF竞争的MVC。 把JSF和Spring MVC混合起来是没有意义的。 进一步的Spring也提供了基本上比JPA更多的抽象层的数据,进一步最小化DAO样板(但实质上并不代表整个业务服务层)。
也可以看看:
- Java EE究竟是什么?
- JSF控制器,服务和DAO
- @无状态豆与@状态豆
这里没有真正简单的答案,因为Spring很多东西。
在一个非常高的层次上,Spring与Java EE竞争,这意味着您可以将其中任何一个用作完整的堆栈框架。
在更精细的层面上,Spring IoC容器和Spring Bean与Java EE中的CDI和EJB相结合。
至于web层,Spring MVC与JSF竞争。 一些Spring xyzTemplate与JPA接口竞争(都可以使用Hibernate作为这些实现的实现)。
这是可能的混合和匹配; 例如,在Spring MVC中使用CDI和EJB bean,或者在JSF中使用Spring Bean。
你通常不会直接使用2个直接竞争的技术。 Spring bean + CDI + EJB在同一个应用程序中,或者Spring MVC + JSF是愚蠢的。