访问由Container管理的会话Listern

时间:2011-06-06 06:45:06

标签: http session listener

AFAIK,httpsessionlisterner实现侦听器类在创建第一个会话时被实例化。

因此,我想访问此实例,因为我需要计算多少活动会话并将其显示在哪里,我想检查哪个用户当前正在登录。在下面的代码中,有list实例变量,我需要访问这个监听器类才能访问私有变量。

@WebListener()
public class SessionListener implements HttpSessionListener, HttpSessionAttributeListener {

  private List<HttpSession> sessionList;

  public SessionListener() {
    sessionList = new ArrayList<HttpSession>();
  }

  @Override
  public void sessionCreated(HttpSessionEvent se) {
    sessionList.add(se.getSession());
  }

  @Override
  public void sessionDestroyed(HttpSessionEvent se) {
    sessionList.remove(se.getSession());
  }

  @Override
  public void attributeAdded(HttpSessionBindingEvent event) {
  }

  @Override
  public void attributeRemoved(HttpSessionBindingEvent event) {

  }

  @Override
  public void attributeReplaced(HttpSessionBindingEvent event) {

  }

  /**
   * @return the sessionList
   */
  public List<HttpSession> getSessionList() {
    return Collections.unmodifiableList(sessionList);
  }

请帮忙。

感谢。

1 个答案:

答案 0 :(得分:1)

我必须做一些假设,因为你没有说明你的身份验证方法是如何工作的。

我将假设您的用户名将包含在您的HttpServletRequest中(这很常见)。除非您已将会话专门编码为包含用户名,否则它将不包含经过身份验证的用户的用户名 - 用户名通常仅限于HttpServletRequest。因此,您通常不会通过使用HttpSessionListener来实现目标。你可能知道这一点,但有各种“范围”。

  • 应用程序范围(ServletContext) - 每个应用程序
  • 会话范围(HttpSession) - 每次会话
  • 请求范围(HttpServletRequest) - 按请求

正如我所说,用户名通常存储在请求范围内。您可以从请求范围访问会话和应用程序范围。您无法从会话范围访问请求范围(因为这没有意义!)。

为了解决您的问题,我将创建一个存储在应用程序范围内的Map,并使用ServletFilter来填充它。您可能希望使用基于时间的缓存(使用会话超时值)而不是直接映射,因为大多数会话已启动但超时而不是由用户明确终止。 kitty-cache是一个非常简单的基于时间的缓存,您可以将其用于此目的。

无论如何,代码草图(未经测试)可能如下所示:

public class AuthSessionCounter implements Filter {

    private static final String AUTHSESSIONS = "authsessions";
    private static ServletContext sc;

    public void init(FilterConfig filterConfig) throws ServletException {
        sc = filterConfig.getServletContext();
        HashMap<String, String> authsessions = new HashMap<String, String>();
        sc.setAttribute(AUTHSESSIONS, authsessions);
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest hsr = (HttpServletRequest) request;
        if (hsr.getRemoteUser() != null) {            
            HttpSession session = hsr.getSession();
            HashMap<String, String> authsessions = (HashMap<String, String>) sc.getAttribute(AUTHSESSIONS);
            if (!authsessions.containsKey(session.getId())) {
                authsessions.put(session.getId(), hsr.getRemoteUser());
                sc.setAttribute(AUTHSESSIONS, authsessions);
            }
        }
        chain.doFilter(request, response);
    }

    public void destroy(){}
}

您现在应该能够从应用程序范围中存储的 authsessions 映射中获取登录用户和用户的详细信息。

我希望这有帮助,

标记

<强>更新

  

我的身份验证通过检查来实现   servlet中的用户名和密码   并为它创建一个新会话。

在这种情况下,HttpSessionListener可能适合您 - 尽管如前所述,由于大多数用户会话超时而非终止的方式,您可能仍需要使用基于时间的缓存。我未经测试的代码草图现在看起来像这样:

public class SessionCounter 
    implements HttpSessionListener, HttpSessionAttributeListener {

    private static final String AUTHSESSIONS = "authsessions";
    private static final String USERNAME = "username";
    private static ServletContext sc;

    public void sessionCreated(HttpSessionEvent se) {
        if (sc == null) {
            sc = se.getSession().getServletContext();
            HashMap<String, String> authsessions = new HashMap<String, String>();
            sc.setAttribute(AUTHSESSIONS, authsessions);
        }
    }

    public void sessionDestroyed(HttpSessionEvent se) {
        HttpSession session = se.getSession();
        HashMap<String, String> authsessions = 
             (HashMap<String, String>) sc.getAttribute(AUTHSESSIONS);
        authsessions.remove(session.getId());
        sc.setAttribute(AUTHSESSIONS, authsessions);
    }

    public void attributeAdded(HttpSessionBindingEvent se) {
        if (USERNAME.equals(se.getName())) {
            HttpSession session = se.getSession();
            HashMap<String, String> authsessions = 
                  (HashMap<String, String>) sc.getAttribute(AUTHSESSIONS);
            authsessions.put(session.getId(), (String) se.getValue());
            sc.setAttribute(AUTHSESSIONS, authsessions);
        }
    }

    public void attributeRemoved(HttpSessionBindingEvent se) {}

    public void attributeReplaced(HttpSessionBindingEvent se) {}
}