尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

Spring Boot 3 + Vue 3 全栈外卖系统:RabbitMQ异步解耦、MySQL/Neo4j双引擎推建

Spring Boot 3 + Vue 3 全栈外卖系统:RabbitMQ异步解耦、MySQL/Neo4j双引擎推建 项目简介本项目是一个完整的外卖点餐系统采用前后端分离架构后端Spring Boot 3.2.5 MyBatis-Plus Redis RabbitMQ Neo4j 支付宝沙箱前端Vue 3 Element Plus Pinia Vite核心业务覆盖用户注册登录、菜品浏览、购物车管理、下单结算、支付宝支付、订单状态实时同步、支付成功邮件通知等完整闭环。系统实现了基于用户行为的个性化推荐、基于图数据库的购物车共现推荐、以及基于消息队列的全链路异步解耦。核心技术亮点一、RabbitMQ 异步消息架构系统使用 RabbitMQ 实现了 5 大业务场景的异步解耦构建了完整的消息驱动架构。1. Exchange / Queue 全景Exchange交换机Queue队列Routing Key业务场景login_code_exchangelogin_code_maillogin.code.mail登录验证码异步邮件发送order_pay_exchangeorder_pay_queueorder.pay支付成功异步邮件通知order_delay_exchangeorder_delay_queueorder.delay订单超时延迟取消TTL 死信order_cancel_exchangeorder_cancel_queueorder.cancel超时订单实际取消执行behavior_exchangeuser_behavior_queuebehavior.save用户行为异步采集与偏好更新2. 消息流转机制┌─────────────────────────────────────────────────────────────────────┐ │ RabbitMQ 消息流转全景 │ ├─────────────────────────────────────────────────────────────────────┤ │ │ │ 【用户行为采集链路】 │ │ 前端行为上报 → BehaviorController → BehaviorServiceImpl │ │ ↓ │ │ behavior_exchange ──behavior.save──→ user_behavior_queue │ │ ↓ │ │ UserBehaviorConsumer 消费 │ │ Step1: 写入 user_behavior_log 行为日志 │ │ Step2: 更新 user_food_preference 偏好分值加权累加 │ │ Step3: 清除 Redis 推荐缓存 │ │ ↓ │ │ ⚡ 降级策略MQ不可用时自动降级为同步处理 │ │ │ │ 【订单超时取消链路TTL 死信队列】 │ │ 下单成功 → 发送 OrderDelayMessage(30min TTL) │ │ ↓ │ │ order_delay_queue (TTL1800s, 死信转发至 order_cancel_exchange) │ │ ↓ 30分钟后 │ │ 若订单未支付 → 死信路由到 order_cancel_queue │ │ ↓ │ │ OrderCancelConsumer 消费 → 自动取消订单(status3) │ │ │ │ 【支付成功通知链路】 │ │ 支付宝回调 → OrderPayProducer → order_pay_queue │ │ ↓ │ │ OrderPayConsumer 消费 → 构建 HTML 邮件 → 发送给用户 │ │ │ │ 【验证码邮件链路】 │ │ 登录/注册 → CodeMailConsumer → 异步发送验证码邮件 │ │ │ └─────────────────────────────────────────────────────────────────────┘3. 降级容错机制链路降级策略说明行为上报MQ不可用 → 同步处理直接在当前线程执行日志写入偏好更新缓存清除邮件发送MQ投递失败 → 同步发送保证邮件必达不阻塞主流程订单超时MQ连接失败 → 不触发订单依赖前端状态轮询兜底全局异常消费端异常仅记日志不影响其他消息处理4. 关键配置说明spring: rabbitmq: host: 127.0.0.1 port: 5672 username: admin password: 123456 listener: simple: concurrency: 1 # 最小消费者数 max-concurrency: 3 # 最大消费者数 acknowledge-mode: auto # 自动确认 prefetch: 10 # 每次预取消息数 publisher-confirm-type: correlated # 发布确认 publisher-returns: true # 发布返回5. 核心 Consumer 实现Consumer监听队列核心职责UserBehaviorConsumeruser_behavior_queue消费行为消息写日志更新偏好清缓存OrderPayConsumerorder_pay_queue消费支付成功消息构建HTML邮件并发送OrderCancelConsumerorder_cancel_queue消费超时取消消息自动将订单置为已取消CodeMailConsumerlogin_code_mail消费验证码消息异步发送验证码邮件二、MySQL 推荐引擎系统基于 MySQL 构建了用户行为权重推荐引擎通过多维度用户行为数据生成个性化推荐。1. 行为权重模型系统为每种用户行为类型定义了权重值用于计算用户对菜品的偏好分值行为类型类型编码权重值说明浏览 (BROWSE)10.3轻度兴趣权重最低加购 (CART)41.5中等意愿收藏 (FAVORITE)23.0强偏好意愿下单 (ORDER)38.0真实消费行为权重最高偏好分值计算公式用户对菜品A的偏好分 Σ(每次行为类型对应权重)例如用户先后浏览了菜品A(0.3)、加购了菜品A(1.5)、最终下单了菜品A(8.0)则最终偏好分 0.3 1.5 8.0 9.82. 核心数据表数据表用途关键字段user_behavior_log用户行为日志原始记录user_id, food_id, behavior_type, create_timeuser_food_preference用户菜品偏好分聚合结果user_id, food_id, score, update_timeresfood菜品基础信息fid, fname, realprice, category, spicy_levelorder_item订单明细菜品销量统计order_id, fid, num3. 推荐算法流程┌─────────────────────────────────────────────────────────────────────┐ │ MySQL 个性化推荐流程 │ ├─────────────────────────────────────────────────────────────────────┤ │ │ │ Step1: 缓存查询 │ │ ┌─────────────────────┐ │ │ │ Redis GET │ → 命中 → 直接返回TTL2h │ │ │ recommend:v2:food: │ │ │ │ user:{userId} │ → 未命中 → 进入 Step2 │ │ └─────────────────────┘ │ │ │ │ Step2: 用户画像判断 │ │ ┌─────────────────────┐ │ │ │ 查询 user_food_ │ │ │ │ preference 表 │ → 有数据 → 老用户offset0 │ │ │ COUNT(*) │ → 无数据 → 新用户计算哈希偏移 │ │ └─────────────────────┘ │ │ ↓ │ │ 新用户哈希偏移算法 │ │ offset Math.abs(hash(userId)) % maxOffset │ │ (maxOffset min(3, totalFoods - limit)) │ │ → 保证不同新用户看到不同的热销菜品组合 │ │ │ │ Step3: MySQL 推荐查询核心 SQL │ │ ┌─────────────────────────────────────────────────────────────┐ │ │ │ SELECT f.fid, f.fname, f.realprice, f.fphoto, │ │ │ │ IFNULL(p.score, 0) AS score │ │ │ │ FROM resfood f │ │ │ │ LEFT JOIN user_food_preference p │ │ │ │ ON f.fid p.food_id AND p.user_id #{userId} │ │ │ │ LEFT JOIN (菜品总销量子查询) s ON f.fid s.fid │ │ │ │ ORDER BY │ │ │ │ CASE │ │ │ │ WHEN 用户有偏好 AND p.score IS NULL THEN -1 -- 没点过排后 │ │ │ │ ELSE IFNULL(p.score, 0) │ │ │ │ END DESC, │ │ │ │ 总销量 DESC, │ │ │ │ fid ASC │ │ │ │ LIMIT #{offset}, #{limit} │ │ │ └─────────────────────────────────────────────────────────────┘ │ │ │ │ Step4: 缓存写入 │ │ ┌─────────────────────┐ │ │ │ Redis SET │ → 写入缓存供下次使用 │ │ │ recommend:v2:food: │ 缓存异常不影响返回 │ │ │ user:{userId} │ │ │ └─────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────┘4. 两种推荐模式对比维度个性化推荐 (/recommend/list)全局热销推荐 (/recommend/hot)数据源user_food_preferenceresfoodorder_itemresfoodorder_itemresorderitem排序规则偏好分 DESC → 总销量 DESC → fid ASC总销量 DESC → fid ASC目标用户已登录用户有行为数据新用户 / 冷启动缓存 Keyrecommend:v2:food:user:{userId}recommend:hot降级策略新用户哈希偏移取不同热销组合直接按总销量排序5. API 接口接口方法说明/recommend/list?userIdsizeGET个性化推荐按用户偏好分排序/recommend/hot?limitGET全局热销推荐按总销量排序/behavior/addPOST上报用户行为异步入MQ三、Neo4j 图数据库推荐系统引入 Neo4j 图数据库构建了购物车双引擎推荐能力基于用户历史订单共现关系和菜品属性规则实现智能搭配推荐。OFTEN_BOUGHT_WITH 共现关系共现 在同一个购物车 / 同一个订单里面一起出现过。 比如很多人的购物车同时放素炒莴笋丝 炖鸡这两个商品共同出现就建立这条关系。1. 图数据模型┌─────────────────────────────────────────────────────────────────────┐ │ Neo4j 图谱模型 │ │ 以 素炒莴笋丝 为中心的图关系示例 │ ├─────────────────────────────────────────────────────────────────────┤ │ │ │ (UserNode) (FoodNode) │ │ ┌─────────────────┐ ┌─────────────────────┐ │ │ │ user_id: 4 │ │ fid: 5 │ │ │ │ username:123d │──ORDERED─────→│ fname: 素炒莴笋丝 │ │ │ └─────────────────┘ orderCount:2 │ realprice: 12.00 │ │ │ ↓ lastOrderTime │ category: COLD │ │ │ │ :2026-08-02 │ spicyLevel: 0 │ │ │ │ │ totalSales: 12 │ │ │ │ └─────────────────────┘ │ │ │ ↑ │ │ │ │ │ │ │ ORDERED {count:1} │ │ │ └─────────────────────────────────────┘ │ │ │ │ (UserNode) ↑ │ │ ┌─────────────────┐ │ │ │ │ user_id: 2 │ ORDERED {count:1} │ │ │ │ username:123 │───────────────────────────┘ │ │ └─────────────────┘ │ │ │ │ │ │ 素炒莴笋丝 的共现关系OFTEN_BOUGHT_WITH │ │ ───────────────────────────────────────── │ │ │ │ (FoodNode) (FoodNode) │ │ ┌─────────────────────┐ ┌─────────────────────┐ │ │ │ fid: 20 │ │ fid: 17 │ │ │ │ fname: 清炒油麦菜 │──OFTEN_BOUGHT──→│ fname: 西红柿蛋汤 │ │ │ │ category: COLD │ _WITH │ category: SOUP │ │ │ │ spicyLevel: 0 │ count: 3 │ spicyLevel: 0 │ │ │ │ totalSales: 8 │ │ totalSales: 15 │ │ │ └─────────────────────┘ └─────────────────────┘ │ │ ↑ ↑ │ │ │ │ │ │ │ OFTEN_BOUGHT_WITH {count: 2} │ │ │ └──────────────────────────────────┘ │ │ │ │ (FoodNode) (FoodNode) │ │ ┌─────────────────────┐ ┌─────────────────────┐ │ │ │ fid: 16 │ │ fid: 26 │ │ │ │ fname: 蒜蓉西兰花 │──OFTEN_BOUGHT──→│ fname: 紫菜蛋花汤 │ │ │ │ category: COLD │ _WITH │ category: SOUP │ │ │ │ spicyLevel: 0 │ count: 2 │ spicyLevel: 0 │ │ │ │ totalSales: 6 │ │ totalSales: 10 │ │ │ └─────────────────────┘ └─────────────────────┘ │ │ │ │ └─────────────────────────────────────────────────────────────────────┘节点类型节点标签主键属性业务含义核心属性UserNodeuser_id用户节点usernameFoodNodefid菜品节点fname, realprice, fphoto, category, spicyLevel, totalSales关系类型关系类型方向含义属性ORDEREDUserNode → FoodNode用户下单关系orderCount, lastOrderTimeOFTEN_BOUGHT_WITHFoodNode → FoodNode菜品共现关系count共现次数2. 购物车双引擎推荐CartRecommendServiceImpl实现了两个独立的推荐引擎分别产出不同推荐理由的菜品┌─────────────────────────────────────────────────────────────────────┐ │ 购物车双引擎推荐架构 │ ├─────────────────────────────────────────────────────────────────────┤ │ │ │ 输入购物车菜品列表 用户ID │ │ │ │ ┌─────────────────────────────────────────────────────────────┐ │ │ │ 引擎一规则推荐基于菜品属性匹配 │ │ │ │ │ │ │ │ 原理从 Neo4j 查询购物车菜品的 category 和 spicyLevel │ │ │ │ 规则优先级 │ │ │ │ ① 有热菜无主食 → 推荐主食 (STAPLE) │ │ │ │ ② 有辣菜无汤/饮品 → 优先推荐汤品 (SOUP)其次饮品 (DRINK) │ │ │ │ ③ 有主食无汤品 → 推荐汤 (SOUP) │ │ │ │ ④ 热菜主食辣无凉菜 → 推荐凉菜 (COLD) │ │ │ │ ⑤ 兜底 → 推荐销量最高的主食或汤 │ │ │ │ │ │ │ │ Cypher 示例 │ │ │ │ MATCH (f:FoodNode {category: $category}) │ │ │ │ WHERE NOT f.fid IN $excludeFids │ │ │ │ RETURN f.fid, f.fname, f.realprice, f.totalSales │ │ │ │ ORDER BY f.totalSales DESC LIMIT 1 │ │ │ └─────────────────────────────────────────────────────────────┘ │ │ │ │ ┌─────────────────────────────────────────────────────────────┐ │ │ │ 引擎二共现推荐基于图数据库关系遍历 │ │ │ │ │ │ │ │ 原理从购物车菜品出发沿 OFTEN_BOUGHT_WITH 关系遍历 │ │ │ │ 排序共现次数(coScore) DESC → 菜品销量(baseSales) DESC │ │ │ │ 降级无共现数据时回退到热销推荐 │ │ │ │ │ │ │ │ Cypher │ │ │ │ MATCH (cart:FoodNode)-[r:OFTEN_BOUGHT_WITH]-(rec:FoodNode) │ │ │ │ WHERE cart.fid IN $excludeFids │ │ │ │ AND NOT rec.fid IN $excludeFids │ │ │ │ RETURN rec.fid, rec.fname, rec.totalSales AS baseSales, │ │ │ │ sum(r.count) AS coScore │ │ │ │ ORDER BY coScore DESC, baseSales DESC LIMIT 1 │ │ │ └─────────────────────────────────────────────────────────────┘ │ │ │ │ 输出两个推荐菜品不同引擎产出保证不重复 │ │ ┌─────────────────────────────────────────────────────────────┐ │ │ │ ruleBased: { fname: 蛋炒饭, tip: 搭配主食更美味 } │ │ │ │ coOccurBased: { fname: 酸辣汤, tip: 经常和这些菜一起下单}│ │ │ └─────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────┘3. 图谱数据初始化与同步启动时自动初始化Neo4jDataInitializer项目启动 ↓ 清空 Neo4j 全部节点与关系MATCH (n) DETACH DELETE n ↓ 同步 MySQL 用户表 → MERGE 写入 UserNode ↓ 同步 MySQL 菜品表 → MERGE 写入 FoodNode含 category, spicyLevel, totalSales ↓ 聚合已支付订单 → 构建 ORDERED 关系orderCount, lastOrderTime ↓ 统计菜品共现 → 构建 OFTEN_BOUGHT_WITH 关系count 共现次数 ↓ 图谱就绪推荐服务可用运行时全量同步Neo4jSyncController接口方法说明/sync/neo4j/allPOST全量同步 MySQL 数据至 Neo4j幂等写入/cart-recommend/sync-co-occurrencePOST手动触发重建菜品共现关系4. 三种推荐策略对比维度MySQL 个性化推荐Neo4j 规则推荐Neo4j 共现推荐数据源user_food_preferenceFoodNode (category)OFTEN_BOUGHT_WITH 关系算法核心行为权重累加 偏好分排序品类补缺规则引擎图遍历 共现次数排序输入用户ID购物车菜品列表购物车菜品列表输出4-10 个推荐菜品1 个规则匹配菜品1 个共现匹配菜品适用场景首页个性化推荐购物车搭配推荐购物车搭配推荐优势实时反映用户偏好可解释性强发现隐藏关联技术栈后端技术栈技术版本说明Spring Boot3.2.5核心框架MyBatis-Plus3.5.5ORM 框架Spring Security-安全框架MySQL8.x关系型数据库用户/订单/菜品/偏好Redis-缓存推荐结果 SessionRabbitMQ-消息队列5大业务场景异步解耦Neo4j-图数据库共现关系 购物车推荐Spring Mail-邮件发送支付宝 SDK4.8.73沙箱支付Hutool5.8.27工具类库Knife4j4.4.0API 文档JWT0.12.6Token 认证OpenFeign-服务间调用Caffeine3.1.8本地缓存前端技术栈技术版本说明Vue3.4.27前端框架Vue Router4.3.2路由Pinia2.1.7状态管理Element Plus2.7.6UI 组件库Axios1.7.2HTTP 请求Vite5.2.11构建工具Day.js1.11.11日期处理功能特性用户端用户注册 / 登录Session JWT 认证菜品浏览与分类筛选购物车增删改查购物车智能搭配推荐规则引擎 共现推荐双引擎下单结算支付宝沙箱支付订单状态实时轮询2秒/次支付成功邮件通知个性化菜品推荐基于行为权重的偏好推荐全局热销推荐用于新用户冷启动订单评价系统特性RabbitMQ 全链路异步解耦5 个 Exchange/Queue 覆盖行为采集、邮件通知、订单超时等核心场景订单超时自动取消TTL 死信队列实现 30 分钟未支付自动取消MySQL 行为权重推荐引擎浏览(0.3) → 加购(1.5) → 收藏(3.0) → 下单(8.0) 加权聚合Neo4j 图共现推荐基于用户历史订单构建菜品共现关系实现购物车智能搭配支付兜底机制支付宝回调丢失时主动查询订单状态同步降级容错MQ 不可用时自动降级为同步处理核心业务不受影响Redis 双层缓存推荐结果缓存 Session 持久化雪花算法唯一订单号生成全局异常处理统一错误响应单元测试覆盖45 单元测试用例项目结构take-out/ # 后端项目根目录 ├── src/ │ ├── main/ │ │ ├── java/org/example/ │ │ │ ├── common/ # 通用类 │ │ │ │ ├── context/ # 用户上下文 │ │ │ │ ├── exception/ # 全局异常处理 │ │ │ │ ├── result/ # 响应结果枚举 │ │ │ │ ├── util/ │ │ │ │ │ ├── BehaviorWeight.java # 行为权重常量 │ │ │ │ │ └── SnowflakeIdWorker.java # 雪花ID生成 │ │ │ │ └── R.java # 统一响应封装 │ │ │ ├── config/ # 配置类 │ │ │ │ ├── RabbitMQConfig.java # MQ 5个Exchange/Queue定义 │ │ │ │ ├── RabbitTemplateConfig.java # MQ序列化配置 │ │ │ │ ├── RedisConfig.java # Redis配置 │ │ │ │ ├── SecurityConfig.java # 安全配置 │ │ │ │ └── ... │ │ │ ├── controller/ # 控制层 │ │ │ │ ├── RecommendController.java # MySQL推荐接口 │ │ │ │ ├── CartRecommendController.java # Neo4j购物车推荐 │ │ │ │ ├── BehaviorController.java # 行为上报接口 │ │ │ │ ├── Neo4jSyncController.java # 图谱同步接口 │ │ │ │ ├── OrderController.java # 订单控制器 │ │ │ │ ├── PayController.java # 支付控制器 │ │ │ │ └── ... │ │ │ ├── dto/ # 数据传输对象 │ │ │ │ ├── RecommendFoodVO.java # 推荐菜品VO │ │ │ │ ├── CartRecommendRequest.java # 购物车推荐请求 │ │ │ │ ├── CartRecommendResponse.java # 购物车推荐响应 │ │ │ │ └── ... │ │ │ ├── entity/ # 实体类 │ │ │ │ ├── UserBehaviorLog.java # 行为日志实体 │ │ │ │ ├── UserFoodPreference.java # 用户偏好实体 │ │ │ │ ├── Orders.java / OrderItem.java │ │ │ │ └── ... │ │ │ ├── listener/ # MQ 消费者 │ │ │ │ ├── UserBehaviorConsumer.java # 行为消费→偏好更新 │ │ │ │ ├── OrderPayConsumer.java # 支付成功邮件消费 │ │ │ │ ├── OrderCancelConsumer.java # 超时订单取消消费 │ │ │ │ └── CodeMailConsumer.java # 验证码邮件消费 │ │ │ ├── mapper/ # MyBatis Mapper │ │ │ │ ├── ResFoodMapper.java # 推荐核心SQL │ │ │ │ └── ... │ │ │ ├── mq/ # MQ 消息定义 │ │ │ │ ├── consumer/ │ │ │ │ │ └── UserBehaviorConsumer.java │ │ │ │ └── dto/ │ │ │ │ ├── BehaviorMessage.java # 行为消息 │ │ │ │ ├── OrderPayMessage.java # 支付消息 │ │ │ │ ├── OrderDelayMessage.java # 延迟消息 │ │ │ │ └── CodeMailMessage.java # 验证码消息 │ │ │ ├── service/ # 业务层 │ │ │ │ ├── RecommendService.java # MySQL推荐接口 │ │ │ │ ├── CartRecommendService.java # Neo4j购物车推荐接口 │ │ │ │ ├── BehaviorService.java # 行为采集接口 │ │ │ │ ├── impl/ │ │ │ │ │ ├── RecommendServiceImpl.java # MySQL推荐实现 │ │ │ │ │ ├── CartRecommendServiceImpl.java # Neo4j推荐实现 │ │ │ │ │ ├── BehaviorServiceImpl.java # 行为采集实现 │ │ │ │ │ └── ... │ │ │ │ └── ... │ │ │ ├── takeout/ # Neo4j 专用 │ │ │ │ ├── config/ │ │ │ │ │ └── Neo4jDataInitializer.java # 图谱初始化 │ │ │ │ └── neo4j/ │ │ │ │ ├── entity/ │ │ │ │ │ ├── FoodNode.java # 菜品节点 │ │ │ │ │ ├── UserNode.java # 用户节点 │ │ │ │ │ └── OrderedRelation.java # 下单关系 │ │ │ │ └── repository/ │ │ │ │ ├── FoodNodeRepository.java │ │ │ │ └── UserNodeRepository.java │ │ │ └── TakeOutApplication.java # 启动类 │ │ └── resources/ │ │ ├── application.yml # 主配置含MQ/Neo4j配置 │ │ ├── application-dev.yml # 开发环境配置 │ │ ├── application-prod.yml # 生产环境配置 │ │ └── mapper/ │ │ └── ResFoodMapper.xml # 推荐核心SQL映射 │ └── test/ │ └── java/org/example/ │ ├── service/impl/ │ │ └── MailServiceImplTest.java │ ├── mq/ │ │ └── OrderNotifyProducerTest.java │ └── MailIntegrationTest.java └── pom.xml快速开始环境要求JDK 17Node.js 18MySQL 8.xRedis 6.xRabbitMQ 3.xNeo4j 5.x1. 数据库准备创建数据库并导入表结构CREATE DATABASE IF NOT EXISTS res DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_unicode_ci; USE res; -- 执行建表脚本项目中提供的 SQL 文件核心数据表结构推荐相关-- 用户行为日志表 CREATE TABLE user_behavior_log ( id BIGINT AUTO_INCREMENT PRIMARY KEY, user_id VARCHAR(32) NOT NULL, food_id BIGINT NOT NULL, behavior_type INT NOT NULL, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, INDEX idx_user_food (user_id, food_id) ); -- 用户菜品偏好分表 CREATE TABLE user_food_preference ( id BIGINT AUTO_INCREMENT PRIMARY KEY, user_id VARCHAR(32) NOT NULL, food_id BIGINT NOT NULL, score DECIMAL(10,2) DEFAULT 0, update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, is_deleted TINYINT DEFAULT 0, UNIQUE KEY uk_user_food (user_id, food_id, is_deleted) );2. 配置文件修改src/main/resources/application-dev.ymlspring: datasource: url: jdbc:mysql://localhost:3306/res?useUnicodetruecharacterEncodingutf-8serverTimezoneAsia/Shanghai username: root password: your_password data: redis: host: localhost port: 6379 password: database: 0 rabbitmq: host: 127.0.0.1 port: 5672 username: admin password: 123456 virtual-host: / neo4j: uri: bolt://127.0.0.1:7687 authentication: username: neo4j password: your_neo4j_password mail: host: smtp.163.com port: 465 username: your_email163.com password: your_email_auth_code alipay: app-id: your_alipay_app_id merchant-private-key: your_private_key alipay-public-key: your_public_key notify-url: your_cpolar_domain/pay/notify.action3. 启动后端cd take-out mvn clean install -DskipTests mvn spring-boot:run后端服务启动后访问API 地址http://localhost:8080API 文档http://localhost:8080/doc.html推荐接口GET /recommend/list、GET /recommend/hot购物车推荐POST /cart-recommend/recommend行为上报POST /behavior/add图谱同步POST /sync/neo4j/all4. 启动前端cd take-out-web npm install npm run dev核心业务流程用户行为驱动推荐闭环┌──────────────────────────────────────────────────────────────────────┐ │ 行为驱动推荐闭环 │ ├──────────────────────────────────────────────────────────────────────┤ │ │ │ ① 用户浏览菜品 → 前端上报 behaviorType1(浏览) │ │ ↓ │ │ ② BehaviorController → BehaviorServiceImpl.reportBehavior() │ │ ↓ │ │ ③ 投递 MQ → behavior_exchange → user_behavior_queue │ │ ↓ │ │ ④ UserBehaviorConsumer 消费 │ │ - 写入 user_behavior_log (行为日志) │ │ - 更新 user_food_preference (偏好分 0.3) │ │ - 清除 Redis 推荐缓存 │ │ ↓ │ │ ⑤ 用户请求推荐 → RecommendController.list() │ │ ↓ │ │ ⑥ 缓存未命中 → 查询 MySQL (LEFT JOIN preference 表) │ │ ↓ │ │ ⑦ 返回最新偏好分排序的推荐列表 → 写入缓存 │ │ │ │ 每一次用户行为都会实时更新推荐结果 │ │ │ └──────────────────────────────────────────────────────────────────────┘下单支付全流程用户选菜 → 加入购物车 → 购物车推荐搭配Neo4j 双引擎 ↓ 提交订单 → 投递 MQ 延迟消息30min TTL ↓ 调用支付宝下单接口 → 支付 ↓ 支付宝异步回调 notify.action → 更新订单状态 ↓ 投递 MQ 支付消息 → OrderPayConsumer → 发送支付成功邮件 ↓ 前端轮询订单状态 → 自动更新 ↓ 30分钟内未支付 → 死信队列触发 → OrderCancelConsumer 自动取消邮件通知链路登录/注册 → 投递 login_code_mail 队列 → CodeMailConsumer → 发送验证码邮件 ↓ 支付成功 → 投递 order_pay_queue → OrderPayConsumer → 发送支付成功HTML邮件 ↓ MQ 投递失败 → 降级为同步发送 → 保证邮件必达测试单元测试# 运行所有单元测试 mvn test 仅运行邮件服务测试 mvn test -DtestMailServiceImplTest 仅运行 MQ 生产者测试 mvn test -DtestOrderNotifyProducerTest邮件测试接口接口说明GET /mail/test/config查看邮件服务状态GET /mail/test/simple发送简单文本邮件GET /mail/test/html发送 HTML 邮件GET /mail/test/order发送模拟订单邮件GET /mail/test/realOrder?orderNoxxx发送真实订单邮件GET /mail/test/mq测试 MQ 链路推荐接口测试# 个性化推荐userId 可从响应中获取 curl http://localhost:8080/recommend/list?userId1size4 全局热销推荐 curl http://localhost:8080/recommend/hot?limit10 购物车双引擎推荐 curl -X POST http://localhost:8080/cart-recommend/recommend -H Content-Type: application/json -d {userId:1,cartItems:[{fid:1,num:2},{fid:3,num:1}]} 触发图谱全量同步 curl -X POST http://localhost:8080/sync/neo4j/all 手动重建共现关系 curl -X POST http://localhost:8080/cart-recommend/sync-co-occurrence 上报用户行为异步入MQ curl -X POST http://localhost:8080/behavior/add -H Content-Type: application/json -d {userId:1,foodId:5,behaviorType:4}关键设计说明RabbitMQ 消息可靠性保障机制实现说明发布确认publisher-confirm-type: correlated消息成功到达 Broker 后回调确认消息返回publisher-returns: true消息无法路由时返回生产者自动重队列default-requeue-rejected: false拒绝消息不自动重入队列避免无限循环消费确认acknowledge-mode: auto自动确认简化消费端逻辑TTL 死信延迟队列设置x-message-ttlx-dead-letter-exchange实现订单超时自动取消MySQL 推荐缓存策略缓存 Keyrecommend:v2:food:user:{userId}个性化、recommend:hot热销TTL2 小时推荐数据不需要实时更新缓存更新用户行为上报后自动清除缓存下次请求重新查库缓存保护所有 Redis 操作 try-catch缓存异常不影响主流程Neo4j 推荐降级策略Neo4j 连接失败时CartRecommendServiceImpl返回 null前端不显示推荐窗口共现查询无结果时降级为按品类热销推荐启动时 Neo4j 不可用不影响 MySQL 推荐和其他核心业务支付兜底机制由于支付宝回调可能因网络原因丢失如 cpolar 内网穿透不稳定系统实现了主动兜底逻辑在支付回调接口中下单后立即查询支付宝订单状态在订单状态轮询接口中主动查询支付宝获取订单真实状态若发现已支付立即更新本地订单并触发邮件通知常见问题Q: 启动时 RabbitMQ 连接失败怎么办RabbitMQ 连接失败时系统会自动降级不影响核心业务。但以下功能将不可用异步邮件通知降级为同步发送订单超时自动取消行为异步采集降级为同步处理建议确保 RabbitMQ 服务正常运行检查application.yml和application-dev.yml中的 RabbitMQ 配置或暂时移除spring-boot-starter-amqp依赖Q: Neo4j 连接失败怎么办Neo4j 连接失败时MySQL 推荐/recommend/list、/recommend/hot不受影响购物车推荐/cart-recommend/recommend将返回空数据系统启动时 Neo4j 数据初始化会跳过不阻塞启动Q: 如何初始化 Neo4j 图谱数据有两种方式自动初始化项目启动时Neo4jDataInitializer会自动执行全量同步手动同步调用POST /sync/neo4j/all接口触发全量同步Q: 如何更新菜品共现关系共现关系 (OFTEN_BOUGHT_WITH) 是基于历史订单预计算的静态关系需要手动触发更新调用POST /cart-recommend/sync-co-occurrence接口重建或重新启动项目触发Neo4jDataInitializerQ: 推荐缓存如何清除有三种方式用户行为上报时自动清除对应用户的推荐缓存缓存 2 小时 TTL 到期后自动失效可通过 Redis 命令手动删除recommend:v2:food:user:*项目地址hac88406-gif/Takeout
返回列表