【问题标题】:JSF injecting and accessing Session Scoped ManagedBean in a Request Scoped BeanJSF 在 Request Scoped Bean 中注入和访问 Session Scoped ManagedBean
【发布时间】:2015-10-03 14:55:51
【问题描述】:

我有一个@SessionScoped ManagedBean,我已将它注入@RequestScoped 以访问存储在会话中的用户。我的代码正在运行我只想知道我是否使用了一个好的做法,如果没有,你能告诉我有什么问题吗?因为我是 JSF 的新手,我不想从一开始就学习一些糟糕的编码,提前非常感谢你。

我的实体利用者:

    @Entity
    public class Utilisateur {

    @Id
    @GeneratedValue( strategy = GenerationType.IDENTITY )
    private Long      id;
    @NotNull( message = "Veuillez saisir une adresse email" )
    @Pattern( regexp = "([^.@]+)(\\.[^.@]+)*@([^.@]+\\.)+([^.@]+)", message = "Merci de saisir une adresse mail valide" )
    private String    email;
    @Column( name = "mot_de_passe" )
    @NotNull( message = "Veuillez saisir un mot de passe" )
    @Pattern(regexp = ".*(?=.{8,})(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).*", message = "Le mot de passe saisi n'est pas assez sécurisé")
    private String motDePasse;
    @NotNull( message = "Veuillez saisir un nom d'utilisateur" )
    @Size( min = 3, message = "Le nom d'utilisateur doit contenir au moins 3 caractères" )
    private String    nom;
    @Column( name = "date_inscription" )
    private Timestamp dateInscription;
//getters .. setters..
    }

我的实体农场:

@Entity
public class Ferme {

    @Id
    @GeneratedValue( strategy = GenerationType.IDENTITY )
    @Column( name = "id_ferme" )
    private Long      id_ferme;
    @Column( name = "nom_ferme" )
    private String nom_ferme;
    @ManyToOne
    @JoinColumn( name = "utilisateur_id" )
    private Utilisateur utilisateur;

//getters .. setters..

}

我的@Statless DAO:

@Stateless
public class UtilisateurDao {
 @PersistenceContext( unitName = "myBD_PU" )
    private EntityManager       em;

 public List<Ferme> lister( Utilisateur user) throws DAOException {
        try {
            TypedQuery<Ferme> query = em.createQuery( "SELECT u FROM Ferme u WHERE u.utilisateur = :userid", Ferme.class );
            query.setParameter("userid", user);

            return query.getResultList();
        } catch ( Exception e ) {
            throw new DAOException( e );
        }
    }
}

我的登录豆:

    @ManagedBean
    @SessionScoped
    public class LoginBean implements Serializable {

        private static final long serialVersionUID = 1L;

        private String email,mdp;
        private Utilisateur user;
        private boolean LoggedIn;
        @EJB 
        UtilisateurDao utilisateurDao; 

        // getters .. setters



public String authentification() {

    if (utilisateurDao.login(email, mdp) != null) {
        user = utilisateurDao.login(email, mdp);
        LoggedIn = true;
        return "listeFermes.xhtml?faces-redirect=true";
    }
    LoggedIn = false;
    FacesMessage message = new FacesMessage( "E-mail ou Mot de passe incorrecte!" );
    FacesContext.getCurrentInstance().addMessage( null, message );

    return "";
}

public String logout() {
    FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
    return "/login.xhtml?faces-redirect=true";
}
     }

我的 ListeFermesBean:

    @ManagedBean
    @RequestScoped
    public class ListeFermesBean implements Serializable{

        /**
         * 
         */
        private static final long serialVersionUID = 1L;

        @ManagedProperty(value="#{loginBean}")
        private LoginBean loginBean;

        @EJB
        UtilisateurDao utilisateurDao;

        private Utilisateur user;
        private List<Ferme> liste;

public List<Ferme> getListe() {
        liste = new ArrayList<Ferme>();
        user = loginBean.getUser();
        return  liste = utilisateurDao.lister(user);
    }
    }

登录.xhtml:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html"> 
    ...
    ...
      <h:form id="Login">
         <fieldset>
            <legend>Login</legend>
            <h:outputLabel for="email">Adresse email <span class="requis">*</span></h:outputLabel>
            <h:inputText id="email" value="#{loginBean.email}" size="20" maxlength="60">
            </h:inputText>
            <h:message id="emailMessage" for="email" errorClass="erreur" />
            <br />

            <h:outputLabel for="motdepasse">Mot de passe <span class="requis">*</span></h:outputLabel>
            <h:inputSecret id="motdepasse" value="#{loginBean.mdp}" size="20" maxlength="20">
            </h:inputSecret>
            <h:message id="motDePasseMessage" for="motdepasse" errorClass="erreur" />
            <br />

            <h:messages globalOnly="true" infoClass="erreur" />

            <h:commandButton value="Login" action="#{loginBean.authentification}" styleClass="sansLabel">
            </h:commandButton>
            <br />
            <h:commandButton value="Logout" action="#{loginBean.logout}" styleClass="sansLabel" />
            <br />
            <h:link value="Inscrivez-vous" outcome="inscription" />



          </fieldset>
        </h:form>   
    </h:body>
</html>

最后是listeFermes.xhtml 页面,该页面显示来自listeFermesBean 的列表,用户ID 存储在会话中的对象User 中。

<!DOCTYPE html>
<html lang="fr"
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:c="http://java.sun.com/jstl/core">
    <h:head>
        <title>SUCCES</title>
    </h:head>
    <h:body>

        <ui:fragment rendered= "#{!loginBean.loggedIn}">
        Not logged !
        </ui:fragment>
        <ui:fragment rendered= "#{loginBean.loggedIn}">
        Welcome : #{loginBean.user.nom} <br />
        E-mail : #{loginBean.user.email} <br />

        <table border="1">
        <tr>
            <td>Nom Ferme</td>
            <td>Nom User</td>
            <td>ID User</td>
        </tr>
        <c:forEach items="#{ listeFermesBean.liste }" var="x">
        <tr>
            <td>#{x.nom_ferme}</td>
            <td>#{x.utilisateur.nom}</td>
            <td>#{x.utilisateur.id}</td>
        </tr>
        </c:forEach>      
        </table>
        </ui:fragment>

    </h:body>
</html>

【问题讨论】:

  • 我会使用 CDI 而不是 JSF(@Named 而不是 @ManagedBean@Inject 而不是 @ManagedProperty 和范围 - 这是较新的技术)并且我不会将 @EJB 注入@RequestScoped 但我会在 @SessionScoped 中创建此方法并委托调用它。使用@Stateless,这不是问题,但如果您使用@Stateful,就会出现问题。
  • @Geinmachi 谢谢你的建议。因此,如果我确实理解了,您是说我不应该在 SessionScoped 和 RequestScoped 中都注入 EJB,而是应该将会话中使用“用户”对象的所有方法创建到 SessionScoped 中,然后我可以调用它们在 RequestScoped Bean 中?
  • 是的,这是关于将@Stateful 注入@RequestScoped 的线程,因此您可以了解我在说什么。 stackoverflow.com/questions/4562941/…
  • @Geinmachi 好的,非常感谢您的帮助!
  • TL;DR : 将范围更广的 JSF 托管 bean 注入到范围更窄的 JSF 托管 bean 中是一种合法的游戏。然而,反过来是不真实的。换句话说,将会话范围的 JSF 托管 bean 注入请求范围的 JSF 托管 bean 是完全合法的。

标签: session jsf jakarta-ee code-injection requestscope


【解决方案1】:

正如评论中所说,您应该使用 cdi 注入。我相信这也是一个很大的禁忌:

public List<Ferme> getListe() {
        liste = new ArrayList<Ferme>();
        user = loginBean.getUser();
        return  liste = utilisateurDao.lister(user);
    }

您应该在您的 getter/setter 中做任何业务密集型的事情。原因是可以在后台多次调用。

相反,您应该在注入服务后调用的方法中调用您的服务。

@PostConstruct
public void init(){
    listeFerm = utilisateurDao.lister(user);
}
public List<Ferm> getListFerm(){
   return listFerm;
}

您没有发布您的身份验证方法(可能是故意的)。

保护您的身份验证系统,您说过您将在之后处理此问题,但您仍然不需要通过 DAO。您应该在文档中阅读有关 JAAS 的信息,了解如何自动处理这个问题,然后您不需要通过服务,您可以在 bean 中验证用户。即:Request.login(username, password) 如果我没记错的话。不过,您必须阅读有关该主题的内容,在验证用户身份时应该使用 hash + salt。

【讨论】:

  • 谢谢您的回答,我的loginBean现在是这样的(在上面的新答案中)我无法在此评论中添加它。
  • 我已经再次发布了我的身份验证方法(在我上面给你的新答案中),如果这就是你所说的。在此先感谢:)
  • @dwix 您打算将密码存储为纯文本吗?因为这就是您丢失每个用户密码的方式。当您发布附加代码时,您应该只编辑您的主要问题。我将编辑我的帖子以提醒您的新代码。然后你可以接受我的回答,因为它对你有帮助(点击 v)。也欢迎为互联网点投票。
  • 不,我稍后会处理密码,谢谢!我会投票让你知道它是否有帮助:)
  • D'accord,谢谢 beaucoup pour ton aide!
【解决方案2】:
@Named
@SessionScoped
public class LoginBean implements Serializable {

    private static final long serialVersionUID = 1L;

    private String email,mdp;
    private Utilisateur user;
    private boolean LoggedIn;
    private List<Ferme> liste;
    private Ferme ferme = new Ferme();
    @Inject
    UtilisateurDao utilisateurDao; 



    public Ferme getFerme() {
        return ferme;
    }
    public void setFerme(Ferme ferme) {
        this.ferme = ferme;
    }
    public void setListe(List<Ferme> liste) {
        this.liste = liste;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public String getMdp() {
        return mdp;
    }
    public void setMdp(String mdp) {
        this.mdp = mdp;
    }
    public Utilisateur getUser() {
        return user;
    }
    public void setUser(Utilisateur user) {
        this.user = user;
    }
    public boolean isLoggedIn() {
        return LoggedIn;
    }
    public void setLoggedIn(boolean loggedIn) {
        LoggedIn = loggedIn;
    }


    public String authentification() {

        if (utilisateurDao.login(email, mdp) != null) {
            user = utilisateurDao.login(email, mdp);
            LoggedIn = true;
            return "listeFermes.xhtml?faces-redirect=true";
        }
        LoggedIn = false;
        FacesMessage message = new FacesMessage( "Wrong E-mail or Password!" );
        FacesContext.getCurrentInstance().addMessage( null, message );

        return "";
    }



public String logout() {
            FacesContext context = FacesContext.getCurrentInstance();
            context.addMessage(null, new FacesMessage("You are disconnected!"));
            ExternalContext externalContext = context.getExternalContext();
            externalContext.getFlash().setKeepMessages(true);
            externalContext.invalidateSession();

            return "/login.xhtml?faces-redirect=true";
        }

    public void deleteFerme(int id) {
            utilisateurDao.supprimerFerme(user, id);
        }

        public void addFerme() {
            utilisateurDao.creerFerme(ferme, user);
        }

        public List<Ferme> getListe() {
        return liste;
    }

    @PostConstruct
    public void init(){
        liste = utilisateurDao.lister(user);
    }

// 我应该声明我的Ferme 然后在@PostConstruct 中初始化它new Ferme(); 吗?还是保持原样? // & 我应该使用 CRUD 方法,这些方法使用存储在会话中的“用户”对象,在 @SessionScope bean 中?然后调用我的@RequestScoped bean 中的方法?像这样:

@SessionScope
public class LoginBean {

    ..
    ..
    public void addFerme() {
    utilisateurDao.creerFerme(ferme, user);
}
    }


    //////..... and then in the RequestScoped bean :

@RequestScoped
    ..
    ..
    @Inject
    private LoginBean loginBean;

    public void addFerme() {

            loginBean.addFerme();
        }

//登录方式

@Stateless
public class UtilisateurDao {

@PersistenceContext( unitName = "MyBD_PU" )
    private EntityManager       em;

public Utilisateur login(String email, String mdp) throws DAOException {
        Utilisateur user = null;
        Query requete = em.createQuery( JPQL_LOGIN );
        requete.setParameter( PARAM_EMAIL, email ).setParameter(PARAM_PWD, mdp);

        try {
            user = (Utilisateur) requete.getSingleResult();
            if (user!=null) {
                return user;
            }
            return null;
        } catch ( NoResultException e ) {
            return null;
        } catch ( Exception e ) {
             FacesMessage message = new FacesMessage( FacesMessage.SEVERITY_ERROR, e.getMessage(), null );
             FacesContext facesContext = FacesContext.getCurrentInstance();
             facesContext.addMessage( null, message );
        }
        return user;

    }

}

【讨论】:

    猜你喜欢
    • 2014-01-04
    • 2013-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-09
    • 2016-09-09
    相关资源
    最近更新 更多