一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

System.currentTimeMillis实现会话超时判断实战指南

时间:2026-06-24 08:40:46 编辑:袖梨 来源:一聚教程网

会话超时判断需基于准确记录的时间戳而非简单相减,应记录会话起始或最后访问时间,实时比对当前时间与阈值,并支持滑动超时及线程安全更新,同时规避时钟不同步、int溢出等陷阱。

会话超时判断不能只靠 System.currentTimeMillis() 简单相减,关键在于合理记录和比较时间戳,同时兼顾业务逻辑与系统稳定性。

明确会话起始时间点

每次用户成功登录或创建会话时,必须立即记录当前毫秒时间戳作为会话开始时间:

  • 推荐存在内存缓存(如 ConcurrentHashMap<String, Long>)或分布式存储(如 Redis)中,键为会话 ID,值为 System.currentTimeMillis()
  • 避免在每次请求时重新生成时间戳,否则无法准确衡量真实会话时长
  • 若使用 Servlet 容器的 HttpSession,可通过 session.getCreationTime() 获取初始时间,它底层也基于 currentTimeMillis()

动态计算剩余有效期

每次用户发起操作(如接口调用、页面刷新),需实时校验是否超时:

  • 获取当前时间:long now = System.currentTimeMillis();
  • 读取该会话的创建时间(或最后活跃时间)long startTime
  • 计算已过期时长:long elapsed = now - startTime;
  • 与预设超时阈值(如 30 分钟 = 30 * 60 * 1000L)比较,elapsed > timeoutMs 即判定超时

支持“滑动超时”机制

多数场景需要用户持续操作则延长会话,而非固定截止时间:

  • 每次合法请求后,更新该会话的“最后访问时间”为当前 System.currentTimeMillis()
  • 超时判断改用:now - lastAccessTime > timeoutMs
  • 注意:更新操作应保证线程安全,尤其在高并发下,建议使用原子操作或加锁
  • 示例:用户每 2 分钟点一次按钮,30 分钟超时策略下,只要间隔 ≤30 分钟,会话就一直有效

规避常见陷阱

System.currentTimeMillis() 本身可靠,但误用会导致逻辑错误:

  • 不要跨 JVM 或跨服务直接比对时间戳——各机器系统时钟可能不同步,需用 NTP 校准或改用分布式唯一时间源(如 Snowflake ID 中的时间部分)
  • 避免在循环中高频调用 currentTimeMillis()——虽开销极小,但无意义重复调用影响可读性
  • 不要把时间戳存成 int 类型——32 位整数会在 2038 年溢出,务必使用 long
  • 日志中打印时间建议格式化(如 new Date(ts).toString()),方便排查问题

不复杂但容易忽略细节,核心就是“一次记录、多次比对、适时更新”。

热门栏目