我对JSF2 + Spring + EJB3或它们的任意组合的混合使用感到有些困惑。我知道Spring的一个主要特性是依赖注入,但是对于JSF托管bean,我可以使用@ManagedBean
和@ManagedProperty
anotations,并获得依赖注入功能。使用EJB3,我更加困惑何时将它与JSF一起使用,或者甚至有理由使用它。
那么,在什么样的情况下使用Spring + JSF2或EJB3 + JSF2是个好主意?
到目前为止,我只使用JSF2创建了一些小型Web应用程序,而且从不需要使用Spring或EJB3。但是,我在很多地方都看到人们正在将所有这些东西放在一起。
答案 0 :(得分:62)
首先,Spring和EJB(+ JTA)是竞争技术,通常不能在同一个应用程序中一起使用。选择其中一个。 Spring 或 EJB(+ JTA)。我不会告诉你选择哪一个,我只会告诉你一些历史和事实,以便你更容易做出决定。
他们试图解决的主要问题是提供具有自动事务管理的业务服务层API。想象一下,您需要触发多个SQL查询来执行单个业务任务(例如下订单),其中一个失败,那么您当然会喜欢所有被回滚,以便DB保持与以前相同的状态,好像完全没有发生任何事情。如果您没有使用事务,那么数据库将处于无效状态,因为第一批查询实际上已成功。
如果您熟悉基本的JDBC,那么您应该知道这可以通过关闭连接上的自动提交,然后按顺序触发这些查询,然后在同一个{{1}中执行commit()
来实现。其中try
catch (SQLException)
执行的人。但是,每次都要实现tedious。
使用Spring和EJB(+ JTA),单个(无状态)业务服务方法调用默认情况下透明地计为单个完整事务。这样您根本不需要担心事务管理。您不需要手动创建rollback()
,也不需要显式调用EntityManagerFactory
,例如当您将业务服务逻辑紧密耦合到JSF支持bean类和/或正在使用{{}时1}}而不是JPA中的em.getTransaction().begin()
。例如,您可以使用以下具有JPA的EJB类:
RESOURCE_LOCAL
如果您的JSF支持bean中有JTA
并在操作方法中调用@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;
调用或orderService.placeOrder(newOrder);
调用因异常而失败,那么它将回滚任何到目前为止执行的updateQuantity()
调用,并使数据库处于干净清晰的状态。当然,您可以在JSF辅助bean中捕获该异常并显示一条面部消息。
注意应该是“Spring”是一个非常大的框架,它不仅竞争EJB,还竞争CDI和JPA。以前,在黑暗的J2EE时代,当EJB 2.x实现起来非常糟糕时(EJB 2.x中的上述EJB 3.x persist()
示例需要至少5倍的代码和一些XML代码)。 Spring提供了一个更好的替代方案,它需要更少的Java代码(但仍然有许多XML代码)。 J2EE / EJB2从Spring中吸取了教训,并附带了Java EE 5,它提供了新的EJB3 API,它比Spring更加灵活,根本不需要XML。
Spring还提供IoC / DI(控制反转;依赖注入)。这是在由XML配置的J2EE时代,这可能会非常落伍。如今Spring也使用注释,但仍然需要一些XML。从Java EE 6开始,在学习了Spring的经验之后,CDI就提供了相同的DI功能,但是不需要XML。使用Spring DI updateQuantity()
/ OrderService
和CDI @Component
/ @Autowired
,您可以实现与JSF对@Named
/ @Inject
所做的相同,但是Spring DI和CDI提供了更多优势:你可以编写拦截器来预处理或后处理托管bean创建/销毁或托管bean方法调用,你可以创建自定义范围,生产者和消费者,你可以注入在更广泛的范围等实例中缩小范围
Spring还提供基本上与JSF竞争的MVC。将JSF与Spring MVC混合是没有意义的。另外,Spring还提供了数据,它本质上是JPA上的额外抽象层,进一步最小化了DAO样板(但实质上并不代表业务服务层)。
答案 1 :(得分:5)
这里没有真正简单的答案,因为Spring有很多东西。
在一个非常高的层面上,Spring与Java EE竞争,这意味着你可以使用其中任何一个作为完整的堆栈框架。
在更细粒度的水平上,Spring IoC容器和Spring Beans与CDI和CD的组合竞争。 Java EE中的EJB。
对于Web层,Spring MVC与JSF竞争。一些Spring xyzTemplate与JPA接口竞争(两者都可以使用例如Hibernate作为其实现)。
可以混合搭配;例如,使用CDI&使用Spring MVC的EJB bean,或者使用Spring Beans和JSF。
您通常不会同时使用2个直接竞争的技术人员。在同一个应用程序中使用Spring bean + CDI + EJB,或者Spring MVC + JSF是愚蠢的。