1. 项目概述
这套基于Java技术栈的外卖系统是我在餐饮行业数字化转型过程中开发的一个实战项目。随着线上订餐需求的爆发式增长,传统餐饮企业急需一套功能完备、稳定可靠的外卖管理系统。这个系统采用SpringBoot+SSM的主流架构,完整实现了从用户下单到商家接单、骑手配送的全流程数字化管理。
系统最核心的价值在于打通了餐饮外卖的完整业务闭环:用户可以通过微信小程序或H5页面浏览餐厅、选择菜品、下单支付;商家后台可以实时接收订单、管理菜品库存、处理退款;配送端则能智能分配骑手、规划最优路线。整套系统经过3个实际餐饮项目的验证,高峰期可稳定支撑每分钟200+的并发订单。
提示:系统采用模块化设计,各功能组件可独立部署,中小型餐饮企业可以根据实际需求选择安装部分模块,降低初期投入成本。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术架构解析
2.1 后端技术选型
系统后端采用经典的Java三层架构:
- 表现层:SpringMVC处理HTTP请求,配合Swagger生成API文档
- 业务层:SpringBoot 2.7 + Spring Transaction管理业务逻辑
- 持久层:MyBatis-Plus 3.5.2 + PageHelper分页插件操作MySQL
数据库设计遵循餐饮行业特点:
sql复制-- 典型表结构示例
CREATE TABLE `order_detail` (
`id` bigint NOT NULL AUTO_INCREMENT,
`order_id` varchar(32) NOT NULL COMMENT '订单编号',
`food_id` bigint NOT NULL COMMENT '菜品ID',
`food_name` varchar(64) NOT NULL COMMENT '菜品名称',
`food_price` decimal(10,2) NOT NULL COMMENT '菜品单价',
`food_quantity` int NOT NULL COMMENT '购买数量',
`food_icon` varchar(512) DEFAULT NULL COMMENT '菜品图片',
PRIMARY KEY (`id`),
KEY `idx_order_id` (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单明细表';
2.2 前端技术方案
针对不同终端采用差异化方案:
- 用户端:Vue.js + Vant UI构建的H5页面,适配微信生态
- 商家端:React + Ant Design Pro的管理后台
- 骑手端:Uni-app开发的跨平台APP
2.3 关键技术实现
2.3.1 订单状态机设计
使用状态模式实现订单生命周期管理:
java复制public enum OrderStatus {
WAIT_PAY(0, "待支付"),
WAIT_ACCEPT(1, "待接单"),
WAIT_DELIVERY(2, "待配送"),
DELIVERING(3, "配送中"),
COMPLETED(4, "已完成"),
CANCELLED(5, "已取消");
// 状态转换校验逻辑
public static boolean canChangeStatus(OrderStatus from, OrderStatus to) {
// 具体状态转换规则...
}
}
2.3.2 分布式锁应用
使用Redis实现分布式锁,解决超卖问题:
java复制public boolean lock(String key, String value, long expireTime) {
return redisTemplate.opsForValue().setIfAbsent(key, value, expireTime, TimeUnit.SECONDS);
}
public boolean unlock(String key, String value) {
String currentValue = redisTemplate.opsForValue().get(key);
if (currentValue != null && currentValue.equals(value)) {
redisTemplate.delete(key);
return true;
}
return false;
}
3. 核心功能实现
3.1 智能订单分配
系统采用加权评分算法为订单匹配最佳骑手:
- 计算骑手当前位置与商家的距离分(0-40分)
- 评估骑手当前负载情况(0-30分)
- 考虑骑手历史服务质量(0-20分)
- 加入随机因子避免算法固化(0-10分)
java复制public Rider selectBestRider(Order order) {
List<Rider> candidates = riderService.findAvailableRiders(order.getShop());
return candidates.stream()
.max(Comparator.comparing(r -> calculateScore(r, order)))
.orElseThrow(() -> new BusinessException("无可用骑手"));
}
private double calculateScore(Rider rider, Order order) {
double distanceScore = 40 * (1 - normalizeDistance(rider, order));
double loadScore = 30 * (1 - rider.getCurrentOrders() / 5.0);
double qualityScore = 20 * rider.getQualityRating();
double randomScore = 10 * Math.random();
return distanceScore + loadScore + qualityScore + randomScore;
}
3.2 实时消息推送
采用WebSocket+MQTT混合方案实现多端实时通信:
- 订单状态变更通过WebSocket即时推送
- 骑手位置更新采用MQTT协议降低带宽消耗
- 重要业务消息使用阿里云短信备份
消息协议设计示例:
json复制{
"msgId": "123e4567-e89b-12d3-a456-426614174000",
"msgType": "ORDER_STATUS_UPDATE",
"data": {
"orderId": "O20230801123456",
"newStatus": "DELIVERING",
"timestamp": 1690867200000
}
}
4. 性能优化实践
4.1 数据库优化
针对外卖系统高频查询场景特别优化:
- 订单表按月份分表,历史数据自动归档
- 热数据缓存策略:
- 菜品信息:Redis缓存 + 本地Caffeine二级缓存
- 商家信息:Guava Cache实现应用内缓存
- 建立复合索引:
sql复制ALTER TABLE `order_master` ADD INDEX `idx_shop_status` (`shop_id`, `order_status`), ADD INDEX `idx_user_time` (`user_id`, `create_time` DESC);
4.2 高并发处理
通过多种技术手段保障高峰时段稳定性:
- 接口限流:使用Guava RateLimiter控制核心接口QPS
- 请求削峰:RabbitMQ延迟队列处理促销活动流量
- 降级方案:配置Hystrix熔断规则,超时自动返回缓存数据
压测指标(4核8G服务器):
| 场景 | QPS | 平均响应时间 | 错误率 |
|---|---|---|---|
| 菜品查询 | 1200 | 38ms | 0.01% |
| 下单接口 | 800 | 65ms | 0.05% |
| 支付回调 | 1500 | 25ms | 0% |
5. 部署与运维
5.1 容器化部署
采用Docker Compose编排微服务:
yaml复制version: '3'
services:
order-service:
image: registry.cn-hangzhou.aliyuncs.com/food-delivery/order:v1.2
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=prod
- REDIS_HOST=redis
depends_on:
- redis
- mysql
redis:
image: redis:6-alpine
ports:
- "6379:6379"
volumes:
- redis-data:/data
volumes:
redis-data:
5.2 监控方案
搭建完整的监控体系:
- Prometheus采集JVM/MySQL指标
- Grafana展示关键业务仪表盘
- ELK收集分析业务日志
- 企业微信机器人发送告警通知
关键监控指标阈值:
- CPU使用率 > 80%持续5分钟
- 订单失败率 > 1%持续10分钟
- 平均响应时间 > 1秒持续15分钟
6. 典型问题解决方案
6.1 重复支付处理
采用分布式事务保证支付一致性:
- 生成支付流水时先落库标记"处理中"
- 支付回调时通过唯一事务ID防重
- 定时任务补偿处理异常订单
java复制@Transactional
public PaymentResult handleCallback(PaymentNotify notify) {
PaymentRecord record = paymentDao.findByTransactionId(notify.getTransactionId());
if (record == null) {
throw new BusinessException("支付记录不存在");
}
if (record.getStatus() != PaymentStatus.PROCESSING) {
return new PaymentResult(record.getStatus());
}
// 实际业务处理
orderService.confirmPayment(record.getOrderId());
paymentDao.updateStatus(record.getId(), PaymentStatus.SUCCESS);
return new PaymentResult(PaymentStatus.SUCCESS);
}
6.2 骑手轨迹优化
使用GeoHash算法提高位置查询效率:
- 将经纬度转换为GeoHash字符串
- 按精度分级存储位置数据
- 附近骑手查询时先匹配GeoHash前缀
java复制public List<Rider> findNearbyRiders(double lat, double lng, int radius) {
String geoHash = GeoHash.withCharacterPrecision(lat, lng, 8).toBase32();
String prefix = geoHash.substring(0, 5);
return riderDao.findByGeoHashPrefix(prefix).stream()
.filter(r -> distance(lat, lng, r.getLat(), r.getLng()) <= radius)
.sorted(Comparator.comparing(r -> distance(lat, lng, r.getLat(), r.getLng())))
.collect(Collectors.toList());
}
这套系统在实际运营中,帮助某连锁餐饮品牌将订单处理效率提升了60%,人力成本降低35%。特别在骑手调度算法上线后,平均配送时间缩短了15分钟,客户投诉率下降40%。对于想要自建外卖平台的餐饮企业,这个经过实战检验的方案值得参考。
