0

我阅读了 BalusC 关于 JSF 通信的优秀教程,它帮助我建立了我的应用程序的基础知识。我想与它的所有子类共享在 SessionScoped BaseBean 类中设置的当前登录的用户对象。这可以在不@ManagedProperty为每个需要引用登录用户的单个支持 bean 注入 BaseBean 的情况下完成吗?

我的课程如下。如果需要更多信息,请告诉我,我很乐意更新我的问题。

BaseBean 类

所有其他 bean 都是该 bean 的子类。我这样做是为了允许 bean 之间的代码重用。

@ManagedBean
@SessionScoped
public class BaseBean {

    @EJB
    protected UserDao userDao;
    // Other DAOs along with methods (like isLoggedIn()) shared between beans

    private User loggedInUser;

    public User getLoggedInUser() {
        return loggedInUser;
    }

    public void setLoggedInUser(User user) {
        loggedInUser = user;
    }

    public boolean isLoggedIn() {
        return loggedInUser != null;
    }

}

LoginBean 类

登录页面的支持 bean。为了减少数据库调用的数量,我使用上述教程中的@ManagedProperty 方法在@SessionScoped BaseBean 中设置用户对象。现在登录和设置loggedInUser按预期工作。

@ManagedBean
@RequestScoped
public class LoginBean extends BaseBean {

    @ManagedProperty(value = "#{baseBean}")
    protected BaseBean baseBean;

    private String username;
    private String password;

    public String login() {
        Subject currentUser = SecurityUtils.getSubject();
        try {
            currentUser.login(username, password);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            baseBean.setLoggedInUser(userDao.getUser(username));
        }
        return "index";
    }

    public String getUserFirstName() {
        return baseBean.getLoggedInUser().getFirstName();
    }

    // Getters and Setters, including for the @ManagedProperty baseBean.

}

创建报表类

这是许多人中一种支持 bean 的示例。我想引用当前登录的用户来创建报告,但是如果下面的代码运行,用户将是null!我可以让它工作的唯一方法是@ManagedProperty为 BaseBean 添加一个带有 getter 和 setter 的条目,就像在 LoginBean 类中一样。我真的很想避免这种情况,因为我会将这段代码复制粘贴到我拥有的几乎每一个支持 bean 上!

@ManagedBean
@RequestScoped
public class CreateReport extends BaseBean {

    private Report report = new Report();

    public String createReport() {
        report.setOwner(getLoggedInUser()); // Use inherited method
                                            // instead of DI-ing BaseBean
        reportDao.create(report);
        return "index";
    }

}

二手软件

  • 玻璃鱼 4
  • 莫哈拉 2.2

编辑

我发现的一种解决方案是直接从 FacesContext 获取 BaseBean 的实例(我猜想其他 bean 不在同一个上下文中或“看不到它?”)。下面的代码(来自 BaseBean)会做我想做的事,但是任何 bean 子类都必须调用base(),这看起来很尴尬和错误。

protected FacesContext context = FacesContext.getCurrentInstance();

public BaseBean base() {
    return (BaseBean) context.getApplication().evaluateExpressionGet(context, "#{baseBean}", BaseBean.class);
}
4

2 回答 2

0

自己创建BaseBean一个托管 bean 并将其用作所有其他托管 bean 的超类是不应该进行的两件事。

相反,您可以:

  • 从中删除@ManagedBean注释BaseBean
  • 保存loggedInUser到会话。
  • isLoggedIn作为受保护的方法保存在BaseBean. 您将能够通过FacesContext那里到达会话并loggedInUser从会话中获取。

    ((HttpServletRequest)FacesContext.getCurrentInstance() .getExternalContext().getRequest()).getSession()

ps:我不知道我在提供静态变量时到底在想什么。

于 2015-03-30T08:50:50.267 回答
0

我可以看到您想要实现身份验证和身份验证控件,那么您可以使用 JSF Filters。您可以将 BaseBean 类保留在会话范围内,创建一个实现 javax.servlet.Filter 的新类,并在此类中通过会话获取 BaseBean 类,例如:

public class LoginFilter implements javax.servlet.Filter {

    @Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {    
    HttpServletRequest req = (HttpServletRequest) request;
    BaseBean base = (BaseBean) req.getSession().getAttribute("baseBean");

    if (base != null && base.isLoggedIn()) {
        // to do something
        chain.doFilter(request, response);
    } else {
        // to do something
        HttpServletResponse res = (HttpServletResponse) response;
        res.sendRedirect(req.getContextPath() + "/index.xhtml");
    }
}

public void init(FilterConfig config) throws ServletException {
    // to do something
}

public void destroy() {
    // to do something
}   

}

现在,如果你想用你的 BaseBean 类创建一个报告,你可以得到你的 BaseBean 类的会话:

BaseBean base = (BaseBean) ( FacesContext.getCurrentInstance()
    .getExternalContext().getRequest()).getSession().getAttribute("baseBean") );

那么我对您的建议是避免继承并利用 JSF 的优势。

我希望这些信息对您有所帮助。

祝你好运。

于 2015-03-31T13:12:44.270 回答