许多@RequestScoped子类从@SessionScoped bean访问变量而没有复制粘贴@ManagedProperty?

时间:2015-03-30 04:37:08

标签: java jsf-2 dependency-injection managed-bean managed-property

我读了BalusC的优秀tutorial on JSF communication,它帮助我建立了我的应用程序的基础知识。我想与SessionScoped BaseBean类中的所有子类共享当前登录的User对象。如果不为需要引用登录用户的每个支持bean注入BaseBean作为@ManagedProperty,是否可以这样做?

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

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中设置User对象。现在登录并设置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.

}

CreateReport Class

这是许多人的一个支持bean的示例。我想引用当前登录的用户以创建报告,但是如果下面的代码运行,则用户将是null!我可以让它工作的唯一方法是为BaseBean添加一个带有getter和setter的@ManagedProperty条目,就像在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";
    }

}

二手软件

  • Glassfish 4
  • Mojarra 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);
}

2 个答案:

答案 0 :(得分:0)

使BaseBean成为托管bean本身,并将其用作所有其他托管bean的超类是不应该做的两件事。

相反,你可以:

  • @ManagedBean删除BaseBean注释。
  • loggedInUser保存到会话。
  • isLoggedIn保留为BaseBean中的受保护方法。您可以通过FacesContext与会话进行会话,并从会话中获取loggedInUser

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

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

答案 1 :(得分:0)

我可以看到您想要实现身份验证和身份验证控件,然后您可以使用JSF过滤器。您可以使用会话范围保留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的优点。

我希望这些信息可以帮到你。

祝你好运。