jsf - 从请求作用域 bean 访问 session 作用域 bean

标签 jsf jsf-2 session-scope

我正在尝试使用 IceFaces 页面上找到的模式。(我没有使用 IceFaces,而是使用 PrimeFaces)

在本例中,我有两个 bean:

UserControllerUsermodel

在我的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;
    }

我有一个template.xhtml,其中包含:

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

问题是它不起作用,没有获取 loggedIn 属性值。

我的猜测是,以这种方式访问​​我有点创建一个新的UserModel实例,如果是这样,那就是一个问题,因为我的UserController不是 session 范围的,仅UserModel

编辑

我知道我可以简单地检查 UserModel userVo 属性是否已设置,而不是使用此 loggedIn 属性,但问题与 session 有关范围 bean,我无法从 UserController 访问它,它是在其中设置的,因为它不是范围 session ,并且我的 template.xhtml 将由每个页面使用。

最佳答案

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

您可能过于关注此 ICEfaces blog其中包含 mainly nonsense .

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

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

然而,“登录用户”的用例很特殊。您不希望将该实体作为 session 范围的托管 bean,否则它会由 JSF 隐式创建。您最好自己直接将其放入 session 范围中,以便您可以检查#{notempty 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 成为一个 session 范围的 bean,它保存 User 实体,您只需要添加一个额外的方法来检查用户是否是是否已登录,以便您可以通过 #{userController.loggedIn} 在 EL 中使用它。

@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>

关于jsf - 从请求作用域 bean 访问 session 作用域 bean,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10658944/

相关文章:

jsf - 拦截器不适用于 JSF 托管 bean?

java - 在 jsf 2 中处理用户 session

css - JSF2/Primefaces 布局性能

java - 使 JSF 页面即使在 View 状态丢失后也始终具有响应能力和功能

ajax - JSF - 在 ajax 调用中传递参数 - 这段代码有什么问题?

java - Primefaces 数据表分页不起作用

java - Spring如何 Autowiring session 作用域的bean?

jsf - 用于授权的RequestFilter和SessionBean

linux - 如何避免 glassfish jsf 中的连接超时?

jsf - 启用选择时,DataModel 必须实现 org.primefaces.model.SelectableDataModel。