昨天有位准备做毕业设计的同学在群里问:SpringBoot和微信小程序到底怎么才能像一套完整项目一样跑起来?他刷到过很多单独讲后端、单独讲前端的教程,但一到真正把它们拼在一起,登录态怎么串、跨域怎么处理、下单时候的金额以谁为准,这些关键点全都不明不白。这个问题很典型,所以我干脆把“springboot餐厅点餐应用微信小程序”这套源码从头拆到尾,把整个点餐链路里那些教程不会明说、却直接决定项目能不能上线的内容,全部摊开讲一遍。
这篇东西不是泛泛介绍“项目有什么功能”,而是站在准备复现、改造、答辩或者接私单的开发者视角,把架构选择、数据库设计、后端接口实现、小程序端状态管理、部署踩坑和扩展方向完整串一遍。无论你是拿它做毕业设计,还是想接一个小餐饮店的数字化单子,这篇文章都可以直接参照着做。
1. 这套源码到底在解决什么:扫码点餐的全链路拆解
1.1 传统点餐的痛点与扫码点餐的体验提升
先说业务背景。传统小餐饮店点餐基本靠服务员手写单子,高峰期一桌催完催另一桌,后厨出单靠喊,结账靠算,漏单、错菜、跑单都是常态。顾客等得急,老板对不上账,这是行业里非常普遍的痛点。
扫码点餐解决的问题很直接:顾客坐下后扫桌台码,在微信小程序里浏览菜品、加购物车、下单支付,订单直接进后厨队列。服务员从“记录员”变成“传菜员”,老板在后台能看到实时的营业数据。这个模式对单桌翻台效率的提升非常明显,尤其是高峰期,顾客边看菜单边点、边吃边加菜,后厨按序出餐,订单流和信息流是同步的。
这套源码正是围绕这个场景设计的:顾客端小程序负责菜单展示、购物车、下单、订单查询;后端负责菜品管理、订单流转、用户身份识别;如果需要商家后台,则承担菜单上下架、桌台管理、订单状态操作。整体就是一个典型的“轻前台、重中台”的小型全栈系统。
1.2 技术选型为什么落在SpringBoot加微信小程序
我拆这类项目时第一步会先问:为什么是SpringBoot,而不是Node、Python,或者小程序云开发?
从实际交付的角度看,SpringBoot有几个优势很难替代。第一是生态成熟,Java在电商、餐饮这类偏传统业务场景里的组件积累太深了,MyBatis、MySQL、Redis、支付对接,哪个环节都有大量现成案例可查。第二是部署形态简单,一个可执行Jar包就能启动,对没有运维能力的小店来说,扔到一台服务器上跑起来就行。第三是后续维护的找人成本低,Java开发者基数大,餐馆老板今天找你做完,三年后找别人接手也容易。
小程序端的选择同样有理由:微信小程序不需要用户安装,扫码即用,支付链路由微信官方账号体系闭环,商家不需要自建收银硬件。相比App,小程序的获客和使用门槛都低得多;相比H5,小程序的流畅度、支付体验和消息触达能力都更好。
这套技术组合,本质上是“用成熟后端兜底业务复杂度,用小程序降低顾客使用门槛”,非常契合中小餐饮店的真实需求。
1.3 从请求到出单:一次完整点餐的链路
我习惯先把一次点餐的完整链路画在脑子里,再去看代码,否则很容易被源码里的类名绕晕。
顾客扫码进入小程序,第一步触发登录:小程序端通过微信登录接口拿到临时凭证code,后端拿code向微信服务端换取用户的openid,并签发一个自定义token返回给前端。后续所有带业务操作的请求,都通过header里的token识别身份。
接着顾客浏览菜品列表,将菜品加入购物车。购物车在前端有本地缓存,在后端也有对应记录,这样即使用户退出重进、换手机,购物车都还在。确认下单时,后端创建订单主表和订单明细表,扣减菜品库存,返回订单号。如果接了微信支付,小程序端调起支付,支付成功回调后,订单状态从待支付变为已支付,同时进入后厨制作队列。
后厨看到订单后按序制作,出餐后由服务员端或商家后台标记为待取餐、已完成,整个链路闭环。你说它复杂吗,业务上不复杂,但要在源码里准确找到每一环的对应实现,需要先有这个整体图景。我下面按数据层、后端、小程序端、部署四个维度逐步展开。
2. 数据库设计是这项目最有价值的一半
2.1 核心表结构与字段设计解读
点餐系统表面上是CRUD,但表设计是否合理,直接决定后面接口好不好写、扩展顺不顺手。我拆这套源码时的核心表大致有这些,也是一份可以直接拿去建库的参考结构。
- 用户表(user):字段包括用户id、openid、昵称、头像、手机号、创建时间。openid是微信生态下的用户唯一标识,必须建唯一索引。注意不要只存微信昵称和头像当用户信息,这两个字段会变,openid才是稳定锚点。
- 菜品分类表(category):字段包括分类id、分类名称、排序值、是否上架。分类不要和菜品绑死在同一个表里,否则后期调整排序、隐藏分类都会很痛苦。
- 菜品表(dish):字段包括菜品id、分类id、菜品名称、图片、价格、库存、单位、描述、是否上架、销量。价格字段在数据库里要用十进制定点数,不能图省事用浮点类型。
- 桌台表(table_info):桌台id、桌台编号、桌台名称、座位数、二维码图片地址、状态。扫码进入时通过桌台号参数绑定当前桌台。
- 购物车表(cart):用户id、菜品id、菜品名称、菜品价格、菜品图片、数量、是否选中。之所以冗余菜品名称和价格,是为了购物车列表展示时不需要反复查菜品表;真正下单时再以菜品表的最新价格重新计算。
- 订单主表(orders):订单id、订单号、用户id、桌台id、订单总金额、实付金额、订单状态、备注、支付方式、支付时间、创建时间、更新时间。订单号要单独生成,不要用自增id直接暴露给用户。
- 订单明细表(order_item):订单id、菜品id、菜品名称、菜品价格、数量、小计。这个表会冗余菜品名称和价格快照,目的后面细说。
- 支付流水表(payment_log):支付单号、订单号、支付金额、支付状态、回调参数。有这张表,对账和退款才有着落。
这套表结构覆盖了一个点餐项目的核心主流程。如果你发现源码里没有支付流水表,也不要意外,很多开源项目的支付回调是预留了接口但没实现完整,真正要接支付时这张表必须补上。
2.2 金额为什么必须用DECIMAL而不是Double
这是我最想强调的一点。餐饮项目的金额计算,一是要精确,二是要和人民币最小单位对齐。用偏底层的话说,二进制浮点数无法精确表示0.1加0.2,你可以在任意一门编程语言的控制台里输入0.1加0.2,多数情况下输出的是0.30000000000000004。这个问题在日常显示里不明显,一旦涉及累加、乘数量、结算比较,误差就会累积放大。
数据库层面,价格字段、金额字段一律用DECIMAL(10,2),Java代码里对应使用BigDecimal,而不是double或float。后端在计算菜品小计、订单总额、优惠金额时,统一走BigDecimal的multiply、add方法,运算顺序也要一致。简单说,double像一把弹性秤,小误差平时看不出来,称得多了就差得离谱;DECIMAL是标准天平,每一分钱都钉死在位置上。
如果有跨语言或者对接第三方支付的情况,金额在传输时建议使用“分”为单位的整数,比如1元传100,这样即使对方系统用的是浮点也不会因为小数位产生误差。很多支付平台的对接文档都明写了这一点,并不是小题大做。
2.3 订单状态机:用枚举思想管理状态流转
订单状态是这类系统的核心枢纽。这套源码里订单状态通常用整型数字存储,比如0待支付、1已支付、2制作中、3待取餐、4已完成、5已取消。整型存储的优点是索引友好、查询快、不依赖字符串拼写,缺点是可读性差,但这可以通过后端枚举和前端文案映射解决。
更重要的是状态流转的心态。你在设计接口时,不能允许“已完成”的订单直接跳到“已支付”,也不允许“已取消”的订单被修改。较好的做法是后端单独建一个状态流转判断,或者使用枚举定义每个状态允许的后续状态。肉眼检查一遍,如果代码里充斥着“想怎么改就怎么改”的裸字段赋值,说明这片区域需要加固。
现实场景里,商家可能点了“已完成”之后发现顾客其实没取餐,需要回滚到“待取餐”;顾客支付后又想加菜,得在原订单上追加明细还是重新开单。这些都要求状态机里预留足够清晰的路由。拆这套源码时,我建议先画一张状态图,把允许的迁移路径列出来,再对照代码找缺口。
2.4 表关系与索引设计心得
表关系本身不复杂:分类和菜品是一对多,订单和订单明细是一对多,用户和订单是一对多。真正容易出现性能问题的是索引设计。
订单表上建议建立组合索引(user_id, create_time),因为用户端最常见的查询是“我的历史订单”,通常按时间倒序;如果是商家后台,则要考虑(status, create_time)组合索引,用来支撑按状态过滤订单。订单明细表上必须建order_id索引,否则按订单查明细时会全表扫描。
还有一个容易忽略的细节:created_at和updated_at这类时间字段,建议让数据库自动维护默认值,INSERT时不需要手动传。多数项目用MySQL的CURRENT_TIMESTAMP就能搞定,这样代码里少一段无意义的赋值,也避免不同服务器时间不一致的问题。
3. SpringBoot后端实现:登录、购物车、下单防并发
3.1 统一返回体与全局异常处理
一个工程化后端项目,接口返回格式必须统一。这套源码里很容易看到类似Result 的结构,包含code、message、data三段。前端不管调哪个接口,只要code等于约定的成功值,就走成功逻辑,否则统一弹错误信息。这样做的好处是前端请求封装可以高度收敛,不需要每个接口单独判断返回结构。
配合统一返回体的,是全局异常处理。SpringBoot里通过@RestControllerAdvice可以拦截所有Controller抛出的异常,将业务异常、参数校验异常、系统异常分别映射到对应的错误码和提示信息。没有这一层的项目,一旦代码里忘了捕获异常,前端拿到的就是一堆栈信息或者默认500页面,体验很糟糕。
我的建议是,拆源码时先找到Result类和全局异常处理器,把它读明白,再去看业务接口。因为所有业务接口都建立在这套约定之上,理解它等于拿到了后端代码的“通用钥匙”。
3.2 微信登录:code换token的完整流程
小程序登录和传统账号密码登录完全不同。传统登录是用户提交用户名密码,后端比对数据库;小程序则是通过微信的开放能力完成身份识别。
整个流程是这样的:小程序端调用微信提供的登录接口拿到一个临时凭证code,这个code有效期很短,且只能用一次。后端收到code后,再向微信服务端发起请求,携带小程序appid、secret和code,换取openid和session_key。openid是用户在当前小程序下的唯一标识,后端拿它去查用户表,查不到就自动注册。随后生成一个自定义token,比如UUID字符串,关联用户id并存放到服务端,设置合理的过期时间,返回给前端。
这里有个关键安全细节:openid和session_key应当只保存在服务端,不要原样返回给前端。前端后续请求都带token,后端根据token解析出用户身份即可。即使token被截获,也不会直接暴露微信侧的核心数据。token过期后前端收到特定错误码,自动重新走一遍登录流程即可。
如果你拆的源码里没有引入Redis,token很可能存在数据库表里,附带过期时间和最后活跃时间,让定时任务清理过期数据。这种实现简单可靠,适合轻量项目;如果担心性能,再考虑换成Redis,但不要一开始就把架构搞复杂了。
3.3 购物车存服务端的取舍
购物车是点餐体验里非常关键的一环。市面上的做法分两类:一类是纯前端存储,另一类是服务端存储。这套源码如果提供了购物车接口,通常是服务端存储,我认为这也是更贴近商业项目的选择。
纯前端存储的优点是后端省事,购物车数据放在小程序本地缓存里,下单时把明细一次性提交给后端。缺点是用户换手机、清理缓存、卸载小程序后购物车直接消失,而且后端无法做“未下单用户”的运营分析。
服务端存储的优点是数据可靠,用户换设备登录后购物车还在;商家可以看到“加购了但没下单”的菜品,为后续营销做铺垫。在这个项目里购物车表建议关联用户id,加唯一索引约束同一用户同一菜品不能重复插入,合并数量即可。容量角度完全不需要Redis,MySQL一张表足够支撑小餐饮店的规模。
3.4 下单时的价格快照与事务边界
下单是整个系统敏感度最高的动作,因为涉及钱和库存。这里要特别讲下价格快照。
顾客浏览菜单时看到的价格是菜品的当前价格,但下单后菜单可能改价。如果订单明细表只存菜品id,等商家改价后,历史订单的金额在统计口径上就乱了:营收报表对不上、顾客维权说不清。所以订单明细表里一定要冗余下单那一刻的菜品名称、单价、图片。这就是快照。它不只是一个字段设计,更是财务和信任层面的保障。
事务边界同样重要。一次下单动作至少包括:扣库存、生成订单主表、生成订单明细、清空购物车。这四件事要么全部成功、要么全部回滚。SpringBoot里直接标记@Transactional即可,底层由Spring统一管理事务提交与回滚。但注意事务别开得过大,比如把远程调用、发送通知也塞进同一个事务里,一旦外部服务慢,数据库连接会被长时间占用,这是新手很容易犯的错。
3.5 库存扣减的乐观锁写法
点餐系统的并发压力大多集中在高峰期的集中下单。比如一家餐厅的招牌菜库存还剩3份,同一秒可能有三四个顾客同时提交订单。如果实现方式是先查库存再判断再更新,就会出现多个请求都读到库存为3,都判定可以下单,最后库存被扣成负数的情况。这在技术上叫“超卖”。
最简单的解决方式是使用条件更新语句,在一条SQL里完成“判断库存足够”和“扣减库存”两个动作。比如执行更新菜品表,将库存字段减去本次购买数量,同时加一个条件要求当前库存大于等于本次购买数量。执行后如果影响行数为1,说明扣减成功;影响行数为0,说明库存不足,回滚整个下单事务。这就是一种典型的乐观锁思路,用数据库自身的条件约束保证并发下的正确性。
对比一下,给代码加synchronized只能保证单实例内的线程安全,如果后端部署了多个实例,锁就失效了;用数据库悲观锁for update则会把行锁持有到事务结束,在高并发下容易阻塞。点餐这种业务,最合适的就是条件更新这种轻量乐观策略,答案在线下消费场景里完全够用。
4. 微信小程序端:从页面骨架到请求封装的实战细节
4.1 页面结构:四个核心页面各司其职
微信小程序端的页面组织方式会直接影响后续维护成本。这套源码的页面结构大体可以归纳为四个核心板块:首页与菜单、购物车、订单相关、个人中心。
- 首页与菜单页:展示分类和菜品。顶部是分类栏,下面是菜品列表,支持按分类切换,菜品卡片上有图片、名称、价格、加入购物车按钮。这里通常还包含桌台参数的落位,扫码进入时要把桌台号带到所有下单请求里。
- 购物车页:展示当前已选菜品、数量、合计金额,支持增减数量、删除、清空,最后进入确认下单流程。
- 订单相关页:包括确认订单页、订单列表页、订单详情页。确认订单页要展示菜品明细、总价、备注输入框、桌台信息;订单列表页按状态分类展示;详情页展示状态时间线和操作按钮。
- 个人中心页:展示用户头像昵称、历史订单入口、联系商家等。
如果小程序端还包含商家服务能力,比如扫码核销、接单处理,则需要额外的页面和身份判断。没有也不要紧,这些可以作为扩展项,后面我会聊到。
4.2 购物车状态放在哪里:globalData与Storage配合
小程序里最容易被新手搞砸的就是跨页面状态的同步。比如在首页把菜品加入购物车,再跳转到购物车页,如果购物车数据只是首页Page里的一个局部变量,那么购物车页根本读不到。
常规方案是组合使用globalData和本地缓存。把购物车数据放进App的globalData里,页面都可以通过getApp()访问;同时每次变更后同步写入wx.setStorageSync,这样即使用户杀掉小程序重启,购物车数据也能恢复。菜单页、购物车页都只依赖同一份数据源,就不会出现两边数据不一致的问题。
在此基础上,购物车角标数字可以自定义tabBar上的badge,或者用页面内自定义组件实现小红点,数据来源同样是购物车总数量。有一点提醒:购物车相关的所有金额展示,统一在数据层完成计算,不要在渲染层用一堆算术表达式拼凑,避免改动口径时到处找代码。
4.3 把wx.request封装成Promise
微信小程序的网络请求接口是回调风格,如果每个页面都直接写success、fail,代码很快就会变成一层套一层的嵌套结构,接口多了以后维护成本直线上升。实际开发中,大家都会把请求封装成Promise,让代码以async/await方式书写。
封装时通常统一做几件事:拼接baseURL,把token放进header,约定业务码处理逻辑,网络错误统一提示。这套源码里的请求封装大概率也是这个思路,你可以顺着这个结构去看具体实现。
我额外要提一个容易被忽略的点:登录态同步问题。小程序冷启动后,多个页面可能同时发请求,而token此时还没拿到。如果不做处理,先发的请求会因为缺少token而报401。正确做法是在请求封装里维护一个登录Promise,未登录时先await登录完成,再发送真正的请求。或者把请求先挂到一个等待队列里,token回来后统一重发。这个细节在我看过的项目里十有八九会被忽略,但它直接影响小程序冷启动的稳定性。
4.4 缓存、图片与首屏体验
点餐小程序的图片量不小,菜品图、分类图、商家图都可能有。小程序代码包有体积限制,图片如果全部塞进代码包里,稍微多一点就超限。更好的方式是把图片放到服务端或云存储,页面里使用网络图片地址加载。
菜单数据相对稳定,可以在小程序端做一层缓存:首次加载后把菜品分类和菜品列表存到本地缓存,并记录缓存时间,比如5分钟内不重新拉取,下拉刷新时强制重新请求。这样顾客再次打开小程序时,菜单可以秒开,体验提升明显。菜品图片建议开启懒加载属性,滚动到可视区域再加载,减少首屏流量消耗和渲染压力。
还有个小建议:如果后端返回的图片地址是相对路径,比如“/upload/xxx.jpg”,一定要和后端配置的静态资源访问前缀拼成完整URL,否则小程序真机上图片会全部加载失败。这个坑很小,但排查起来特别费时间。
5. 部署与联调:从源码到能跑通的完整操作路径
5.1 环境准备清单
拿到源码后第一件事不是急着改代码,而是把环境准备到位。下面是这类型项目常见的一套环境组合,可以作为起步参照。
| 组件 | 推荐版本 | 用途 |
|---|---|---|
| JDK | 17 | Spring Boot 3.x 必须 |
| Maven | 3.8+ | 依赖管理与构建打包 |
| MySQL | 8.x | 数据存储 |
| 微信开发者工具 | 最新稳定版 | 小程序预览与调试 |
| 开发IDE | IDEA 或 VSCode | 前后端读写 |
| 数据库管理工具 | Navicat 或 DBeaver | 建库与数据检查 |
打开源码先确认Spring Boot版本。如果parent依赖是3.x,就必须用JDK17;如果是2.7及以下,JDK8更稳妥。很多环境问题都出在版本错配上,启动报错先别怀疑代码,先检查JDK和Spring Boot版本的匹配关系。
5.2 需要改动的配置项
后端配置集中在application.yml文件里,改三个地方基本就能跑起来。数据源配置,改成你本地MySQL的地址、库名、账号和密码;微信相关配置,将appid和secret替换成自己的小程序凭证;如果有Redis相关配置,启动本地Redis或先把依赖排除掉。
小程序端同样有对应配置:请求的基础路径要指向你本机或服务器的后端地址,替换为自己的Appid。开发阶段后端跑在电脑上,小程序用模拟器调试时可以直接填本地端口;如果用手机真机预览,需要把地址改为电脑的局域网IP,保证手机和电脑在同一网络里。
数据库导入时注意字符集设置为utf8mb4,否则生僻汉字或特殊字符可能出现乱码。这一点对餐饮项目尤其重要,菜品名称里经常出现“炝”“煲”“盅”这类字符。
5.3 最容易翻车的五个坑
我把反复遇到过的坑整理成一张表,方便对照排查。
| 坑 | 现象 | 解决办法 |
|---|---|---|
| 小程序请求后端进不去 | 模拟器正常,真机失败 | 真机要求后端地址是局域网IP或已备案域名,不要用localhost |
| 报错“不在以下合法域名列表中” | 开发时可勾选“不校验合法域名”,上线前必须配置备案域名并启用HTTPS | 微信开发者工具详情里临时跳过校验 |
| 跨域报错 | 使用网页版调试或者接了管理后台时出现 | 后端添加CorsFilter配置允许跨域请求 |
| 价格显示异常 | 金额算错、多出小数尾数 | 检查字段类型和代码逻辑是否使用BigDecimal |
| 菜品图片不显示 | 图片路径404 | 检查后端静态资源映射和小程序端完整URL拼接 |
开发阶段“不校验合法域名”可以让你快速跑通,但它只是调试开关,不是解决方案。真正发布时,服务器域名必须完成备案,且必须走HTTPS,小程序的request、uploadFile等接口都受这个限制约束。
5.4 推荐的联调顺序
联调最忌讳的是前后端同时开工一次性对接,出了问题不知道查哪边。我的习惯是先打通链路,再补细节,顺序如下。
先启动后端,用接口测试工具把菜品列表、菜品详情等只读接口调通,确保数据和字段符合预期。然后启动小程序,先完成最基础的登录流程,这一步通了,说明token机制和全局请求封装没问题。接着做菜单浏览和加入购物车,验证菜品数据能正确展示、购物车状态能跨页同步。最后提交一笔真实订单,重点观察扣库存、订单生成、购物车清空这三件事是否一致。
按这个顺序走,每一阶段的问题都限定在明确范围内。如果第二步登录卡住,先查后端日志,再查小程序请求封装;如果第四步下单金额不对,直接查数据库里的金额字段和后端计算逻辑。排查效率会高很多。
6. 这套源码还能扩展成什么样:私单与毕设的加分方向
6.1 后厨大屏与WebSocket实时推送
很多餐厅实际需要的不是“小程序能点餐”,而是“后厨能实时看到订单”。传统做法是小票打印机,升级做法是做一块后厨大屏。实现方式是在同一个SpringBoot项目里加一个面向后厨的只读订单页面,后端在订单状态变为已支付时通过WebSocket向前端推送一条消息,后厨大屏收到消息后自动刷新列表。这不需要改太多现有代码,只需要在订单状态变化的Service里增加一个消息发布动作。
从学习角度说,这个扩展涉及的WebSocket、消息推送、前后端实时交互,是面试和答辩中很加分的技术点,而且和现有业务结合得很自然,不是生搬硬套。
6.2 小票打印机对接
小票打印机是餐饮私单里几乎绕不开的需求。现在不少小票机支持HTTP接口,后端在订单支付成功后,拼一段格式化文本推送到打印机地址,驱动打印机出单。格式里通常包含桌台号、下单时间、菜品明细、数量、备注、合计金额。
这个扩展的难点不在接口调用,而在拼单的格式化逻辑:模板要足够灵活,能适配不同宽度的小票纸,还要处理特殊字符,比如英文引号、加号、emoji。做私单时,打印机联调最好用商家实际使用的那台设备,不同品牌上的字符渲染存在差异。
6.3 会员积分与营销工具
另一个自然的方向是会员体系。用户下单后按实付金额累积积分,积分可以抵扣下次消费,或者兑换指定菜品。落地上需要增加用户积分字段、积分流水表,在下单成功事务里写积分流水,并在结算时增加积分抵扣计算。营销方面还可以加上优惠券:后台发券、用户领券、下单时校验并核销。
这些功能都是在现有订单和用户模型上的增量开发,不会动到核心主流程。但要注意,只要涉及抵扣和优惠,金额计算就必须纳入BigDecimal的统一口径,否则各种满减、折扣叠加起来非常容易出错。
6.4 多门店与桌台码扩展
如果小店做成了连锁,这套结构也能扩展成多门店版本。思路是给菜品、桌台、订单都增加一个门店维度,顾客扫码时根据二维码参数确定进入哪家门店,后端根据门店id隔离数据。小程序端首页要支持选择门店,或者直接由桌台码绑定门店并锁定。
这个扩展有一个容易被忽略的点:不同门店的菜品、库存、价格很可能不一致,所以商品表要增加门店id字段,分类也可能需要区分总店统一管理和门店自定义。读写接口都要增加门店参数校验,否则容易出现A店订单落进B店的逻辑错误。扩展能力的大小,其实从最开始的表结构设计就已经决定了,这也是我强调数据库设计重要的原因。
五、这套源码对新手最大的价值,其实不在于它能“直接跑起来”,而在于它把小程序、SpringBoot、MySQL三端串成了一条完整的业务闭环。拆的时候不要只看单点技术,要顺着订单这条主线走一遍,从扫码登录、加购、下单、支付回调到订单状态流转,你会发现每一个环节都藏着一个前人踩过的坑。尤其是金额精度、库存并发、登录态同步这三个点,在任何用得上这套架构的项目里都会反复出现。把这三个点吃透,再往里面加会员、打印机、多门店这些扩展,都是顺手的事。如果你正在拿它做毕业设计,答辩时能把这些“为什么这样设计”讲清楚,比单纯展示能跑通要打动人得多。