我正在使用JSF(2.2)和EclipseLink(JPA 2.1)使用NetBeans 8.0.2构建Web应用程序。
让我们假设当前功能是安静的基本包含:登录,注销,注册,用户角色,仅供管理员使用的页面(通过使用过滤器)等。
我已经阅读过maaany SO Q& A(主要来自@BalusC,谢谢!)并且想验证我的设计是否正确/遵循最佳做法。
目前我有:
也许这个名字是多余的,但我想要一个明显的名称开头),对应于数据库中的用户:
@Entity
@Table(name = "Users")
@XmlRootElement
@NamedQueries({
@NamedQuery(name = "UserEntity.findAll", query = "SELECT u FROM UserEntity u")...})
public class UserEntity implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "userID")
private Integer userID;
...
}
它使用UserService
并保留相关的UserEntity
。它的方法用于.xhtml文件的EL
@ManagedBean(name = "user") // name not needed here, but I kind of like it
@SessionScoped
public class User implements Serializable {
private UserEntity userEntity; // with getter or make this public to be accessed directly from EL?
public String login() {
userEntity = UserService.find(username);
...
}
...
}
基本上有数据库访问方法:
public class UserService {
public static String insertUser(UserEntity user) {
String retMessage;
EntityManager em = JPAResource.factory.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
try {
em.persist(user);
tx.commit();
retMessage = "ok";
return retMessage;
}
catch (PersistenceException e) {
if (tx.isActive()) tx.rollback();
retMessage = e.getMessage();
return retMessage;
}
finally {
em.close();
}
}
...
}
在某些时候,我注意到UserService只能有静态方法,因此我可以在不创建实例的情况下访问它们。
这很糟糕,为什么?
我想正确的方法是将UserService作为: import javax.ejb.TransactionAttribute; import javax.ejb.TransactionAttributeType; ...
@Stateless
public class UserService {
@PersistenceContext
private EntityManager em;
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public static String insertUser(UserEntity user)
{
em.persist(user);
}
...
}
用户bean为:
@ManagedBean(name = "user")
@SessionScoped
public class User implements Serializable {
@EJB
private UserEntity userEntity;
public String login() {
userEntity = UserService.find(username);
...
}
...
}
这是对的吗?
我不确定@Stateless
,@EJB
,PersistenceContext
到底是什么意思。
(它们分别来自javax.ejb.Stateless
,javax.ejb.EJB
,javax.persistence.PersistenceContext
吗?)
使用@Stateless
和@EJB
是否允许我使用UserService
而不创建实例并且没有静态方法?
检查交易怎么样? @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
是否涵盖了我?即无需进一步检查?如果抛出异常,方法return
会带有相关消息吗?
使用@PersistenceContext
,创建EntityManager
实例的人/谁?
这种设计是否是良好的做法,尊重关注点的分离等?
谢谢!
答案 0 :(得分:1)
@Stateless
是替代静态方法的方法。如果您使用NetBeans,您可以自动生成这些@Stateless
类,它们在那里称为外观(在NetBeans中 - >右键单击pacakge - > new - >实体类的会话bean并选择实体)。
您不能自己创建EJB
个实例,只需使用@EJB
注释,容器就会为您提供实例"。
对于您有单独注释的交易,您可以阅读javax.ejb.TransactionAttribute
。您只需使用EJB
注释javax.ejb.TransactionAttributeType
类/方法并给予@SessionScoped
以及所有内容,容器将为您开始/结束/嵌套(阻止)事务。
对于关于@RequestScoped
的部分,它可以是您的控制器。我们假设您有5个xhtml页面。然后创建5个支持bean(@ViewScoped
/ @Inject
等),并在每个控制器类中使用EJB
。因此,您的支持bean将其逻辑范围缩小到仅1页,然后将进一步的操作转发给控制器类。 Controller类可以有只有1行的方法(API),它将操作转发到@Stateful
。在EJB中,您可以使用与此控制器通信的服务(@Stateless
),此服务与其他类进行通信(如先前支持bean,但现在只需将其称为管理器),并且管理器具有业务逻辑。此逻辑可以通过先前生成的外观(EJB
)将数据持久保存到数据库中。
您不需要使用javax.annotation.security.RolesAllowed
过滤器来控制角色,您可以使用注释@ManagedBean
并指定哪个角色可以调用哪个方法。
这是我的观点,它可能不是很复杂的解释,但有很多工作人员可以使用关键字进行谷歌搜索。
编辑:
不要使用@ManagedProperty
和@Named
等JSF注释。更好地使用CDI @Inject
和{{1}}等新技术。