【问题标题】:Get SessionBean Instance获取 SessionBean 实例
【发布时间】:2013-04-24 21:53:50
【问题描述】:

我试图在我的页面中保持 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,但即使我实例化它,也没有工作。

有什么问题吗?

【问题讨论】:

标签: java eclipse jsf xhtml jboss5.x


【解决方案1】:

您获得 NPE 是因为 You cannot obtain a FacesContext object 在 JSF 工件的上下文之外(@ManagedBean@FacesConverter@FacesComponentPhaseListener 等),相对于 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);      
     }

JSF 中的SessionScope,就像您已经知道的那样,是HttpSession 的一个外观。因此,您可以轻松访问基本的 HttpSession 并提取所有 @SessionScoped 变量,而不是您正在探索的环形交叉路口 FacesContext 替代方案

【讨论】:

  • 我知道了,但是在其他类中我不使用'ServletRequest'和'ServletResponse'?
  • @MarcosFontana “其他类”在 JavaEE 中是一个模棱两可的说法。不同的上下文(Servlet?Managed Bean?)将需要不同的访问方法来达到相同的结果
  • 好的@kolossus,但是如果我需要在不属于任何JSF工件的类中恢复会话中的对象,例如DAO类,我应该如何进行?因为我见过一些使用 HttpSession 的解决方案,但是我没有 HttpRequest/Response 来使用它。
  • @MarcosFontana,无论它是什么类,它都必须在 Web 应用程序中。如果它在 Web 应用程序中,那么引擎盖下会有一个 HttpServletRequest/Response。它变成了在那里导航的问题。就像我之前所说的,“a class”是一个非常模棱两可的说法。事实是,只要您处于 Web 应用程序的上下文中,您就总能找到进入会话的方式。 DAO 类将在 JEE 构造中使用:EJB、Web 服务等。只要它不在桌面 J2SE 上,它下面总会有一个 HttpRequest
【解决方案2】:

如果会话范围的 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 实例,因此所有实例变量将在所有请求/会话之间共享。换句话说:它不是线程安全的。

【讨论】:

  • 您在这里遗漏了一个关键点:OP 无权访问过滤器中的FacesContext。在此之后,您在此处提出的其他事实将不再相关。我也找不到任何 OP 提到 PhaseListener 的地方。也许您的意思是FacesContext。您在此处的回答中存在一些误解
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-18
  • 1970-01-01
  • 2013-04-20
  • 2012-04-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多