使用system.currenttimemillis()记录用户最后操作时间需明确记录时机、存储位置及时区处理:仅在真实活跃操作(如点击、提交)或校验后的心跳请求中更新,避免非主动行为;存储可选session(单机)、数据库(强一致)或redis(高性能);比较用毫秒差,展示时再格式化时区;并发更新需原子操作或条件更新防覆盖。

用 System.currentTimeMillis() 记录用户最后操作时间是常见做法,但要注意它只是毫秒级时间戳,不自带业务语义,需结合具体场景合理使用。
记录时机要明确
不能只在登录时记一次,也不能每次HTTP请求都盲目更新。重点覆盖真实体现“活跃”的操作:
- 用户点击按钮、提交表单、切换页面等前端交互后,由后端接收并更新时间戳
- 心跳类请求(如每30秒ping一次)可更新,但需防刷——建议加简单校验(如前后两次间隔≥10秒)
- 避免在日志打印、缓存读取、静态资源访问等非用户主动行为中更新
存储位置要匹配场景
时间戳存在哪,取决于你的可用性和一致性要求:
- Session中:适合单机或粘性负载均衡,简单直接,但集群环境下需共享Session(如Redis)
- 数据库用户表字段(如
last_active_time):强一致性首选,但高频更新要考虑DB压力 - Redis哈希结构(如
user:123:status→{last_active: 1717023456789}):高性能、易过期,适合实时在线状态判断
使用时别忽略时区与精度问题
System.currentTimeMillis() 返回的是自1970-01-01 UTC以来的毫秒数,本身与时区无关,但显示或比对时容易出错:
- 做“超时判断”(如30分钟无操作视为离线),直接用 long 相减即可:
if (now - lastActive > 30 * 60 * 1000) - 展示给用户时,再按本地时区格式化,不要在存储层转时区
- 避免和
new Date()或LocalDateTime.now()混用比较——后者可能受系统默认时区影响
注意并发更新安全
多个请求可能同时写最后操作时间,一般不需要强一致,但得防止异常覆盖:
- 用原子操作:Redis 的
SET user:123:last_active 1717023456789天然幂等 - DB更新建议带条件:
UPDATE user SET last_active_time = ? WHERE id = ? AND last_active_time (避免旧请求覆盖新值) - 如果用内存Map暂存(测试或轻量场景),确保用
ConcurrentHashMap或加锁











