温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片!
1. 项目背景与意义
随着城市生活节奏的加快和消费水平的提升,美食已成为人们日常社交、休闲和出行的重要驱动力。然而,面对海量的餐饮信息,用户往往难以快速找到符合口味、口碑良好且位置合适的餐厅。传统的美食推荐方式多依赖人工编辑或单一平台的评分,存在信息更新滞后、主观性强、覆盖不全等问题。
基于SpringBoot的城市美食排行榜网站,旨在通过系统化的数据采集、评分聚合和榜单展示,为城市居民和游客提供客观、实时、可筛选的美食参考。该网站不仅帮助用户高效决策,也为中小餐饮商户提供了流量曝光和口碑管理的数字化窗口,具有一定的社会价值和经济价值。
2. 系统技术栈
本系统采用前后端分离的架构设计,后端以SpringBoot为核心框架,前端使用Vue.js构建交互界面,数据存储采用MySQL关系型数据库,并辅以Redis缓存热点数据以提升访问性能。
| 层次 | 技术选型 | 说明 |
|---|---|---|
| 后端框架 | SpringBoot 2.7 | 快速构建RESTful API,集成Spring Security与MyBatis-Plus |
| 前端框架 | Vue.js 3 + Element Plus | 组件化开发,支持响应式布局与榜单交互 |
| 数据库 | MySQL 8.0 | 存储用户、餐厅、评分、评论等核心业务数据 |
| 缓存 | Redis | 缓存热门榜单与验证码,降低数据库压力 |
| 构建工具 | Maven | 依赖管理与项目打包 |
| 接口文档 | Swagger / Knife4j | 自动生成在线接口调试文档 |
3. 核心功能模块
系统围绕美食排行榜的核心业务,划分为用户管理、餐厅管理、评分评论、榜单生成和后台管理五个主要模块。
- 用户模块:注册、登录、个人信息维护,支持基于JWT的Token鉴权。
- 餐厅模块:餐厅信息录入、分类标签、地理位置、营业时间、人均消费等基础数据管理。
- 评分评论模块:用户对餐厅进行星级评分和文字评论,系统自动聚合平均分与评价数量。
- 榜单模块:根据评分、销量、浏览量等维度动态生成城市美食排行榜,支持按分类和区域筛选。
- 后台管理模块:管理员对餐厅、用户、评论进行审核与下架操作,保障内容合规。
4. 数据库设计
数据库共设计五张核心数据表,分别为用户表、餐厅表、分类表、评分表和评论表。以下为餐厅表与评分表的关键字段设计。
CREATE TABLE restaurant ( id BIGINT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(100) NOT NULL COMMENT '餐厅名称', category_id BIGINT COMMENT '分类ID', address VARCHAR(255) COMMENT '详细地址', avg_price DECIMAL(10,2) COMMENT '人均消费', avg_score DECIMAL(3,2) DEFAULT 0 COMMENT '平均评分', rating_count INT DEFAULT 0 COMMENT '评分人数', status TINYINT DEFAULT 1 COMMENT '状态:1上架 0下架', create_time DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE rating ( id BIGINT PRIMARY KEY AUTO_INCREMENT, user_id BIGINT NOT NULL, restaurant_id BIGINT NOT NULL, score TINYINT NOT NULL COMMENT '1-5星', create_time DATETIME DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY uk_user_restaurant (user_id, restaurant_id) );5. 核心代码实现
榜单生成是系统的核心逻辑。以下代码演示了如何根据评分和评分人数计算综合得分,并生成排行榜列表。
@Service public class RankService { @Autowired private RestaurantMapper restaurantMapper; /** 生成城市美食排行榜 综合得分 = 平均分 * 0.7 + 评分人数归一化值 * 0.3 */ public List<RestaurantVO> getRankList(String city, Long categoryId) { List<Restaurant> list = restaurantMapper.selectByCityAndCategory(city, categoryId); return list.stream() .map(this::toRankVO) .sorted(Comparator.comparing(RestaurantVO::getCompositeScore).reversed()) .collect(Collectors.toList()); } private RestaurantVO toRankVO(Restaurant r) { double scoreWeight = r.getAvgScore() * 0.7; double countWeight = Math.log10(r.getRatingCount() + 1) * 1.5; double composite = Math.round((scoreWeight + countWeight) * 100) / 100.0; RestaurantVO vo = new RestaurantVO(); vo.setId(r.getId()); vo.setName(r.getName()); vo.setAvgScore(r.getAvgScore()); vo.setRatingCount(r.getRatingCount()); vo.setCompositeScore(composite); return vo; } }用户评分接口采用事务控制,确保评分写入与餐厅平均分更新保持一致性。以下为评分提交的核心代码。
@Transactional public void submitRating(Long userId, Long restaurantId, Integer score) { if (score == null || score < 1 || score > 5) { throw new BusinessException("评分必须在1到5之间"); } Rating rating = new Rating(); rating.setUserId(userId); rating.setRestaurantId(restaurantId); rating.setScore(score); ratingMapper.insertOrUpdate(rating); restaurantMapper.refreshAvgScore(restaurantId); }6. 总结
基于SpringBoot的城市美食排行榜网站,通过合理的技术选型和模块化设计,实现了从数据采集、评分聚合到榜单展示的完整业务闭环。系统在保证功能完整性的同时,兼顾了性能与扩展性,为后续接入更多城市数据和个性化推荐算法预留了空间。