[英]Many @RequestScoped subclasses access variable from @SessionScoped bean without copy-pasting @ManagedProperty?
我閱讀了BalusC 關於JSF通信的出色教程 ,它幫助我建立了應用程序的基礎。 我想與所有子類共享在SessionScoped BaseBean類中設置的當前登錄的User對象。 是否可以為每個需要引用登錄用戶的單個后備bean不注入BaseBean作為@ManagedProperty
來完成此操作?
我的課程在下面列出。 請讓我知道是否需要更多信息,我很樂意更新我的問題。
所有其他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;
}
}
登錄頁面的后備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.
}
這是很多人支持的一個例子。 我想引用當前登錄的用戶以創建報告,但是,如果運行以下代碼,則User為null
! 我可以使它正常工作的唯一方法是添加一個@ManagedProperty
條目,該條目具有BaseBean的getter和setters,就像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";
}
}
我發現的一個解決方案是直接從FacesContext獲取BaseBean的實例(我想其他豆不在同一上下文中或“看不到?”)。 以下代碼(來自BaseBean)可以滿足我的要求,但是任何bean子類都必須調用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類保留在會話范圍內,創建一個實現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類創建報告,則可以獲取Session的BaseBean類:
BaseBean base = (BaseBean) ( FacesContext.getCurrentInstance()
.getExternalContext().getRequest()).getSession().getAttribute("baseBean") );
然后,在您的情況下,我的建議是避免繼承,並使用JSF的優點。
希望這些信息對您有所幫助。
祝好運。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.