访问会话范围的bean的请求范围豆(Access session scoped bean from

2019-06-24 14:16发布

我试图使用ICEfaces的页面上发现一个规律。(我不使用ICEfaces的,使用PrimeFaces)

在这种情况下,我有两个豆子:

UserController中的usermodel

在我的usermodel我有UserVO的实例(由另一个程序员创建)。 在我UserController的我有这样的:

@ManagedBean
@RequestScoped
public class UserController implements Serializable
{

    private static final long serialVersionUID = 1L;
    private UserBO bo;
    private UserModel model;

    public UserController()
    {
        bo = new UserBO();
        model = new UserModel();
    }

    public void Login() throws IOException
    {
        model.setUserVo(bo.executeLogin(model.getUserVo()));
        ExternalContext externalContent = FacesContext.getCurrentInstance().getExternalContext();
        if (!model.getUserVo().isError())
        {
            model.setLoggedIn(true);
            externalContent.getSessionMap().put("userSession", model);
            externalContent.redirect(externalContent.getRequestContextPath() + "/views/request/search.html");
        } else
        {
            model.setLoggedIn(false);
            FacesMessage facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR, model.getUserVo().getMessage(), model.getUserVo().getLogin());
            FacesContext.getCurrentInstance().addMessage(null, facesMessage);
        }
    }

    public UserBO getBo()
    {
        return bo;
    }

    public void setBo(UserBO bo)
    {
        this.bo = bo;
    }

    public UserModel getModel()
    {
        return model;
    }

    public void setModel(UserModel model)
    {
        this.model = model;
    }
}

正如你所看到的,我创建的usermodel的一个新实例,并用什么从返回的设置bo.executeLogin()它工作正常,返回我的对象。

为了确保用户登录,我有我的usermodel属性:

@ManagedBean
@SessionScoped
public class UserModel
{

    private UserVO userVo;
    private Boolean loggedIn = false;

    public UserModel()
    {
        userVo = new UserVO();
    }

    public UserVO getUserVo()
    {
        return userVo;
    }

    public void setUserVo(UserVO userVo)
    {
        this.userVo = userVo;
    }

    public Boolean getLoggedIn()
    {
        return loggedIn;
    }

    public void setLoggedIn(Boolean loggedIn)
    {
        this.loggedIn = loggedIn;
    }

我有一个所引用

<ui:fragment rendered="#{userModel.loggedIn}">
            <ui:include src="../includes/top.xhtml"/>
</ui:fragment>

而事情是,它不工作时,没有得到loggedIn属性值。

我的猜测是,访问这种方式我有点创建的usermodel的新实例,如果是这样,这是一个问题,因为我的UserController的不是会话范围,只有的usermodel

编辑

除了使用如此loggedIn属性我知道我可以简单地检查的usermodel userVo属性设置,但问题是关于会话范围的bean,我无法从UserController中 ,它被设置,因为它没有范围的会话访问它,我的template.xhtml将每一个页面中使用。

Answer 1:

而不是创建一个新的UserModel在您的实例UserController ,用注入它@ManagedProperty

UserController

@ManagedProperty(value="#{userModel}")
private UserModel model;

// add getter and setter for userModel (important!)

然后,你不必实例化它在构造函数中,将永远得到会话范围的情况下UserModel在你的控制器。

更新:

我认为,你与你的严格MVC方法登录过程复杂化。 在JSF模型,视图和控制器之间的边界线是有些模糊的或重叠的。

我建议阅读这个有趣的问题和答案 ,尤其是这个答案对于有关该主题的更多信息。

至于你的具体问题。 我不太清楚是什么原因,但你绝对应该避免都由你自己来实例化管理的bean,并反复折腾都注入和豆类自初始化的实例。

此外,我会推荐给你的豆一起合并成一个单一的豆。 那你没有与循环依赖和空引用的问题。



Answer 2:

(这是最初发布于https://stackoverflow.com/questions/10691324/working-with-3-java-beans-controller-backing-model ,但OP删除的问题,我不想扔掉答案,我想在这个问题上重新发布适用为好)

你可能都集中在这个太多ICEfaces的博客包含主要是无稽之谈 。

你应该有一个JSF托管bean充当控制器,你已经拥有了它: UserController 。 你应该有它代表了模型的简单实体bean,你已经拥有了它: UserVO 。 你应该有一个enterprise bean它代表了服务,你已经拥有了它: UserBO 。 最后两不需要是JSF管理的Bean。

根据您的问题记录你使用Glassfish的,因此你可以使用JPA和EJB的。 因此,模型类应该是一个JPA @Entity和服务类应该是一个@Stateless EJB。

“登录用户”的使用情况下,然而特殊。 你不希望有实体作为会话范围的受管Bean或将通过JSF隐式地创建。 你最好把它直接在会话范围自己,这样就可以在检查#{not empty user}如果用户登录或没有。

所有的一切就应该是这个样子:

@Entity
public class User {

    private String username;
    private String password;

    // ...
}
@Stateless
public class UserService {

    @PersistenceContext
    private EntityManager em;

    public User find(String username, String password) {
        return em.createQuery("SELECT u FROM User u WHERE username = :username AND password = MD5(:password)", User.class)
           .setParameter("username", username)
           .setParameter("password", password)
           .getSingleResult();
    }

}
@ManagedBean
@ViewScoped
public class UserController {

    private String username;
    private String password;

    @EJB
    private UserService service;

    public String login() {
        FacesContext context = FacesContext.getCurrentInstance();

        try {
            User user = userService.find(username, password);
            context.getExternalContext().getSessionMap().put("user", user);
            return "/views/commons/home.html?faces-redirect=true";
        }
        catch (NoResultException) {
            context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Unknown login, please try again", null));
            return null;
        }
    }

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

    // ...
}

<h:form>
    <h:inputText value="#{userController.username}" required="true" />
    <h:inputSecret value="#{userController.password}" required="true" />
    <h:commandButton value="login" action="#{userController.login}"/>
    <h:messages />
</h:form>

或者,你可以让UserController的会话范围的bean,其保持User的实体,你只需要添加一个额外的方法来检查,如果用户登录或不那么你可以通过在EL使用#{userController.loggedIn}

@ManagedBean
@SessionScoped
public class UserController {

    private User user = new User();

    @EJB
    private UserService service;

    public String login() {
        FacesContext context = FacesContext.getCurrentInstance();

        try {
            user = userService.find(user.getUsername(), user.getPassword());
            return "/views/commons/home.html?faces-redirect=true";
        }
        catch (NoResultException) {
            context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Unknown login, please try again", null));
            return null;
        }
    }

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

    public boolean isLoggedIn() {
        return user.getId() != null;
    }

    // ...
}

<h:form>
    <h:inputText value="#{userController.user.username}" required="true" />
    <h:inputSecret value="#{userController.user.password}" required="true" />
    <h:commandButton value="login" action="#{userController.login}"/>
    <h:messages />
</h:form>


Answer 3:

您可以使用依赖注入从与会话范围该bean获取值。

@Inject UserModel user; 

然后,你可以在你的用户控件的bean使用这个对象。 顺便说一句,你并不需要实现序列化时,你正在处理RequestScope豆。



文章来源: Access session scoped bean from request scoped bean