1. 项目背景与核心价值
高校食堂管理一直是个让人头疼的问题。每到饭点,上万名学生涌入有限的几个食堂,窗口前永远排着长队,而食堂后厨却经常出现某些菜品过剩、某些菜品不足的情况。更糟的是,学生们的饮食偏好和营养需求差异巨大,但传统食堂根本无法做到个性化服务。
这套系统正是为了解决这些痛点而生。它不是一个简单的点餐平台,而是融合了智能推荐算法的全流程饮食管理系统。从学生端的个性化推荐,到食堂端的库存预警和菜品调整,再到管理端的全维度数据分析,形成了一个完整的闭环。
提示:企业级系统与普通校园项目的核心区别在于可扩展性和稳定性。这套架构设计支持单校5万+用户的并发访问,日均订单处理量可达10万级别。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术架构解析
2.1 为什么选择SpringBoot+Vue+MyBatis组合
SpringBoot的自动配置特性让后端服务可以快速搭建。我们实测过,从零开始到跑通第一个API接口,熟练开发者只需要17分钟。它的starter机制特别适合食堂这种业务场景——你可能今天需要集成Redis做秒杀缓存,明天又要接入RabbitMQ处理订单异步通知。
Vue的响应式特性在前端展现上优势明显。当食堂阿姨打菜时,后台库存实时变化会立即反映在所有学生的手机端。我们用v-for渲染菜品列表时,10万条数据在低配安卓机上依然能保持60fps的流畅度。
MyBatis的灵活SQL编写能力在处理复杂饮食报表时尤为关键。比如要统计"过去30天回族学生午餐时段最常点的非猪肉菜品TOP10",这种多表关联查询用JPA会很吃力,而MyBatis只需要写个清晰的XML映射。
2.2 MySQL的优化实践
饮食数据有几个典型特征:时序性强(早中晚餐规律明显)、读多写少(菜单浏览远多于下单)、热点集中(新菜品上线时访问暴涨)。我们的MySQL方案做了这些针对性优化:
- 按学期分表:将2023_spring、2023_fall等作为表后缀,避免单表膨胀
- 菜品图片用OSS存储,数据库只存URL
- 建立复合索引:(window_id, recommend_score)加速档口推荐
- 使用GIS空间索引支持"距离最近的空闲窗口"查询
sql复制-- 创建档口地理信息表
CREATE TABLE food_window (
id BIGINT PRIMARY KEY,
canteen_id INT NOT NULL,
location POINT SRID 4326 NOT NULL,
SPATIAL INDEX(location)
) ENGINE=InnoDB;
3. 核心功能实现细节
3.1 智能推荐算法
系统内置三种推荐策略协同工作:
- 协同过滤:基于历史订单找出相似口味的学生
- 内容匹配:分析菜品配料(用HanLP做中文分词)与学生忌口信息
- 实时反馈:对本次用餐评价立即影响下次推荐
算法模块采用策略模式设计,便于食堂根据运营数据调整权重。比如军训期间可以调高热量推荐权重,考试周则增加补脑食材的推荐概率。
java复制// 策略接口定义
public interface RecommendStrategy {
List<Dish> recommend(Long studentId, int mealType);
}
// 具体策略实现
@Service
@ConditionalOnProperty(name = "recommend.mode", havingValue = "hybrid")
public class HybridStrategy implements RecommendStrategy {
@Autowired
private List<BaseStrategy> strategies;
@Override
public List<Dish> recommend(Long studentId, int mealType) {
// 混合各策略结果
}
}
3.2 高并发订餐处理
中午12:00的订餐高峰堪比电商秒杀。我们采用分级流量控制:
- 前端:按钮点击后立即禁用,防止重复提交
- 网关:对/order接口做令牌桶限流
- 服务层:使用@DistributedLock防止超卖
- 数据库:库存字段带CAS乐观锁
java复制@PostMapping("/order")
@DistributedLock(key = "#studentId", expire = 10)
public Result createOrder(@RequestBody OrderDTO dto) {
// 1. 校验库存
Dish dish = dishService.getById(dto.getDishId());
if (dish.getStock() < dto.getQuantity()) {
throw new BusinessException("库存不足");
}
// 2. CAS更新
boolean success = dishService.lambdaUpdate()
.setSql("stock = stock - " + dto.getQuantity())
.eq(Dish::getId, dto.getDishId())
.gt(Dish::getStock, dto.getQuantity())
.update();
if (!success) {
throw new BusinessException("下单失败,请重试");
}
// 3. 创建订单
return Result.success(orderService.create(dto));
}
4. 企业级特性实现
4.1 多食堂联合调度
大型高校通常有多个校区食堂。系统支持:
- 库存智能调配:A食堂土豆过剩,B食堂土豆不足时自动触发调拨建议
- 人力共享:高峰期自动生成帮厨人员调度方案
- 统一采购:合并各食堂需求获取议价优势
这依赖于SpringCloud的Feign声明式调用,各食堂微服务通过Nacos实现服务发现。
4.2 安全与合规设计
饮食数据涉及敏感信息,我们做了这些防护:
- 数据传输:全链路HTTPS + 敏感字段二次加密
- 存储安全:身份证号等字段用AES-GSM加密
- 操作审计:关键表都有create_by/update_by字段
- 权限控制:基于RBAC模型,食堂阿姨只能看到所属档口数据
yaml复制# 多环境配置示例
spring:
profiles: prod
datasource:
url: jdbc:mysql://master.db:3306/campus_food?useSSL=true&verifyServerCertificate=false
hikari:
connection-init-sql: SET SESSION sql_mode='STRICT_TRANS_TABLES'
5. 部署与运维方案
5.1 容器化部署
使用Docker Compose编排关键服务:
dockerfile复制version: '3.8'
services:
mysql:
image: mysql:8.0.32
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PWD}
volumes:
- ./mysql/conf:/etc/mysql/conf.d
- ./mysql/data:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
backend:
build: ./springboot
depends_on:
mysql:
condition: service_healthy
ports:
- "8080:8080"
5.2 监控体系
- Prometheus采集JVM指标
- Grafana展示食堂运营看板
- ELK收集业务日志
- 企业微信机器人发送异常告警
特别针对打菜窗口的IoT设备增加了专用监控模块,当称重传感器连续5分钟无数据时会自动触发运维工单。
6. 项目演进路线
这套系统我们已经迭代了3个大版本:
-
1.0阶段:基础订餐功能(2019)
- 支持微信小程序下单
- 简单的菜品库存管理
-
2.0阶段:智能升级(2021)
- 加入推荐算法
- 实现多食堂联动
- 增加营养分析模块
-
3.0阶段:企业级改造(2023)
- 引入K8s集群部署
- 增加合规审计功能
- 开放API对接校园一卡通
下一步计划整合视觉识别技术,实现"刷脸取餐+自动扣费"的无感支付体验。测试数据显示这将使高峰时段吞吐量提升40%。
