返回成就页

智慧食堂订餐管理平台

智慧食堂订餐管理平台

项目背景

暂无项目背景

STAR 过程

情境(Situation):暂无

任务(Task):暂无

行动(Action):暂无

结果(Result):暂无

智慧食堂 — 项目概要文档

1. 项目简介

sky-take-out 是一套基于 Spring Boot 2.7.3 的智慧食堂后端管理系统。系统采用 Maven 多模块聚合工程,提供管理端(Admin)和用户端(C端)两套完整 API,覆盖菜品/套餐管理、购物车与订单、报表统计,并扩展了智慧食堂功能:每日菜单计划、营养追踪、取餐时段预约、团队拼单、周订阅自动下单。

  • 技术栈: Java 8+, Spring Boot 2.7.3, MyBatis, MySQL 8.x, Redis 6.x+, RabbitMQ 3.x+, WebSocket, Knife4j
  • 端口: 8081
  • API 文档: http://localhost:8081/doc.html

2. 仓库结构

sky-take-out/
├── sky-common/          # 通用模块:常量、异常、工具类、统一响应、配置属性
├── sky-pojo/            # 数据模型:DTO(28)、Entity(18)、VO(25)
├── sky-server/          # 主服务模块:Controller、Service、Mapper、Config、Task、WebSocket
├── sql/                 # 数据库脚本 (smart_canteen_ddl.sql)
├── k6_test/             # 压测脚本与结果
└── note/                # 技术文档

3. 技术架构图(文字描述)

┌──────────────────────────────────────────────────────────┐
│                    前端 (管理端 / 微信小程序)               │
└──────────┬───────────────────────────────┬───────────────┘
           │ /admin/**                     │ /user/**
           ▼                               ▼
    ┌─────────────┐                ┌─────────────┐
    │ JWT Admin   │                │ JWT User    │
    │ Interceptor │                │ Interceptor │
    └──────┬──────┘                └──────┬──────┘
           │                               │
           ▼                               ▼
    ┌─────────────────────────────────────────────┐
    │               Controller Layer              │
    │    (12 Admin Controllers + 13 User Controllers) │
    └────────────────────┬────────────────────────┘
                         │
                         ▼
    ┌─────────────────────────────────────────────┐
    │                Service Layer                │
    │  15 Interfaces + 15 Impls + Cache/MQ/Stock  │
    └────────────────────┬────────────────────────┘
                         │
           ┌─────────────┼─────────────┐
           ▼             ▼             ▼
    ┌──────────┐  ┌──────────┐  ┌────────────┐
    │  MyBatis │  │  Redis   │  │  RabbitMQ  │
    │  (MySQL) │  │ (缓存/库存)│  │ (异步下单)  │
    └──────────┘  └──────────┘  └────────────┘
           │             │             │
           ▼             ▼             ▼
    ┌──────────┐  ┌──────────┐  ┌────────────┐
    │  MySQL   │  │  Redis   │  │  RabbitMQ  │
    │ 18 tables│  │  Server  │  │   Server   │
    └──────────┘  └──────────┘  └────────────┘

关键技术组件:

  • WebSocket: 新订单/催单实时推送
  • Scheduled Tasks: 超时订单取消、每日菜单生成、配送自动完成
  • AOP: 自动填充创建/更新时间与操作人

4. 核心业务能力

业务域管理端用户端
认证鉴权员工登录/JWT微信登录/JWT
分类管理CRUD + 起停按类型查询
菜品管理CRUD + 口味 + 起停按分类查询(缓存)
套餐管理CRUD + 菜品关联 + 起停按分类查询(缓存)
购物车-加入/查看/清空
订单管理确认/拒单/取消/派送/完成/统计提交/支付/催单/历史/取消/再来一单
报表营业额/用户/订单/Top10-
工作台今日数据/概览-
文件上传阿里云 OSS-
店铺状态营业/休息查看状态
智慧食堂
菜单计划CRUD今日菜单/按餐段查询
营养信息CRUD菜品营养/今日摄入
取餐时段配置时间段查看可用时段
拼单-创建/加入/退出/查邀请码
周订阅-订阅/暂停/恢复/取消(自动下单)

5. 订单链路核心设计

提交 → 幂等(Redis SET NX) → 库存扣减(Redis Lua原子) → 雪花ID → MQ异步入MySQL
  • 幂等保护: Redis 键 120 秒防重复
  • 库存扣减: Lua 脚本保证原子性,失败自动回滚
  • 异步写入: RabbitMQ 削峰,消费者负责写入 orders 和 order_detail
  • 支付防重: Redis 分布式锁 + CAS SQL 双重保险
  • 分表支持: 按月分表(可配置开关),支持海量订单

详见 详细技术文档


6. 数据库概览

18 张表,分为两大类:

基础业务(11 张): employee, user, category, dish, dish_flavor, setmeal, setmeal_dish, shopping_cart, orders, order_detail, address_book

智慧食堂新增(7 张): meal_plan, nutrition_info, pickup_slot, group_order, group_order_member, meal_subscription, user_daily_nutrition

详见 数据库文档


7. API 概览

类别路径前缀Controller 数接口数
管理端/admin/12~50
用户端/user/13~45
WebSocket/ws/{sid}11

详见 接口文档


8. 本地运行

环境要求

  • JDK 8+、Maven 3.6+
  • MySQL 8.x(数据库 sky_take_out
  • Redis 6.x+
  • RabbitMQ 3.x+

启动

mvn clean package -DskipTests
mvn -pl sky-server spring-boot:run

访问

  • API: http://localhost:8081
  • 文档: http://localhost:8081/doc.html
  • WebSocket: ws://localhost:8081/ws/{sid}

9. 外部依赖

服务用途
MySQL 8.x主数据库
Redis 6.x+缓存、库存计数、分布式锁、幂等
RabbitMQ 3.x+订单异步创建
阿里云 OSS图片/文件存储
微信小程序 APIC端用户登录

智慧食堂 — 详细技术文档

1. 项目概述

sky-take-out 是一个基于 Spring Boot 2.7.3 的外卖 / 智慧食堂后端系统。采用 Maven 多模块结构,覆盖管理端与用户端的完整业务链路,并在原外卖系统基础上扩展了智慧食堂功能(菜单计划、拼单、周订阅、营养追踪、取餐时段管理)。


2. 项目结构

sky-take-out/
├── pom.xml                          # 根 POM,聚合模块 + 依赖管理
├── sky-common/                       # 通用模块:常量、异常、工具类、Result、配置属性
├── sky-pojo/                         # 数据模型:Entity、DTO、VO
├── sky-server/                       # 主服务:Controller、Service、Mapper、Config、Task、WebSocket
├── sql/                              # 数据库脚本(智慧食堂 DDL)
├── k6_test/                          # 压测脚本
└── note/                             # 技术文档

2.1 sky-common(通用模块)

包路径内容说明
com.sky.constantAutoFillConstant, JwtClaimsConstant, MessageConstant, PasswordConstant, StatusConstant常量定义
com.sky.contextBaseContextThreadLocal 存储当前用户 ID
com.sky.enumerationOperationTypeINSERT / UPDATE
com.sky.exceptionBaseException 及 11 个子类异常业务异常体系
com.sky.jsonJacksonObjectMapper自定义 Jackson 序列化(Java 8 时间支持)
com.sky.propertiesAliOssProperties, JwtProperties, WeChatProperties外部配置绑定
com.sky.resultResult, PageResult统一响应格式
com.sky.utilsAliOssUtil, HttpClientUtil, JwtUtil, WeChatPayUtil通用工具

2.2 sky-pojo(数据模型)

包路径数量说明
com.sky.dto28 个数据传输对象,接收前端参数
com.sky.entity18 个数据库实体映射
com.sky.vo25 个视图对象,返回给前端

2.3 sky-server(主服务)

文件数说明
Controller2512 个 admin + 13 个 user
Service 接口15业务接口
Service 实现15业务实现
Service 组件4CacheClient, CacheConsistencyService + 3 个 order 子服务
Mapper18MyBatis 接口 + 18 个 XML
Config5WebMvc, Redis, OSS, WebSocket, RabbitMQ
Interceptor2JWT 拦截器(admin + user)
Aspect1AutoFillAspect
Task/Scheduler3OrderTask, WebSocketTask, MealPlanScheduler
WebSocket1WebSocketServer
Handler1GlobalExceptionHandler

3. 认证鉴权机制

3.1 双通道 JWT 认证

系统有两套独立的认证通道:

通道请求路径前缀Token 头名称JWT Claim放行接口
Admin/admin/**tokenEMP_ID/admin/employee/login
User/user/**authenticationUSER_ID/user/user/login

3.2 拦截器配置

WebMvcConfiguration 注册两个拦截器:

  • JwtTokenAdminInterceptor: 从请求头取 token,用 admin 密钥解析 JWT,提取 EMP_ID 置入 BaseContext.setCurrentId(empId)
  • JwtTokenUserInterceptor: 从请求头取 authentication,用 user 密钥解析 JWT,提取 USER_ID 置入 BaseContext

解析失败返回 HTTP 401。

3.3 BaseContext — ThreadLocal 上下文

public class BaseContext {
    private static final ThreadLocal<Long> threadLocal = new ThreadLocal<>();
    public static void setCurrentId(Long id);
    public static Long getCurrentId();
    public static void removeCurrentId();
}

用于 AOP 自动填充、Service 层获取当前操作用户 ID。

3.4 密码策略

  • 管理端默认密码 123456,MD5 加密存储
  • 登录时对明文密码 MD5 后与数据库比对
  • 员工查询时密码字段脱敏为 "****"

3.5 微信登录流程

  1. C端传入微信小程序 code
  2. 调用微信 API https://api.weixin.qq.com/sns/jscode2session 获取 openid
  3. 查数据库是否存在该 openid,不存在则自动注册
  4. 生成 JWT(claim: USER_ID)返回

4. 订单核心链路

订单链路是系统最关键的业务链路,包含以下节点:

4.1 链路总览

用户提交订单 → 幂等检查 → 库存扣减 → 生成订单号 → RabbitMQ 异步入 MySQL
                                                    ↓
                                              OrderCreateConsumer
                                              → 写入 orders / order_detail
                                              → 失败回滚库存

4.2 详细步骤(OrderServiceImpl.submit)

步骤 1: 校验

  • 校验购物车非空
  • 校验地址存在
  • 智慧食堂模式:若请求含 mealPeriodpickupSlotId,尝试预订取餐时段

步骤 2: 幂等检查

  • 生成幂等键: order:submit:idem:{userId}:{MD5(DTO JSON)} 或使用客户端提供的 Idempotency-Key
  • SET NX 到 Redis,TTL 120 秒
  • 若 set 失败(键已存在),检查是否有缓存结果返回;若都无,抛 OrderBusinessException("请勿重复提交")

步骤 3: 库存扣减

  • 遍历购物车,对每项构建 stock key: stock:dish:{dishId}stock:setmeal:{setmealId}
  • 调用 RedisLuaStockService.tryDeduct(key, quantity) 原子扣减
  • 任一扣减失败,回滚所有已扣项,抛异常

步骤 4: 生成订单号

  • SnowflakeIdWorker.nextId() 生成全局唯一订单号
  • 参数: epoch 2023-01-01, machineId=1, 10 位机器 ID + 12 位序列号

步骤 5: 异步入 MySQL

  • 构造 OrderCreateEvent(含订单号、DTO、地址、购物车数据、扣减记录、分表表名)
  • 通过 OrderEventProducer 发送到 RabbitMQ 交换机 order.event.exchange,routing key order.create

步骤 6: 返回结果

  • OrderSubmitVO 缓存到 Redis(key=幂等键,TTL 10 分钟)
  • 返回给前端

4.3 异步消费者(OrderCreateConsumer)

@RabbitListener(queues = "order.create.queue"):

  1. 幂等检查: 查分表内是否已有该订单号(getByNumberFromTable),有则跳过
  2. 写入 orders 表: insertToTable 到路由后的分表
  3. 写入 order_detail 表: insertBatchToTable 批量插入
  4. 失败处理: catch 异常后调用 StockService.rollback() 回滚库存
  5. 自动确认: 默认 autoDelete 模式

4.4 订单状态机

PENDING_PAYMENT (1)
    │
    ├─ paySuccess() → TO_BE_CONFIRMED (2)
    │                    │
    │                    ├─ confirm() → CONFIRMED (3)
    │                    │                │
    │                    │                ├─ delivery() → DELIVERY_IN_PROGRESS (4)
    │                    │                │                  │
    │                    │                │                  ├─ complete() → COMPLETED (5)
    │                    │                │                  │
    │                    │                │                  └─ 1AM 定时任务: super(old>60min) → COMPLETED (5)
    │                    │                │
    │                    │                └─ pickup() (智慧食堂) → COMPLETED (5)
    │                    │
    │                    └─ rejection() → CANCELLED (6) [已支付则退款]
    │
    ├─ userCancel() → CANCELLED (6)
    ├─ adminCancel() → CANCELLED (6)
    │
    └─ 定时任务: 超时 15 分钟未支付 → CANCELLED (6)

4.5 支付防重

支付成功回调 paySuccess(outTradeNo):

  • Redis 分布式锁: order:pay:success:{outTradeNo},TTL 24 小时
  • CAS 更新 SQL: UPDATE orders SET status=TO_BE_CONFIRMED, pay_status=PAID WHERE id=? AND status=PENDING_PAYMENT AND pay_status=UNPAID
  • 成功后推送 WebSocket 新订单通知(type=1)

5. 缓存架构

5.1 CacheClient — 缓存读取组件

实现 read-through 缓存模式,解决三大缓存问题:

防击穿(热点数据过期瞬间大量请求打 DB):

  • Redis 互斥锁: SET NX lock:key value EX 10s
  • 获得锁的线程查 DB 并回写缓存
  • 未获得锁的线程定时间隔重试(最多 60 次,每次 50ms)
  • 解锁使用 Lua 脚本 if get(key)==token then del(key) 防止误删

防穿透(查询不存在的数据):

  • 查询结果为 null 时,写 __NULL__ 标记到缓存,TTL 3 分钟

防雪崩(大量缓存同时过期):

  • 每个缓存 TTL 加随机抖动: defaultTtlMinutes + random(0, ttlJitterMinutes)
  • 默认 30 分钟 + 随机 0~10 分钟

配置项 (sky.cache.*):

配置默认值说明
default-ttl-minutes30默认缓存 TTL
ttl-jitter-minutes10TTL 随机抖动范围
null-ttl-minutes3空值缓存 TTL
lock-ttl-seconds10互斥锁 TTL
lock-sleep-millis50重试间隔
lock-retry-times60最大重试次数

5.2 CacheConsistencyService — 缓存一致性

采用 双删策略(double-delete):

  1. 立即删除: 更新数据库后立即删除缓存
  2. 延迟删除: 500ms 后再次删除(防止并发读导致脏数据被回写)

支持:

  • doubleDelete(String key): 精确删除单个缓存键
  • doubleDeleteByPattern(String pattern): 模式匹配批量删除

使用 ThreadPoolTaskScheduler(pool size=2)执行延迟删除。

5.3 缓存应用位置

缓存键使用位置缓存方式
dish_{categoryId}User DishControllerCacheClient.queryWithMutex
setmeal_{categoryId}User SetmealControllerCacheClient.queryWithMutex
meal_plan_list:{date}User MealPlanControllerCacheClient + MealPlanScheduler 预热
meal_plan:{date}:{period}User MealPlanControllerCacheClient

5.4 缓存失效触发

操作触发的缓存清除
菜品新增/更新/删除/状态变更doubleDelete("dish_" + categoryId) + doubleDeleteByPattern("dish_*")
套餐新增/更新/删除/状态变更doubleDeleteByPattern("setmeal_*")

6. 消息队列设计

6.1 RabbitMQ 拓扑

order.event.exchange (Direct, durable)
        │
        ▼
order.create.queue (durable)
        │
        ▼
OrderCreateConsumer (@RabbitListener)
元素名称说明
Exchangeorder.event.exchange直连交换机,持久化
Queueorder.create.queue持久化队列
Routing Keyorder.create绑定路由键

6.2 消息序列化

RabbitOrderConfig 配置 Jackson2JsonMessageConverter,集成 JavaTimeModule 以支持 LocalDateTime 等 Java 8 时间类型的序列化与反序列化。

6.3 OrderCreateEvent

事件对象在 com.sky.dto.OrderCreateEvent,包含:

  • 订单号、DTO、地址
  • 购物车数据
  • 已扣减的库存清单
  • 目标分表表名

6.4 消费策略

  • 消费者确认模式: 自动确认(默认)
  • 失败策略: 捕获异常后,主动调用 StockService.rollback() 回滚 Redis 库存
  • 消息顺序: 不保证严格顺序(订单号通过幂等检查去重)

7. 库存扣减

7.1 RedisLuaStockService

使用 Redis Lua 脚本实现原子性库存检查与扣减:

local stock = redis.call('get', KEYS[1]);
if (not stock) then return -1 end;  -- 库存键不存在
stock = tonumber(stock);
local qty = tonumber(ARGV[1]);
if (stock < qty) then return 0 end;  -- 库存不足
redis.call('decrby', KEYS[1], qty);
return 1;  -- 扣减成功

返回值:

  • 1: 扣减成功
  • 0: 库存不足
  • -1: 库存键不存在

7.2 StockService 接口

方法说明
tryDeduct(key, qty)原子扣减,返回是否成功
rollback(List<StockDeductItem>)批量回滚(INCRBY 返还已扣数量)
increase(key, qty)增加库存
exists(key)检查库存键是否存在
buildStockKey(cart)从购物车项构建 stock key

7.3 库存键设计

  • 菜品: stock:dish:{dishId}
  • 套餐: stock:setmeal:{setmealId}

库存数值需由管理系统预先设定。


8. 订单分表策略

8.1 OrderShardRouter

配置默认值说明
sky.sharding.enabledfalse是否启用分表
sky.sharding.scan-months2定时任务扫描的月份数

分表命名规则: orders_YYYYMM / order_detail_YYYYMM

路由逻辑:

  • 未启用分表: 所有操作指向 orders / order_detail
  • 启用分表: 按订单时间路由到对应月份的分表

定时任务扫描: candidateOrdersTables(LocalDateTime.now()) 返回当前及最近 N 个月的 orders 分表名列表,用于超时订单扫描。

8.2 动态表名

Mapper XML 使用 ${ordersTable} / ${orderDetailTable} 动态表名(非预编译),传入参数时以 Map 形式传递:

Map<String, Object> params = new HashMap<>();
params.put("ordersTable", router.ordersTable(time));
params.put("order", orderEntity);

9. 雪花 ID 生成

9.1 SnowflakeIdWorker

参数
起始时间戳 (epoch)2023-01-01 00:00:00 (1672502400000)
机器 ID 位数10 bit(最多 1024 台机器)
序列号位数12 bit(每毫秒 4096 个ID)
当前机器 ID1

时钟回拨处理: spin-wait 直到时间追上上次时间戳。


10. 取餐时段预订

10.1 容量控制

PickupSlotServiceImpl.tryBook(slotId):

Redis 侧(核心,Lua 脚本):

-- 原子检查容量并 +1
local booked = redis.call('get', 'pickup:slot:'..slotId..':booked');
if booked and tonumber(booked) >= maxCapacity then return 0 end;
redis.call('incr', 'pickup:slot:'..slotId..':booked');
return 1;

MySQL 侧(备份): 同时更新 pickup_slot.booked_count 字段作为数据兜底。

10.2 释放

  • release(slotId): Redis DECR + MySQL booked_count - 1

11. 拼单系统

11.1 状态流转

RECRUITING (1) ── timeout ──> members>=2: CLOSED_PENDING (2) ──> ORDERED (3)
                  │              members<2: CANCELLED (4)
                  │
                  └── leader 取消 ──> CANCELLED (4)

11.2 核心逻辑

创建: 生成 6 位邀请码(UUID 前 6 位),存储到 Redis group_order:lock:{inviteCode}

加入: 原子增加 current_membersincrementMembers mapper 用 SET current_members = current_members + 1),检查:

  • 拼单状态为 RECRUITING
  • 当前成员数 < 最大成员数
  • 未超过截止时间

定时处理 (processDeadline()):

  • 每 30 秒扫描已截止的拼单
  • 成员 >= 2 → 状态变更为 CLOSED_PENDING → 自动为每个成员提交订单 → ORDERED
  • 成员 < 2 → CANCELLED

12. 周订阅系统

12.1 SubscriptionServiceImpl

定时任务 (processDailyAutoOrder()): 每天早 7:00 执行

  1. 查询所有 ACTIVE 状态、当前日期在工作日范围内的订阅
  2. 对每个订阅,根据订阅的餐段,查找当天的 meal_plan
  3. 为每个餐段自动生成订单
  4. 使用幂等键 sub:{subscriptionId}:{date}:{period} 防止重复下单

状态: ACTIVE → PAUSED(暂停) / ACTIVE → CANCELLED(取消) / PAUSED → ACTIVE(恢复)


13. 定时任务

13.1 OrderTask

任务Cron功能
deleteOrder()0 * * * * ? (每分钟)扫描所有候选分表,取消超过 15 分钟未支付订单
completeOrder()0 0 1 * * ? (每天 1:00 AM)自动完成超过 60 分钟的配送中订单

13.2 MealPlanScheduler

任务Cron功能
生成每日菜单0 0 2 * * ? (每天 2:00 AM)为当天自动创建三餐菜单计划(早餐:4菜+2套餐, 午餐:8菜+4套餐, 晚餐:6菜+3套餐),缓存到 Redis TTL 26 小时

13.3 WebSocketTask

任务Cron功能
心跳推送0/5 * * * * ? (每 5 秒)向所有连接客户端广播服务器时间

14. WebSocket 实时推送

14.1 服务端

WebSocketServer 使用 JSR 356 @ServerEndpoint("/ws/{sid}") 注解:

  • sessionMap: ConcurrentHashMap<String, Session> 管理连接
  • sendToAllClient(message): 遍历所有 session 发送消息

14.2 消息类型

type事件触发位置
1新订单通知OrderServiceImpl.paySuccess()
2催单通知OrderServiceImpl.remind()

14.3 配置

WebSocketConfiguration 注册 ServerEndpointExporter bean 以启用 @ServerEndpoint 注解。


15. AOP 自动填充

15.1 @AutoFill 注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {
    OperationType value();
}

15.2 AutoFillAspect

切点: execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)

逻辑:

  • 获取被注解方法的第一个参数(实体对象)
  • INSERT: 通过反射调用 setCreateTime(now), setUpdateTime(now), setCreateUser(currentId), setUpdateUser(currentId)
  • UPDATE: 通过反射调用 setUpdateTime(now), setUpdateUser(currentId)

currentIdBaseContext.getCurrentId() 获取(ThreadLocal)。


16. 全局异常处理

16.1 GlobalExceptionHandler

@RestControllerAdvice:

  • BaseException(及其子类): 返回 Result.error(ex.getMessage())
  • SQLIntegrityConstraintViolationException: 解析重复键异常,提取字段名,返回友好提示 "duplicateField" + USER_EXIST

17. 配置详解

17.1 application.yml 核心配置

server:
  port: 8081

spring:
  profiles:
    active: dev
  datasource:
    druid: ...           # 数据源配置(dev 中明文)
  redis: ...             # Redis 连接(dev 中明文)
  rabbitmq: ...          # RabbitMQ 连接(localhost:5672, guest/guest)
  main:
    allow-circular-references: true  # 允许循环依赖

mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.sky.entity
  configuration:
    map-underscore-to-camel-case: true

sky:
  cache:
    default-ttl-minutes: 30
    ttl-jitter-minutes: 10
    null-ttl-minutes: 3
    lock-ttl-seconds: 10
    lock-sleep-millis: 50
    lock-retry-times: 60
  jwt:
    admin-secret-key: itcast
    user-secret-key: itcast
    admin-token-name: token
    user-token-name: authentication
    admin-ttl: 720000000    # 约 8.3 天
    user-ttl: 720000000
  sharding:
    enabled: false
    scan-months: 2

17.2 安全提醒

application-dev.yml 包含明文密码(MySQL: root/123456, Redis: 123456, WeChat appid, OSS access key),不建议直接用于生产环境。


18. 关键设计决策与权衡

决策选择原因
订单创建RabbitMQ 异步 + 立即返回提升用户响应速度,削峰填谷
库存扣减Redis Lua 原子操作保证高并发下库存一致性
缓存更新Cache Aside + 双删保证最终一致性,避免缓存脏数据
幂等保护Redis SET NX + 业务键简单可靠的防重方案
分表策略按月分表(可开关)适应订单数据增长,开发/测试阶段可关闭
支付防重Redis 锁 + CAS SQL双保险,防止重复处理支付回调
取餐容量Redis Lua(主) + MySQL(备)Redis 保障并发性能,MySQL 保证数据持久
JWT 密钥itcast(固定明文)开发/学习环境,生产环境应使用配置中心
密码加密MD5开发/学习环境,生产环境应使用 BCrypt/Argon2
雪花 ID epoch2023-01-01基于项目创建时间,缩小 ID 长度

19. 外部依赖

服务用途配置位置
MySQL 8.x主数据库application-dev.yml
Redis 6.x+缓存/库存/锁/幂等application-dev.yml
RabbitMQ 3.x+订单异步创建application.yml (localhost:5672)
阿里云 OSS图片文件存储application-dev.yml
微信小程序 API用户登录WeChatProperties

20. 启动指南

环境要求

  • JDK 8+
  • Maven 3.6+
  • MySQL 8.x(需预先创建 sky_take_out 数据库并执行 DDL)
  • Redis 6.x+
  • RabbitMQ 3.x+

启动步骤

# 1. 编译
mvn clean package -DskipTests

# 2. 启动 sky-server 模块
mvn -pl sky-server spring-boot:run

# 3. 或者直接运行 jar
java -jar sky-server/target/sky-server-1.0-SNAPSHOT.jar

可访问地址

  • API 服务: http://localhost:8081
  • Knife4j 文档: http://localhost:8081/doc.html
  • WebSocket: ws://localhost:8081/ws/{sid}