[英]How to access a @Named bean in PhaseListener?
我们正在使用带有CDI bean的JBoss 7.1,MySQL / PostgreSQL DB,JSF 2.0。
我必须通过登录名和密码来实现基于数据库的身份验证。 我们有一个管理(管理)门户。 当客户端打开未登录的受限页面时,如果客户端未登录,则应将请求重定向到login.*
页面。
我试图通过使用PhaseListener
做到这一点。 我可以登录和注销,但是当我尝试打开其他页面时,我遇到了一个问题:我无法在PhaseListener
类中获取@Named("user") public class UserManager
bean。 我试图通过使用FacesContext
和EL ...来获得它,但这一切都没有帮助我。
UserManager
验证登录名并将登录的用户存储为current
属性。 对于每个请求,我都想在PhaseListener
检查#{user.current}
是否不为null
。 但是我无法在PhaseListener
获得#{user}
bean。
如何在beforePhase()
或afterPhase()
获得@Named
bean?
更新 :这是我到目前为止的尝试:
private boolean loggedIn( FacesContext context ) throws IOException, ServletException
{
LOGSTORE.debug( "loggedIn().2 " );
HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();
// ELContext elContext = FacesContext.getCurrentInstance().getELContext();
// UserManager userManager = (UserManager) FacesContext.getCurrentInstance().getApplication()
// .getELResolver().getValue( elContext, null, "user" );
HttpSession session = (HttpSession) context.getExternalContext().getSession( true );
UserManager userManager = (UserManager) session.getAttribute( "user" );
// UserManager userManager = (UserManager) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get( "user" );
if (!StringUtils.contains( ((HttpServletRequest) context.getExternalContext().getRequest())
.getRequestURL().toString(), URL_SESSION_EXPIRED ))
{
if (userManager == null || !userManager.isLoggedIn())
{
LOGSTORE.debug( " userManager is " + (userManager == null ? "" : "not ") + " null" );
if (userManager != null)
{
LOGSTORE.debug( " userManager.isLoggedIn() is "
+ (userManager.isLoggedIn() ? "TRUE" : "FALSE") );
}
LOGSTORE.debug( " doPhaseFilter() - START REDIRECT " );
response.sendRedirect( request.getContextPath() + "/" + homepage + "?auth-failed" );
}
return false;
} else
{
LOGSTORE.debug( "loggedIn().3 it is " + homepage );
return true;
}
}
会话范围的CDI托管Bean与普通会话范围的JSF托管Bean的存储方式不同。 实际上,由JSF管理的会话范围实际上是通过bean名称作为键存储在会话中的。 但是,会话范围的CDI托管Bean通过会话范围中的另一个映射进一步抽象了。
您需要通过以编程方式评估EL来获取它,而不是从会话映射中获取它。 您的EL解析器尝试有一个错误,该值不包含任何#{}
表达式。
ELContext elContext = FacesContext.getCurrentInstance().getELContext();
UserManager userManager = (UserManager) FacesContext.getCurrentInstance().getApplication()
.getELResolver().getValue(elContext, null, "user");
相应地修复它:
ELContext elContext = FacesContext.getCurrentInstance().getELContext();
UserManager userManager = (UserManager) FacesContext.getCurrentInstance().getApplication()
.getELResolver().getValue(elContext, null, "#{user}");
顺便说一句,上面的缩写是Application#evaluateExpressionGet()
:
UserManager userManager = context.getApplication()
.evaluateExpressionGet(context, "#{user}", UserManager.class);
请注意,您已经有了FacesContext context
作为方法参数。
我使用以下代码从PhaseListener
获取对CDI bean的引用。
public BeanManager getBeanManager() {
BeanManager beanManager = null;
try {
InitialContext initialContext = new InitialContext();
beanManager = (BeanManager) initialContext.lookup("java:comp/BeanManager");
} catch (NamingException e) {
logger.log(Level.SEVERE, "Couldn't get BeanManager through JNDI", e);
}
return beanManager;
}
public <T> T getBean(final Class<T> clazz) {
BeanManager bm = getBeanManager();
Bean<T> bean = (Bean<T>) bm.getBeans(clazz).iterator().next();
CreationalContext<T> ctx = bm.createCreationalContext(bean);
return (T) bm.getReference(bean, clazz, ctx);
}
因此,要获取bean,您可以像下面这样调用它。
DataManager dataManager = getBean(DataManager.class);
在这种情况下,该bean是@Dependent
bean,它在PhaseListener
。
希望在下一版的JSF中对此问题进行修复,该JSF对此具有真正的CDI集成。 您需要做的(并保持可移植性)是通过JNDI查找BeanManager,然后从BeanManager中获取命名的bean。
另一个可能性是使用Seam Faces 。 它是便携式CDI扩展,可让您观察面部事件 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.