1

我试图通过我的页面保持 SessionBean 范围,为此,我从这里遵循了一些教程,实际上,我试图通过 ExternalContext 获取会话,如下面的代码:

public class LoginFilter implements Filter{

ProfileBean pBean = new ProfileBean();
ActiveUserModel activeUserModel;
ExternalContext tmpEC;
Map sMap;      

public void destroy() {}

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

    tmpEC = FacesContext.getCurrentInstance().getExternalContext();
    sMap = tmpEC.getSessionMap();
    activeUserModel = (ActiveUserModel) sMap.get("ActiveUserModel");        

    String username = SecurityAssociation.getPrincipal().getName();              

    if(activeUserModel.getUsername() == null)
    {
        try {
            pBean.consultaProfile(username);            

        } catch (SQLException e) {
            e.printStackTrace();
        } catch (NamingException e) {
            e.printStackTrace();
        } 
    }else{
        }        

    filterChain.doFilter(servletRequest, servletResponse);      
}

public void init(FilterConfig filterConfig) throws ServletException {}

}

在这一行 if(activeUserModel.getUsername() == null),我得到一个 java.lang.NullPointerException 因为我没有实例化 bean,但即使我实例化它,也没有工作。

有什么不对吗?

4

2 回答 2

5

您获得 NPE 是因为您无法FacesContext@ManagedBean在 JSF 工件( 、@FacesConverter@FacesComponent等)的上下文之外获取对象PhaseListener,而不是针对 JSF 请求。结果,sMap将在该行之后评估为 null

不知道为什么你首先选择去寻找会话FacesContext。你可以很容易地做到这一点:

   public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

    //Get a hold of the http request
    HttpServletRequest req = (HttpServletRequest)request; 

    //Access the HttpSession associated with the request
    HttpSession session =  req.getSession(false);  

    //Take what you want from the session
    activeUserModel = (ActiveUserModel) session.getAttribute("ActiveUserModel");         

    String username = SecurityAssociation.getPrincipal().getName();              

       if(activeUserModel.getUsername() == null) {
          try {
           pBean.consultaProfile(username);            

          } catch (SQLException e) {
            e.printStackTrace();
          } catch (NamingException e) {
            e.printStackTrace();
          } 
          }else{
        }        

      filterChain.doFilter(servletRequest, servletResponse);      
     }

SessionScopeJSF 中,就像您已经知道的那样,它是HttpSession. 因此,与您正在探索的环形交叉路口替代方案相比,您可以轻松地进入基础HttpSession并提取所有@SessionScoped变量FacesContext

于 2013-04-30T23:48:15.277 回答
1

如果会话范围的 bean 为空,则仅表示尚未为会话创建它。这可能发生在新会话的第一个请求期间。您必须自己创建它并自己将其放入会话范围内。JSF 只会在会话的剩余部分中重用它。

您获取会话范围 bean 的方式有点笨拙。您正在从 JSF 的底层获取原始 Servlet API。您也可以只使用ExternalContext#getSessionMap()来管理会话属性。

Map<String, Object> sessionMap = externalContext.getSessionMap();
LoginBean loginBean = (LoginBean) sessionMap.get("loginBean");
if (loginBean == null) {
    loginBean = new LoginBean();
    sessionMap.put("loginBean", loginBean);
}
// ...

请注意,您不应将 bean 声明为 PhaseListener 的实例变量。即在应用程序的整个生命周期中只有一个 PhaseListener 实例,因此所有实例变量将在所有请求/会话之间共享。换句话说:它不是线程安全的。

于 2013-04-30T21:37:46.290 回答