当前位置:首页 > 后端开发 > 正文

如何在Java中查看在线用户?

在 Java Web应用中,查看 在线用户通常通过HttpSessionListener监听会话状态实现,核心步骤:创建自定义监听器跟踪session创建/销毁,使用线程安全集合(如ConcurrentHashMap)存储 在线用户信息,在ServletContext中维护实时用户列表,可通过获取ServletContext中的用户集合实时展示在线状态。

核心实现方案

HttpSessionListener 监听会话状态

通过监听会话创建/销毁事件自动更新在线用户列表。

// 创建监听器 public class OnlineUserListener implements HttpSessionListener { private static final Set<String> onlineUsers = Collections.synchronizedSet(new HashSet<>()); @Override public void sessionCreated(HttpSessionEvent se) { String userId = (String) se.getSession().getAttribute("userId"); if (userId != null) onlineUsers.add(userId); } @Override public void sessionDestroyed(HttpSessionEvent se) { String userId = (String) se.getSession().getAttribute("userId"); onlineUsers.remove(userId); } public static Set<String> getOnlineUsers() { return new HashSet<>(onlineUsers); } }

注册监听器(web.xml):

<listener> <listener-class>com.example.OnlineUserListener</listener-class> </listener>

优点:实时性强,自动管理会话生命周期

缺点:无法捕获用户非正常退出(如直接关闭浏览器)


Filter + 心跳检测(推荐)

通过用户活动时间戳判断活跃状态,避免会话超时误判。

// 心跳过滤器 public class SessionActivityFilter implements Filter { private static final Map<String, Long> userLastActivity = new ConcurrentHashMap<>(); @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; String userId = (String) request.getSession().getAttribute("userId"); if (userId != null) { userLastActivity.put(userId, System.currentTimeMillis()); // 更新活动时间 } chain.doFilter(req, res); } // 获取活跃用户(5分钟内活动) public static Set<String> getActiveUsers() { long now = System.currentTimeMillis(); return userLastActivity.entrySet().stream() .filter(entry -> now - entry.getValue() < 300_000) // 5分钟 .map(Map.Entry::getKey) .collect(Collectors.toSet()); } }

配置过滤路径(web.xml):

如何在Java中查看在线用户? 第1张

<filter> <filter-name>sessionActivityFilter</filter-name> <filter-class>com.example.SessionActivityFilter</filter-class> </filter> <filter-mapping> <filter-name>sessionActivityFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>


结合Redis存储分布式状态

适用于集群环境,解决多服务器间状态同步问题。

// 使用Redis记录活动时间 try (Jedis jedis = jedisPool.getResource()) { String userId = getCurrentUserId(); jedis.setex("user:activity:" + userId, 300, String.valueOf(System.currentTimeMillis())); // 5分钟过期 } // 查询在线用户 Set<String> onlineUsers = jedis.keys("user:activity:*").stream() .map(key -> key.split(":")[2]) .collect(Collectors.toSet());

优势:支持水平扩展,数据持久化

工具建议:Spring Data Redis、Lettuce

如何在Java中查看在线用户? 第2张

如何在Java中查看在线用户? 第3张


在线用户信息增强

可扩展存储更多会话数据:

public class UserSession { private String userId; private String ipAddress; private LocalDateTime loginTime; // 存储到ConcurrentHashMap或Redis } public static Map<String, UserSession> activeSessions = new ConcurrentHashMap<>();


安全性及性能优化

  1. 隐私保护
    • 脱敏处理:仅展示部分用户ID(如 user***123)
    • 权限控制:限制管理员访问 /admin/online-users
  2. 性能提升
    • 缓存查询结果:使用Guava Cache定时刷新 LoadingCache<String, Set<String>> onlineUsersCache = CacheBuilder.newBuilder() .refreshAfterWrite(1, TimeUnit.MINUTES) // 自动刷新 .build(this::loadActiveUsersFromRedis);
  3. 会话可靠性
    • 配置web.xml确保会话超时时间: <session-config> <session-timeout>30</session-timeout> <!-- 30分钟 --> </session-config>


方案选型指南

场景 推荐方案 特点
单机应用 HttpSessionListener 简单易用,零额外依赖
高精度活跃检测 Filter + 时间戳 避免会话超时误差
微服务/集群 Redis存储 分布式支持,高可用
需要详细会话数据 扩展UserSession对象 记录IP、设备等元信息


关键注意事项

  1. 会话固定攻破防护

    用户登录后重置Session ID: request.getSession().invalidate(); HttpSession newSession = request.getSession(true);

  2. 内存泄漏预防

    使用WeakReference存储会话数据,或在sessionDestroyed()中显式清除引用

  3. 跨平台兼容

    对于WebSocket连接,可通过@OnOpen/@OnClose注解管理状态

最佳实践:生产环境建议采用 Filter+Redis 组合方案,平衡实时性、扩展性和资源开销,通过Spring Boot Actuator可集成监控端点,实时查看在线用户数据。


引用说明:本文代码实现参考Oracle官方HttpSessionListener文档,Redis会话管理方案基于Spring Session最佳实践,安全建议依据OWASP会话管理标准。

0