如何从Filter中获取SessionScoped CDI bean?

时间:2011-10-19 00:30:49

标签: jsf-2 servlet-filters cdi

此问题与writing a session timeout handler上的前一个问题有关。

该线程的答案涉及从servlet访问各种会话范围的托管bean。建议(如here所示)是在过滤器中执行此操作:

HttpSession session = request.getSession(false);
User user = (session != null) ? (User) session.getAttribute("user") : null;

据推测,这会获取类用户的会话bean。问题是这不起作用。

出现问题的是bean在会话属性中存在,但它们由Weld工具包装。我写了 doFilter()方法,如下所示:

public void doFilter(ServletRequest request, ServletResponse response,
        FilterChain chain)
        throws IOException, ServletException {
    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse res = (HttpServletResponse) response;

    String sp = req.getServletPath();
    System.out.println("------------------------");
    System.out.println("doFilter(): " + sp);

    if (!sp.startsWith("/javax")) {  // eliminates many requests
        HttpSession session = req.getSession();
        Enumeration<String> en = session.getAttributeNames();
        int count = 0;            
        while (en.hasMoreElements()) {
            String e = en.nextElement();
            System.out.println("Attribute " + ++count + ": " + e);
        }
    }
    chain.doFilter(request, response);
}

当这会转储会话属性时,我通常会得到这样的结果:

INFO: ------------------------
INFO: doFilter(): /Display.xhtml
INFO: Attribute 1: org.jboss.weld.context.http.HttpSessionContext#org.jboss.weld.bean-WEB-INF/lib/myfaces-extcdi-bundle-jsf20-1.0.1-ManagedBean-class org.apache.myfaces.extensions.cdi.jsf.impl.scope.conversation.EditableWindowContextManagerProxy
INFO: Attribute 2: org.jboss.weld.context.http.HttpSessionContext#org.jboss.weld.bean-MyApp5-ManagedBean-class com.app.Login
INFO: Attribute 3: org.jboss.weld.context.conversation.ConversationIdGenerator
INFO: Attribute 4: com.sun.faces.renderkit.ServerSideStateHelper.LogicalViewMap
INFO: Attribute 5: org.jboss.weld.context.ConversationContext.conversations
INFO: Attribute 6: facelets.ui.DebugOutput
INFO: Attribute 7: javax.faces.request.charset
INFO: Attribute 8: org.apache.myfaces.extensions.cdi.core.api.scope.conversation.WindowContext:EXISTING_WINDOW_ID_LIST

属性#2似乎代表了我想要的bean。不用说,对 session.getAttribute(“login”)的调用不起作用。

有人可以说如何访问底层托管bean吗?我宁愿以一种与Weld无关的方式来做,但这可能是不可能的。

2 个答案:

答案 0 :(得分:16)

此方法仅适用于会话范围的JSF @ManagedBean,不适用于CDI @Named bean。

您需要将@Inject作为过滤器的属性。

@Inject
private User user;

答案 1 :(得分:5)

import org.jboss.weld.context.SerializableContextualInstanceImpl;

    HttpSession httpSession = (HttpSession) facesContext.getExternalContext().getSession(false);
    Enumeration<String> attribs = httpSession.getAttributeNames();
    String attrib = null;
    while (attribs.hasMoreElements()) {         
        attrib = attribs.nextElement();
        Object obj = httpSession.getAttribute(attrib);
        if(obj instanceof SerializableContextualInstanceImpl){
            SerializableContextualInstanceImpl impl = (SerializableContextualInstanceImpl)obj;
            //here: MyObject myObj= (MyObject)impl.getInstance();
        }           
    }