1. 项目背景与核心需求
校园外卖平台系统是针对高校场景设计的餐饮服务解决方案。随着高校规模扩大和学生生活节奏加快,传统食堂就餐模式已难以满足多样化需求。尤其在课间休息、考试周或恶劣天气时,学生更倾向选择便捷的外卖服务。但主流商业外卖平台存在配送费高、响应慢等问题,无法很好适应校园封闭环境。
本系统基于SpringBoot框架开发,旨在构建一个专属于校园的外卖服务平台,具有以下核心特点:
- 本地化运营:仅服务校内师生,配送距离短、响应快
- 成本优化:配送可由勤工俭学学生担任,降低运营成本
- 安全可控:商家经过学校审核,食品来源可追溯
- 功能定制:针对校园场景优化订单流程和支付方式
2. 技术架构设计
2.1 整体架构
系统采用前后端分离架构:
code复制前端:Vue3 + Ant Design Vue
后端:SpringBoot 3.x + MyBatis + MySQL 8.0
通信:RESTful API + JWT认证
部署:Nginx + Tomcat
2.2 技术选型考量
SpringBoot优势:
- 自动配置:减少XML配置,快速搭建项目
- 内嵌容器:可直接打包为可执行JAR
- 丰富的Starter:轻松集成MyBatis、Redis等组件
- 健康检查:内置Actuator监控端点
MySQL选型原因:
- 高校场景数据规模适中(预计日订单<1万)
- 事务支持完善,适合订单业务
- 与SpringBoot生态集成良好
3. 核心模块实现
3.1 用户认证模块
采用JWT+BCrypt方案:
java复制// 密码加密存储
public void register(User user) {
user.setPassword(BCrypt.hashpw(user.getPassword(), BCrypt.gensalt()));
userMapper.insert(user);
}
// JWT生成
public String generateToken(String userId, String role) {
return Jwts.builder()
.setSubject(userId)
.claim("role", role)
.setExpiration(new Date(System.currentTimeMillis() + 2 * 60 * 60 * 1000)) // 2小时过期
.signWith(SignatureAlgorithm.HS512, secretKey)
.compact();
}
3.2 订单状态机设计
订单状态流转是关键业务逻辑:
code复制待支付 → 待接单 → 已接单 → 制作中 → 待取餐 → 配送中 → 已完成
↘ 已取消
使用状态模式实现:
java复制public interface OrderState {
void handle(OrderContext context);
}
@Component
@Scope("prototype")
public class PaidState implements OrderState {
@Override
public void handle(OrderContext context) {
// 通知商家接单
notifyMerchant(context.getOrder());
context.setState(new AcceptedState());
}
}
3.3 库存扣减方案
采用乐观锁防止超卖:
sql复制UPDATE dish SET stock = stock - #{quantity}
WHERE id = #{dishId} AND stock >= #{quantity}
在Service层校验更新结果:
java复制int affectedRows = dishMapper.reduceStock(dishId, quantity);
if (affectedRows == 0) {
throw new BusinessException("库存不足");
}
4. 关键问题解决方案
4.1 高并发下单处理
采用分级处理策略:
- 前端:提交按钮防重复点击
- 网关:限流(如每秒500请求)
- 服务层:分布式锁(Redis实现)
- 数据库:库存乐观锁+队列削峰
4.2 分布式事务问题
订单创建涉及多个操作:
- 创建订单记录
- 扣减库存
- 写入订单项
使用本地消息表方案:
java复制@Transactional
public void createOrder(OrderDTO orderDTO) {
// 1. 创建订单
orderMapper.insert(order);
// 2. 扣减库存(本地事务)
for (OrderItem item : order.getItems()) {
dishMapper.reduceStock(item.getDishId(), item.getQuantity());
}
// 3. 发送MQ消息(补偿机制)
sendCreateOrderMessage(order);
}
5. 性能优化实践
5.1 缓存策略
采用多级缓存:
- 本地缓存(Caffeine):存储静态数据如菜品分类
- Redis缓存:
- 热点餐厅信息(TTL 5分钟)
- 菜品详情(TTL 10分钟)
- 使用Hash结构存储对象
5.2 SQL优化示例
典型慢查询优化:
sql复制-- 优化前
SELECT * FROM order WHERE user_id = ? AND status IN (1,2,3) ORDER BY create_time DESC;
-- 优化后
SELECT * FROM order
WHERE user_id = ?
AND status IN (1,2,3)
ORDER BY create_time DESC
LIMIT 20;
建立复合索引:
sql复制ALTER TABLE order ADD INDEX idx_user_status_time (user_id, status, create_time);
6. 安全防护措施
6.1 常见漏洞防护
- XSS防护:
java复制@Bean
public FilterRegistrationBean<XssFilter> xssFilter() {
FilterRegistrationBean<XssFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(new XssFilter());
registration.addUrlPatterns("/*");
return registration;
}
- SQL注入防护:
- 使用MyBatis预编译
- 禁止拼接SQL
- 定期SQL审计
6.2 敏感数据保护
- 密码加密:BCrypt
- 手机号脱敏:138****1234
- 日志过滤:
java复制@Bean
public FilterRegistrationBean<LogFilter> logFilter() {
FilterRegistrationBean<LogFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(new LogFilter());
registration.addUrlPatterns("/*");
return registration;
}
7. 部署方案
7.1 容器化部署
Docker Compose配置示例:
yaml复制version: '3'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root
volumes:
- ./mysql/data:/var/lib/mysql
backend:
build: ./backend
ports:
- "8080:8080"
depends_on:
- mysql
frontend:
build: ./frontend
ports:
- "80:80"
7.2 监控方案
- SpringBoot Actuator:健康检查
- Prometheus + Grafana:指标监控
- ELK:日志收集
8. 典型问题排查
8.1 订单状态不同步
排查步骤:
- 检查MQ消费日志
- 验证分布式锁有效性
- 检查定时补偿任务
- 审计数据库事务日志
8.2 性能瓶颈定位
- 使用Arthas分析:
bash复制# 监控方法调用
watch com.example.service.OrderService createOrder '{params,returnObj}' -x 2
- SkyWalking追踪慢请求
- JVM内存分析:MAT工具
9. 扩展方向
- 小程序端:开发微信小程序版本
- 智能调度:基于LBS优化配送路径
- 推荐系统:基于历史订单的菜品推荐
- 语音交互:集成语音点餐功能
我在实际开发中发现,校园外卖系统与商业平台的最大区别在于:
- 配送半径小(通常<2公里),可优化配送算法
- 用户群体固定,便于建立信用体系
- 可深度集成校园卡支付等特色功能
建议在初期版本聚焦核心流程,后续逐步扩展增值功能。数据库设计时要预留扩展字段,接口版本控制从第一天就要考虑。
