1. 项目概述与核心价值
校园外卖服务系统是一个典型的O2O(Online to Offline)应用场景,它解决了高校师生在校园内就餐的最后一公里问题。这个基于SpringBoot+Vue+MySQL的技术栈实现的外卖平台,相比市面上通用的外卖APP具有几个独特优势:
- 校园场景定制化:专门针对高校环境设计,支持校内食堂档口入驻,菜品定价更符合学生消费水平
- 配送效率优化:利用校内学生兼职配送,缩短配送半径,平均送达时间可控制在20分钟内
- 安全管控严格:所有商户均为学校认证的实体餐饮单位,食品安全更有保障
技术选型方面,SpringBoot+Vue的前后端分离架构提供了良好的开发体验和性能表现。SpringBoot的约定优于配置原则让后端开发更高效,Vue的组件化开发则非常适合构建复杂的前端交互界面。MySQL作为关系型数据库,在事务处理和数据结构规范性方面表现出色,完全满足订单、支付等核心业务的数据存储需求。
提示:校园场景的外卖系统需要特别注意并发处理能力,因为用餐高峰时段(如中午11:30-12:30)的订单量会是平时的5-10倍
2. 系统架构设计
2.1 技术栈详解
后端技术栈:
- SpringBoot 2.7.x:提供RESTful API接口
- Spring Security:负责认证授权
- MyBatis-Plus:数据库ORM框架
- Redis:缓存热点数据和分布式锁
- RabbitMQ:处理异步任务(如订单超时取消)
前端技术栈:
- Vue 3.x:前端主框架
- Element Plus:UI组件库
- Axios:HTTP请求库
- Vue Router:路由管理
- Pinia:状态管理
数据库设计:
sql复制-- 主要表结构示例
CREATE TABLE `user` (
`id` bigint NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL COMMENT '登录账号',
`password` varchar(100) NOT NULL COMMENT '加密后的密码',
`role` tinyint NOT NULL COMMENT '1-学生 2-商家 3-配送员 4-管理员',
`phone` varchar(20) DEFAULT NULL COMMENT '手机号',
`balance` decimal(10,2) DEFAULT '0.00' COMMENT '账户余额',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
2.2 系统模块划分
-
用户模块:
- 多角色统一登录(学生/商家/骑手)
- JWT token认证
- 余额充值与消费记录
-
商家模块:
- 菜品管理(分类、规格、库存)
- 订单处理与数据统计
- 店铺评分系统
-
订单模块:
- 购物车设计(支持多店铺合并结算)
- 订单状态机设计(待支付→待接单→制作中→配送中→已完成)
- 超时自动取消机制
-
配送模块:
- 骑手接单算法(基于位置和负载均衡)
- 实时位置追踪
- 配送路径优化
3. 核心功能实现细节
3.1 高并发订单处理
校园外卖系统的最大技术挑战在于应对用餐高峰期的并发请求。我们采用多级缓存策略:
- Redis缓存:
- 热点菜品信息缓存(TTL 5分钟)
- 库存预扣减(使用Redis的DECR命令)
- 分布式锁防止超卖(Redisson实现)
java复制// 订单创建伪代码
public Result createOrder(OrderDTO orderDTO) {
// 1. 校验库存
String lockKey = "product_" + orderDTO.getProductId();
RLock lock = redissonClient.getLock(lockKey);
try {
boolean locked = lock.tryLock(5, 10, TimeUnit.SECONDS);
if (locked) {
// 2. 扣减库存
int remain = redisTemplate.opsForValue().decrement(
"stock:" + orderDTO.getProductId(),
orderDTO.getQuantity());
if (remain < 0) {
// 库存不足回滚
redisTemplate.opsForValue().increment(
"stock:" + orderDTO.getProductId(),
orderDTO.getQuantity());
return Result.error("库存不足");
}
// 3. 创建订单
Order order = convertToOrder(orderDTO);
orderMapper.insert(order);
// 4. 发送MQ消息
rabbitTemplate.convertAndSend(
"order.delay.exchange",
"order.create",
order.getId());
return Result.success(order.getId());
}
} finally {
lock.unlock();
}
}
3.2 实时通信方案
骑手端与用户端的实时位置共享采用WebSocket协议实现:
javascript复制// 前端WebSocket实现
const socket = new WebSocket('wss://yourdomain.com/ws');
socket.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type === 'LOCATION_UPDATE') {
// 更新骑手位置到地图
updateRiderMarker(data.lat, data.lng);
}
};
// 发送心跳包保持连接
setInterval(() => {
if (socket.readyState === WebSocket.OPEN) {
socket.send(JSON.stringify({type: 'PING'}));
}
}, 30000);
后端使用Spring的WebSocket支持:
java复制@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(orderTrackingHandler(), "/ws")
.setAllowedOrigins("*");
}
@Bean
public WebSocketHandler orderTrackingHandler() {
return new OrderTrackingHandler();
}
}
4. 部署方案与性能优化
4.1 生产环境部署
推荐使用Docker Compose进行服务编排:
yaml复制version: '3.8'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
MYSQL_DATABASE: campus_delivery
volumes:
- mysql_data:/var/lib/mysql
ports:
- "3306:3306"
redis:
image: redis:6.2
ports:
- "6379:6379"
volumes:
- redis_data:/data
backend:
build: ./backend
ports:
- "8080:8080"
depends_on:
- mysql
- redis
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/campus_delivery
SPRING_REDIS_HOST: redis
frontend:
build: ./frontend
ports:
- "80:80"
depends_on:
- backend
volumes:
mysql_data:
redis_data:
4.2 性能优化要点
-
数据库层面:
- 为订单表按月份分表(order_202301, order_202302)
- 建立复合索引:
idx_user_status(user_id, status)加速订单查询 - 使用读写分离(一主多从)
-
JVM调优:
bash复制# SpringBoot启动参数 JAVA_OPTS="-Xms512m -Xmx1024m -XX:+UseG1GC -XX:MaxGCPauseMillis=200" -
前端优化:
- 路由懒加载
- 图片使用WebP格式
- 启用HTTP/2和Brotli压缩
5. 毕业设计扩展建议
如果想在基础版本上进一步提升项目质量,可以考虑以下扩展方向:
-
智能推荐系统:
- 基于用户历史订单的协同过滤推荐
- 实时热门榜单(使用Redis的ZSET实现)
-
配送路径优化算法:
python复制# 简单的贪心算法示例 def optimize_delivery_path(current_location, orders): unvisited = orders.copy() path = [] while unvisited: nearest = min(unvisited, key=lambda o: distance(current_location, o['location'])) path.append(nearest) current_location = nearest['location'] unvisited.remove(nearest) return path -
数据分析看板:
- 使用ECharts可视化销售数据
- 定时任务生成经营报表(Spring Scheduler)
-
压力测试方案:
- 使用JMeter模拟高峰时段流量
- 关键指标:TPS应≥200,平均响应时间<500ms
注意:在论文撰写时,建议采用"问题驱动"的结构,先分析校园餐饮现状和痛点,再对应介绍系统如何解决这些问题,最后通过实测数据验证方案有效性
