1. 项目概述与核心价值
去年夏天,我在一家网红餐厅用餐时遇到件趣事:邻桌客人对着刚上的招牌菜连拍十几张照片,却在社交平台只打了三颗星。服务员紧张地询问原因,客人嘟囔着"照片好看但太咸了"。这个场景让我意识到,当前餐饮评价系统存在两个核心痛点:用户难以精准表达体验,商家无法获取有效改进建议。
这套基于SpringBoot的餐厅菜品评价系统,正是为了解决这个行业痛点而生。不同于传统五星评分,我们构建了多维度反馈体系:
- 基础评分(1-5星)
- 口味标签(咸度/辣度/甜度等)
- 图文评价(支持9图+文字)
- 匿名与追评机制
技术架构采用现在主流的前后端分离模式:
mermaid复制graph TD
A[Vue3前端] -->|HTTP/JSON| B(SpringBoot后端)
B --> C[MySQL主库]
B --> D[Redis缓存]
B --> E[阿里云OSS]
C --> F[MySQL从库]
实际开发中发现:当评价包含图片时,传统同步上传方式会导致页面卡顿。我们最终采用先传文字后异步传图的方案,用户提交体验流畅度提升60%
2. 关键技术实现细节
2.1 评价提交的并发处理
高峰期可能出现秒级上千条评价提交,我们设计了三层防护:
- 前端防抖(300ms间隔)
- 令牌桶限流(Redis实现)
java复制// 基于Redis的限流器示例
public boolean tryAcquire(String key, int max, int timeout) {
RedisScript<Long> script = redisScript();
List<String> keys = Collections.singletonList(key);
Long result = redisTemplate.execute(script, keys, max, timeout);
return result != null && result == 1L;
}
- 数据库队列缓冲(Spring Batch)
实测数据:
- 无防护时MySQL CPU峰值:98%
- 三级防护后峰值:63%
2.2 敏感内容审核流程
为避免违规内容,我们实现了双审核机制:
mermaid复制sequenceDiagram
用户->>+后端: 提交评价
后端->>+阿里云内容安全: 图片鉴黄
后端->>+本地DFA算法: 文本过滤
alt 发现敏感内容
后端->>+审核队列: 转入人工审核
审核队列->>+管理员: 发送通知
else 安全内容
后端->>+数据库: 直接入库
end
关键配置参数:
- 图片审核阈值:0.85(置信度)
- 敏感词库更新频率:每日凌晨3点
- 人工审核响应时效:<30分钟
3. 数据可视化实现
3.1 实时评分计算
采用滑动窗口算法保证数据时效性:
sql复制-- 最近30天加权评分SQL
SELECT
dish_id,
ROUND((SUM(rating * 0.9^DATEDIFF(NOW(), create_time))) /
SUM(0.9^DATEDIFF(NOW(), create_time)), 1) AS dynamic_score
FROM reviews
WHERE create_time > DATE_SUB(NOW(), INTERVAL 30 DAY)
GROUP BY dish_id;
权重衰减曲线:
code复制天数 | 权重
0 | 1.0
7 | 0.48
15 | 0.21
30 | 0.04
3.2 评价词云生成
后端处理流程:
- 使用HanLP分词
- 过滤停用词("的"、"了"等)
- 计算TF-IDF权重
- 生成前端所需的JSON格式
json复制// 输出示例
{
"麻辣": 0.87,
"分量足": 0.65,
"上菜慢": 0.53
}
4. 性能优化实践
4.1 缓存策略设计
采用多级缓存架构:
code复制用户请求 → Nginx缓存 → Redis → 本地Caffeine → DB
缓存击穿解决方案:
java复制@Cacheable(value = "dishes", key = "#id")
public Dish getDishWithLock(Long id) {
synchronized (this) {
// 双重检查
Dish dish = dishMapper.selectById(id);
if (dish == null) {
// 防止缓存穿透
return new Dish().setId(id).setName("已下架");
}
return dish;
}
}
4.2 数据库优化
索引设计原则:
- 评价表:联合索引 (dish_id, status, create_time)
- 用户表:唯一索引 (phone)
- 订单表:分区表(按月份)
慢查询监控结果对比:
code复制优化前:TOP1慢查询 4.7s(全表扫描)
优化后:相同查询 0.02s(索引命中)
5. 部署与监控方案
5.1 容器化部署
Docker Compose配置要点:
yaml复制services:
app:
image: openjdk:11-jre
deploy:
resources:
limits:
cpus: '2'
memory: 2G
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
interval: 30s
timeout: 5s
retries: 3
5.2 ELK日志监控
关键日志字段:
java复制log.info("REVIEW_ADD|{}|{}|{}ms|{}",
dishId, userId,
System.currentTimeMillis()-start,
text.length());
Kibana看板配置:
- 请求成功率
- 平均响应时间
- 热点菜品TOP10
- 差评预警趋势
6. 典型问题排查实录
6.1 图片上传失败
现象:安卓设备上传图片概率性失败
排查过程:
- 抓包发现部分请求未带Content-Type
- 查前端代码发现uni.uploadFile()未显式设置type
- 测试不同机型发现华为EMUI系统存在兼容问题
解决方案:
javascript复制// 修复后的上传代码
uni.uploadFile({
url: '/api/upload',
fileType: 'image',
file: file,
header: {
'Content-Type': 'multipart/form-data'
}
});
6.2 缓存不一致问题
现象:商家后台看到的评分与用户端不一致
根本原因:
- 缓存TTL设置过长(24h)
- 更新评价后未清除相关缓存
最终方案:
java复制@CacheEvict(value = "dish_scores", key = "#dishId")
public void addReview(Long dishId, Review review) {
// 先更新数据库
reviewMapper.insert(review);
// 异步更新统计信息
scoreRecalculateService.asyncUpdate(dishId);
}
7. 项目演进方向
-
智能推荐算法:
- 基于用户口味标签的协同过滤
- 实时推荐(Kafka+Spark Streaming)
-
供应链优化:
- 差评关键词→后厨看板
- 食材消耗预测模型
-
无障碍访问:
- 语音评价输入
- 高对比度UI模式
这套系统在课程设计评审中获得优秀成绩,关键创新点在于将简单的评分交互转化为有价值的数据资产。特别提醒后来者:在实现WebSocket通知时,务必处理好连接中断后的重试机制,我们曾因此丢失过重要差评预警。