许多@RequestScoped 子类从@SessionScoped bean 访问变量而无需复制粘贴@ManagedProperty?
Many @RequestScoped subclasses access variable from @SessionScoped bean without copy-pasting @ManagedProperty?
我阅读了 BalusC 的优秀 tutorial on JSF communication,它帮助我建立了我的应用程序的基础知识。我想与它的所有子 class 共享在 SessionScoped BaseBean class 中设置的当前登录的用户对象。这可以在不为每个需要引用已登录用户的支持 bean 注入 BaseBean 作为 @ManagedProperty
的情况下完成吗?
我的class列在下面。如果需要更多信息,请告诉我,我很乐意更新我的问题。
BaseBean Class
所有其他 bean 都是此 bean 的子class。我这样做是为了允许 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;
}
}
登录Bean Class
登录页面的支持 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.
}
创建报表Class
这是一个来自多个支持 bean 的示例。我想引用当前登录的用户以创建报告,但是如果运行以下代码,用户将为 null
!我可以让它工作的唯一方法是为 BaseBean 添加一个带有 getter 和 setter 的 @ManagedProperty
条目,就像在 LoginBean class 中一样。我真的很想避免这种情况,因为我会将这段代码复制粘贴到我拥有的几乎每个支持 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 不在同一上下文中或 "don't see it?")。下面的代码(来自 BaseBean)会做我想做的,但是任何 bean subclass 都必须调用 base()
,这看起来很尴尬和错误。
protected FacesContext context = FacesContext.getCurrentInstance();
public BaseBean base() {
return (BaseBean) context.getApplication().evaluateExpressionGet(context, "#{baseBean}", BaseBean.class);
}
使 BaseBean
成为托管 bean 本身,并将其用作所有其他托管 bean 的超类是两件不应该进行的事情。
相反,您可以:
- 从
BaseBean
中删除 @ManagedBean
注释。
- 将
loggedInUser
保存到会话。
将 isLoggedIn
保留为 BaseBean
中的受保护方法。您将能够通过那里的 FacesContext
到达会话并从会话中获取 loggedInUser
。
((HttpServletRequest)FacesContext.getCurrentInstance()
.getExternalContext().getRequest()).getSession()
ps:我不知道我在提供静态变量时到底在想什么。
我看你想实现身份验证和身份验证控件,那么你可以使用 JSF 过滤器。您可以将 BaseBean class 保留在会话范围内,创建一个新的 class 实现 javax.servlet.Filter 并在此 class 中让您的 BaseBean class 通过会话,例如:
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 class 创建报告,您可以获取会话的 BaseBean class:
BaseBean base = (BaseBean) ( FacesContext.getCurrentInstance()
.getExternalContext().getRequest()).getSession().getAttribute("baseBean") );
那么在你的情况下我的建议是避免继承并利用 JSF 的优势。
希望这些信息对您有所帮助。
祝你好运。
我阅读了 BalusC 的优秀 tutorial on JSF communication,它帮助我建立了我的应用程序的基础知识。我想与它的所有子 class 共享在 SessionScoped BaseBean class 中设置的当前登录的用户对象。这可以在不为每个需要引用已登录用户的支持 bean 注入 BaseBean 作为 @ManagedProperty
的情况下完成吗?
我的class列在下面。如果需要更多信息,请告诉我,我很乐意更新我的问题。
BaseBean Class
所有其他 bean 都是此 bean 的子class。我这样做是为了允许 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;
}
}
登录Bean Class
登录页面的支持 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.
}
创建报表Class
这是一个来自多个支持 bean 的示例。我想引用当前登录的用户以创建报告,但是如果运行以下代码,用户将为 null
!我可以让它工作的唯一方法是为 BaseBean 添加一个带有 getter 和 setter 的 @ManagedProperty
条目,就像在 LoginBean class 中一样。我真的很想避免这种情况,因为我会将这段代码复制粘贴到我拥有的几乎每个支持 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 不在同一上下文中或 "don't see it?")。下面的代码(来自 BaseBean)会做我想做的,但是任何 bean subclass 都必须调用 base()
,这看起来很尴尬和错误。
protected FacesContext context = FacesContext.getCurrentInstance();
public BaseBean base() {
return (BaseBean) context.getApplication().evaluateExpressionGet(context, "#{baseBean}", BaseBean.class);
}
使 BaseBean
成为托管 bean 本身,并将其用作所有其他托管 bean 的超类是两件不应该进行的事情。
相反,您可以:
- 从
BaseBean
中删除@ManagedBean
注释。 - 将
loggedInUser
保存到会话。 将
isLoggedIn
保留为BaseBean
中的受保护方法。您将能够通过那里的FacesContext
到达会话并从会话中获取loggedInUser
。((HttpServletRequest)FacesContext.getCurrentInstance() .getExternalContext().getRequest()).getSession()
ps:我不知道我在提供静态变量时到底在想什么。
我看你想实现身份验证和身份验证控件,那么你可以使用 JSF 过滤器。您可以将 BaseBean class 保留在会话范围内,创建一个新的 class 实现 javax.servlet.Filter 并在此 class 中让您的 BaseBean class 通过会话,例如:
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 class 创建报告,您可以获取会话的 BaseBean class:
BaseBean base = (BaseBean) ( FacesContext.getCurrentInstance()
.getExternalContext().getRequest()).getSession().getAttribute("baseBean") );
那么在你的情况下我的建议是避免继承并利用 JSF 的优势。
希望这些信息对您有所帮助。
祝你好运。