我正在尝试使用jersey为struts应用程序添加休息服务。为此我需要以这样的方式隔离java代码,以便struts和rest api可以共同访问它。这样做是为了使代码在rest和struts之间共享,任何变化都会反映在这两个服务中。我想知道,这个想法有多少是可行的,而这就是人们设计休息服务的通常情况。
答案 0 :(得分:2)
虽然我们的表示层不是基于Struts的(通常是Spring Web MVC或JSF),但我们使用Spring 3.0 + Java EE 6,特别是EJB 3.0和JPA 2.0来处理这种情况。
EJB 3.0无状态会话bean工作得很好 - 它们可以具有声明性(基于注释)依赖注入和事务划分,或者它们可以使用任何传统机制管理它们的事务,依赖关系和资源。它们与JPA 2.0无缝集成,非常容易进行单元测试。与纯Spring bean相比,它的主要优点是可以独立于Web应用程序(作为EJB JAR)进行部署。
在面向前端的Web服务上,我们还使用Jersey / JAX-RS。由于Jersey / JAX-RS依赖注入被破坏(它不像其他Java EE一样使用Weld / CDI),我们不得不求助于Spring DI将前面的REST资源类“连接”起来。 '后端'EJB。好处是它可以很好地将EJB注入我们的MVC控制器,也可以与JSF托管bean一起使用。或者,您可以单独使用Spring编写REST-ful资源(无论哪种方式都有自己的优点/缺点,但通常都可以很好地完成工作)。
我知道我掩饰了整件事,但我很乐意根据要求分享更多细节。
编辑:根据要求提供更多详细信息。
你是学习泽西/ JAX-RS的第一站,必须是Jersey User Guide。您还可以通过“网络”轻松找到几个教程/示例。
虽然您应该能够将Jersey / JAX-RS资源打包到与Struts页面相同的WAR中,但我们采用了更简单的替代方法来单独部署它们。
现在,在部署到Glassfish 3.1时,我们遇到了this错误,还记录了here。最重要的是@EJB
注射对我们没有预期效果。
所以,相反,我们使用jersey-spring
contrib模块,在example之后重新使用Spring。
无论如何,其余部分是标准的Java EE 6 / EJB 3.0。我们识别并将所有常见功能放入“服务”层,这些层主要实现为@Stateless
EJB。
持久性是通过JPA注入@Entity
访问的JPA EntityManager
来处理的。使用@TransactionAttribute
以声明方式划分事务。
以下是典型的EJB + JPA服务bean的快速说明:
@Stateless
public class WidgetServiceBean implements WidgetService {
@PersistenceContext
private EntityManager em;
@Override
public List<Widget> findWidgetByName(String name) {
return em.createNamedQuery("Widget.findByName", Widget.class)
.setParam("name", name).getResultList();
}
@Override
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void removeWidgetById(int id) {
em.find(Widget.class, id).remove();
}
}
(显然不是生产质量,而只是表明它们的“精益”程度。)
服务层和实体打包为EJB JAR,可以单独部署,并通过全局JNDI查找提供给所有其他模块。或者,它们可以部署在Struts或JAX-RS WAR中,从Java EE 6(Glassfish 3.x)开始,它们将被发现,作为模块的一部分进行部署,并可用于同一WAR中的其他组件。
有些人可能认为,如果你正在使用Spring容器,那么使用Spring bean会更简单。我想说,可能,但是你还必须使用Spring的持久性框架和Spring的事务框架。 (Spring还提供了声明式事务和持久性。)如果你已经大量投入Spring,那么这可能是一条更容易的道路。
OTOH,EJB 3.0,JPA 2.0和JTA也从它们的前辈和中彻底简化,它们是Java EE标准的一部分,因此它是一个具有很多维度的架构决策。