簡體   English   中英

JSF設計和@Stateless @EJB @PersistenceContext的說明/用法

[英]JSF design and @Stateless @EJB @PersistenceContext explanation/usage

我正在使用JSF(2.2)和EclipseLink(JPA 2.1)使用NetBeans 8.0.2構建Web應用程序。

假設當前功能是安靜的基本功能,包括:登錄,注銷,注冊,用戶角色,僅管理員可用的頁面(通過使用過濾器)等。

我已經閱讀了maaany SO的問答集(主要來自@BalusC ,謝謝!),並想驗證我的設計是否正確/遵循最佳實踐。

目前我有:

用戶實體(UserEntity.java)

也許這個名字是多余的,但是我想要一個明顯的名字開頭),對應於數據庫中的用戶:

@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;
    ...
}

用戶bean(User.java)

它使用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);
        ...
    }
    ...
}

還有一個UserService.java

基本上有數據庫訪問方法:

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; 導入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@Stateless @EJBPersistenceContext到底在做什么/意味着什么。 (它們分別來自javax.ejb.Statelessjavax.ejb.EJBjavax.persistence.PersistenceContext嗎?)

使用@Stateless@EJB是否可以使我使用UserService而不創建它的實例並且沒有靜態方法?

如何檢查交易呢? @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)是否覆蓋了我? 即不需要進一步檢查? 如果拋出異常,該方法將return相關消息嗎?

使用@PersistenceContext ,什么/誰在創建EntityManager實例?

這種設計是否是良好的做法,同時考慮到關注點分離等問題?

謝謝!


也可以看看:

@Stateless是替代靜態方法的方法。 如果您使用NetBeans,則可以自動生成這些@Stateless類,它們在此稱為Facades(在NetBeans->右鍵單擊pacakge-> new->會話Bean中選擇實體類,然后選擇實體)。

您不必自己創建EJB實例,只需使用@EJB批注,容器將為您提供“實例”。

對於事務,您具有單獨的注釋,可以閱讀有關javax.ejb.TransactionAttribute 您只需使用它們注釋EJB類/方法,並給定javax.ejb.TransactionAttributeType ,這就是一切,容器將為您啟動/結束/嵌套(阻止)事務。

對於@SessionScoped它可以作為您的控制器。 假設您有5個xhtml頁面。 然后創建5個支持bean( @RequestScoped @ViewScoped / @ViewScoped等),並將每個@Inject與控制器類一起使用。 因此,您的支持bean將其邏輯范圍縮小到只有一頁,然后將進一步的操作轉發到控制器類。 控制器類只能具有僅1行的方法(API),用於將操作轉發到EJB 在EJB中,您可以具有與該控制器進行通信的服務( @Stateful ),該服務與其他類進行通信(例如以前支持Bean,但現在僅稱為管理器),並且管理器具有業務邏輯。 此邏輯可以通過先前生成的外觀( @Stateless )將數據持久保存到數據庫。

您不需要使用EJB過濾器來控制角色,可以使用批注javax.annotation.security.RolesAllowed並指定可以由哪個角色調用的方法。

這是我的觀點,它可能不是一個復雜的解釋,但是您可以使用關鍵字在Google上搜索很多人員。

編輯:

不要使用@ManagedBean@ManagedProperty類的JSF注釋。 最好使用更新的技術,例如CDI @Named@Inject

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM