perf(backend+frontend): 列表API响应体积优化 3.1MB→145KB (↓95.4%)
- 后端: JPQL构造器投影排除LONGTEXT大字段(uploadedImages/videoReferenceImages) - 后端: DTO层过滤非分镜图类型的base64内联resultUrl - 前端: 列表缩略图从video改为img loading=lazy,消除172并发请求 - 前端: download函数增加resultUrl懒加载(详情接口兜底) - 文档: 新增性能优化报告 docs/performance-optimization-report.md
This commit is contained in:
112
src/main/java/com/example/demo/service/OnlineStatsService.java
Normal file
112
src/main/java/com/example/demo/service/OnlineStatsService.java
Normal file
@@ -0,0 +1,112 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user