上一篇                     
               
			  如何在Java中查看在线用户?
- 后端开发
- 2025-06-01
- 2933
 在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):
<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

在线用户信息增强
可扩展存储更多会话数据:
public class UserSession {
    private String userId;
    private String ipAddress;
    private LocalDateTime loginTime;
    // 存储到ConcurrentHashMap或Redis
}
public static Map<String, UserSession> activeSessions = new ConcurrentHashMap<>(); 
安全性及性能优化
- 隐私保护 
  - 脱敏处理:仅展示部分用户ID(如 user***123)
- 权限控制:限制管理员访问 /admin/online-users
 
- 脱敏处理:仅展示部分用户ID(如 
- 性能提升 
  - 缓存查询结果:使用Guava Cache定时刷新 LoadingCache<String, Set<String>> onlineUsersCache = CacheBuilder.newBuilder() .refreshAfterWrite(1, TimeUnit.MINUTES) // 自动刷新 .build(this::loadActiveUsersFromRedis); 
 
- 缓存查询结果:使用Guava Cache定时刷新 
- 会话可靠性 
  - 配置web.xml确保会话超时时间: <session-config> <session-timeout>30</session-timeout> <!-- 30分钟 --> </session-config> 
 
- 配置web.xml确保会话超时时间: 
方案选型指南
| 场景 | 推荐方案 | 特点 | 
|---|---|---|
| 单机应用 | HttpSessionListener | 简单易用,零额外依赖 | 
| 高精度活跃检测 | Filter + 时间戳 | 避免会话超时误差 | 
| 微服务/集群 | Redis存储 | 分布式支持,高可用 | 
| 需要详细会话数据 | 扩展UserSession对象 | 记录IP、设备等元信息 | 
关键注意事项
- 会话固定攻击防护
 用户登录后重置Session ID:request.getSession().invalidate(); HttpSession newSession = request.getSession(true); 
- 内存泄漏预防
 使用WeakReference存储会话数据,或在sessionDestroyed()中显式清除引用
- 跨平台兼容
 对于WebSocket连接,可通过@OnOpen/@OnClose注解管理状态
最佳实践:生产环境建议采用 Filter+Redis 组合方案,平衡实时性、扩展性和资源开销,通过Spring Boot Actuator可集成监控端点,实时查看在线用户数据。
引用说明:本文代码实现参考Oracle官方HttpSessionListener文档,Redis会话管理方案基于Spring Session最佳实践,安全建议依据OWASP会话管理标准。
 
 
 
			