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);
}
请帮忙。
感谢。
答案 0 :(得分:1)
我必须做一些假设,因为你没有说明你的身份验证方法是如何工作的。
我将假设您的用户名将包含在您的HttpServletRequest中(这很常见)。除非您已将会话专门编码为包含用户名,否则它将不包含经过身份验证的用户的用户名 - 用户名通常仅限于HttpServletRequest。因此,您通常不会通过使用HttpSessionListener来实现目标。你可能知道这一点,但有各种“范围”。
正如我所说,用户名通常存储在请求范围内。您可以从请求范围访问会话和应用程序范围。您无法从会话范围访问请求范围(因为这没有意义!)。
为了解决您的问题,我将创建一个存储在应用程序范围内的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) {}
}