- 后端: JPQL构造器投影排除LONGTEXT大字段(uploadedImages/videoReferenceImages) - 后端: DTO层过滤非分镜图类型的base64内联resultUrl - 前端: 列表缩略图从video改为img loading=lazy,消除172并发请求 - 前端: download函数增加resultUrl懒加载(详情接口兜底) - 文档: 新增性能优化报告 docs/performance-optimization-report.md
113 lines
3.2 KiB
Java
113 lines
3.2 KiB
Java
package com.example.demo.service;
|
||
|
||
import org.slf4j.Logger;
|
||
import org.slf4j.LoggerFactory;
|
||
import org.springframework.scheduling.annotation.Scheduled;
|
||
import org.springframework.stereotype.Service;
|
||
|
||
import java.time.Duration;
|
||
import java.time.LocalDate;
|
||
import java.time.LocalDateTime;
|
||
import java.util.Map;
|
||
import java.util.Set;
|
||
import java.util.concurrent.ConcurrentHashMap;
|
||
|
||
/**
|
||
* 在线统计服务
|
||
* 通过IP地址统计当天访问的独立用户数
|
||
*/
|
||
@Service
|
||
public class OnlineStatsService {
|
||
|
||
private static final Logger logger = LoggerFactory.getLogger(OnlineStatsService.class);
|
||
|
||
// 存储当天访问过的IP地址(使用Set去重)
|
||
private final Set<String> todayVisitors = ConcurrentHashMap.newKeySet();
|
||
|
||
// 记录当前日期,用于判断是否需要重置
|
||
private volatile LocalDate currentDate = LocalDate.now();
|
||
|
||
// 系统启动时间
|
||
private final LocalDateTime startTime = LocalDateTime.now();
|
||
|
||
/**
|
||
* 记录访问IP
|
||
* @param ip 访问者IP地址
|
||
*/
|
||
public void recordVisit(String ip) {
|
||
if (ip == null || ip.isEmpty()) {
|
||
return;
|
||
}
|
||
|
||
// 检查是否需要重置(新的一天)
|
||
checkAndResetIfNewDay();
|
||
|
||
// 添加IP到今日访客列表
|
||
todayVisitors.add(ip);
|
||
}
|
||
|
||
/**
|
||
* 获取当天在线人数(独立IP数)
|
||
* @return 当天访问的独立IP数量
|
||
*/
|
||
public int getTodayVisitorCount() {
|
||
checkAndResetIfNewDay();
|
||
return todayVisitors.size();
|
||
}
|
||
|
||
/**
|
||
* 检查是否是新的一天,如果是则重置统计
|
||
*/
|
||
private void checkAndResetIfNewDay() {
|
||
LocalDate today = LocalDate.now();
|
||
if (!today.equals(currentDate)) {
|
||
synchronized (this) {
|
||
if (!today.equals(currentDate)) {
|
||
logger.info("新的一天开始,重置在线统计。昨日访客数: {}", todayVisitors.size());
|
||
todayVisitors.clear();
|
||
currentDate = today;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 每天凌晨0点重置统计
|
||
*/
|
||
@Scheduled(cron = "0 0 0 * * ?")
|
||
public void resetDailyStats() {
|
||
logger.info("定时任务:重置每日在线统计。昨日访客数: {}", todayVisitors.size());
|
||
todayVisitors.clear();
|
||
currentDate = LocalDate.now();
|
||
}
|
||
|
||
/**
|
||
* 获取系统运行时间(格式化为 X小时X分)
|
||
* @return 运行时间字符串
|
||
*/
|
||
public String getUptime() {
|
||
Duration duration = Duration.between(startTime, LocalDateTime.now());
|
||
long hours = duration.toHours();
|
||
long minutes = duration.toMinutes() % 60;
|
||
|
||
if (hours > 0) {
|
||
return hours + "小时" + minutes + "分";
|
||
} else {
|
||
return minutes + "分钟";
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取统计信息
|
||
* @return 包含统计数据的Map
|
||
*/
|
||
public Map<String, Object> getStats() {
|
||
checkAndResetIfNewDay();
|
||
Map<String, Object> stats = new ConcurrentHashMap<>();
|
||
stats.put("todayVisitors", todayVisitors.size());
|
||
stats.put("date", currentDate.toString());
|
||
stats.put("uptime", getUptime());
|
||
return stats;
|
||
}
|
||
}
|