Spring Boot与Vue 3构建外卖点餐系统实战
2026/9/17 23:16:34 网站建设 项目流程

1. 项目概述与设计思路

外卖点餐管理系统是现代餐饮行业数字化转型的核心工具,我们采用前后端分离架构实现了一套高性能、易扩展的解决方案。这个系统主要解决三个核心问题:一是提升餐厅运营效率,二是优化顾客点餐体验,三是实现精准的订单管理。

技术选型上,后端采用Spring Boot框架,版本为2.7.5,主要考虑其快速启动、自动配置和丰富的起步依赖特性。前端选择Vue 3组合式API,配合Element Plus组件库,确保界面响应速度和开发效率。数据库使用MySQL 8.0,充分利用其事务处理能力和JSON字段支持。

系统架构分为四层:

  • 表现层:Vue构建的响应式Web界面和移动端适配页面
  • 应用层:Spring Boot提供的RESTful API服务
  • 业务逻辑层:领域驱动设计(DDD)实现的订单处理核心
  • 数据访问层:MyBatis-Plus + 多数据源配置

2. 核心模块实现细节

2.1 用户认证与权限控制

采用JWT+Spring Security的安全方案,关键实现如下:

@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() .antMatchers("/api/auth/**").permitAll() .antMatchers("/api/admin/**").hasRole("ADMIN") .anyRequest().authenticated() .and() .addFilter(new JwtAuthenticationFilter(authenticationManager())) .addFilter(new JwtAuthorizationFilter(authenticationManager())); } }

权限设计采用RBAC模型,包含5种角色:

  1. 顾客:浏览菜单、下单、支付
  2. 商家:菜品管理、订单处理
  3. 配送员:接单、配送状态更新
  4. 店长:数据统计、员工管理
  5. 超级管理员:系统配置

关键点:JWT令牌设置30分钟过期时间,配合refreshToken机制实现无感刷新。权限验证通过自定义注解@PreAuthorize实现方法级控制。

2.2 订单状态机设计

订单生命周期管理采用状态模式,定义6种核心状态:

stateDiagram [*] --> 待支付 待支付 --> 已取消: 超时/用户取消 待支付 --> 已支付: 支付成功 已支付 --> 制作中: 商家接单 制作中 --> 配送中: 制作完成 配送中 --> 已完成: 送达确认 已完成 --> [*]

状态转换通过Spring StateMachine实现:

public class OrderStateMachineConfig extends EnumStateMachineConfigurerAdapter<OrderState, OrderEvent> { @Override public void configure(StateMachineStateConfigurer<OrderState, OrderEvent> states) throws Exception { states .withStates() .initial(OrderState.待支付) .states(EnumSet.allOf(OrderState.class)); } @Override public void configure(StateMachineTransitionConfigurer<OrderState, OrderEvent> transitions) throws Exception { transitions .withExternal() .source(OrderState.待支付).target(OrderState.已取消) .event(OrderEvent.取消订单) .and() .withExternal() .source(OrderState.待支付).target(OrderState.已支付) .event(OrderEvent.支付成功); } }

2.3 高并发订单处理

采用多级缓存策略应对高峰时段:

  1. 本地缓存:Caffeine缓存热门菜品信息
  2. 分布式缓存:Redis集群存储库存余量
  3. 数据库:MySQL最终持久化

库存扣减使用Redis Lua脚本保证原子性:

local key = KEYS[1] local change = tonumber(ARGV[1]) local current = tonumber(redis.call('GET', key) or "0") if current + change >= 0 then redis.call('INCRBY', key, change) return 1 else return 0 end

3. 关键业务逻辑实现

3.1 购物车设计

购物车服务采用混合存储策略:

  • 登录用户:数据持久化到MySQL
  • 未登录用户:存储在localStorage

核心数据结构:

{ "cartId": "UUID", "items": [ { "dishId": 123, "quantity": 2, "selectedOptions": [ {"optionId": 1, "value": "微辣"}, {"optionId": 2, "value": "不要香菜"} ] } ], "lastUpdated": "2023-07-20T08:30:00Z" }

合并逻辑处理:

public Cart mergeCarts(Cart persistentCart, Cart tempCart) { Map<CartItemKey, CartItem> itemMap = persistentCart.getItems().stream() .collect(Collectors.toMap( item -> new CartItemKey(item.getDishId(), item.getOptionSignature()), Function.identity())); tempCart.getItems().forEach(tempItem -> { CartItemKey key = new CartItemKey(tempItem.getDishId(), tempItem.getOptionSignature()); if (itemMap.containsKey(key)) { itemMap.get(key).addQuantity(tempItem.getQuantity()); } else { persistentCart.addItem(tempItem); } }); return persistentCart; }

3.2 支付系统集成

支付流程采用状态机+策略模式:

  1. 选择支付方式(微信/支付宝/余额)
  2. 创建支付订单
  3. 调用对应支付网关
  4. 异步通知处理

防重复支付设计:

@Transactional public PaymentResult handlePayment(PaymentRequest request) { // 分布式锁防止重复提交 String lockKey = "payment:" + request.getOrderId(); try { if (!redisLock.tryLock(lockKey, 10, TimeUnit.SECONDS)) { throw new BusinessException("操作过于频繁"); } Order order = orderService.getById(request.getOrderId()); if (order.getStatus() != OrderStatus.待支付) { throw new BusinessException("订单状态异常"); } PaymentStrategy strategy = paymentStrategyFactory.getStrategy(request.getPaymentType()); PaymentResult result = strategy.pay(request); if (result.isSuccess()) { orderService.updateOrderStatus(order.getId(), OrderStatus.已支付); paymentRecordService.save(result.toPaymentRecord()); } return result; } finally { redisLock.unlock(lockKey); } }

4. 性能优化实践

4.1 数据库优化方案

  1. 索引策略:

    • 订单表:复合索引(user_id, create_time)
    • 菜品表:全文索引(name)、普通索引(category_id)
    • 使用EXPLAIN分析慢查询
  2. 分库分表:

    • 按餐厅ID水平分片
    • 订单表按月分表
    • 使用ShardingSphere实现透明访问
  3. 读写分离:

    • 一主三从架构
    • 使用Spring AbstractRoutingDataSource动态切换

4.2 前端性能提升

  1. 代码分割:
const Menu = () => import(/* webpackChunkName: "menu" */ './views/Menu.vue') const Order = () => import(/* webpackChunkName: "order" */ './views/Order.vue')
  1. 图片优化:
  • WebP格式替代PNG/JPG
  • 懒加载实现:
<img v-lazy="item.image" alt="菜品图片">
  1. API请求优化:
  • 使用GraphQL减少请求字段
  • 批量获取接口设计:
query { menu { categories { id name dishes { id name price } } } }

5. 部署与监控方案

5.1 容器化部署

Docker Compose编排方案:

version: '3.8' services: backend: image: registry.example.com/takeaway:${TAG} environment: - SPRING_PROFILES_ACTIVE=prod deploy: resources: limits: cpus: '2' memory: 2G healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"] interval: 30s timeout: 10s retries: 3 frontend: image: registry.example.com/takeaway-front:${TAG} ports: - "80:80" depends_on: - backend

5.2 监控体系搭建

  1. 指标收集:
  • Prometheus采集Spring Boot Actuator指标
  • 自定义业务指标:
@Bean public MeterRegistryCustomizer<MeterRegistry> metricsCommonTags() { return registry -> registry.config().commonTags( "application", "takeaway-system", "region", System.getenv("REGION")); }
  1. 日志收集:
  • ELK栈集中管理
  • 结构化日志配置:
<Pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</Pattern>
  1. 告警规则:
groups: - name: business.rules rules: - alert: HighFailedPaymentRate expr: rate(payment_failed_total[5m]) / rate(payment_attempted_total[5m]) > 0.1 for: 10m labels: severity: warning annotations: summary: "High payment failure rate ({{ $value }})"

6. 项目演进路线

6.1 技术债解决方案

  1. 代码重构计划:
  • 领域模型精炼:使用事件风暴重新划分限界上下文
  • 测试覆盖率提升:从60%到85%
  • 技术栈升级:Spring Boot 2.x → 3.x迁移路径
  1. 架构改进:
  • 引入CQRS模式分离读写模型
  • 关键模块服务化:支付服务独立部署
  • 事件驱动架构改造

6.2 扩展功能规划

  1. 智能推荐系统:
  • 基于用户历史的协同过滤
  • 实时推荐使用Redis向量搜索
  • 冷启动解决方案
  1. 配送路线优化:
  • 地理围栏技术
  • 骑手路径规划算法
  • 实时交通数据接入
  1. 厨房显示系统(KDS):
  • WebSocket实时推送
  • 订单优先级算法
  • 多屏协同工作

在实际开发过程中,我们发现状态机的引入虽然增加了前期设计复杂度,但显著降低了后期维护成本。特别是在处理退款流程时,状态模式的优势体现得淋漓尽致。一个经验之谈:在定义状态转换规则时,一定要与业务专家充分沟通,把所有的异常流程都考虑进去,这能避免后续80%的状态相关bug。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询