ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

微信小程序+SpringBoot餐厅点餐系统源码解析与实战

微信小程序+SpringBoot餐厅点餐系统源码解析与实战 做点餐类小程序最常见的技术路线就是微信小程序做前端、SpringBoot 做后端接口这轮交付的weixin185餐厅点餐微信小程序springboot工程正是这套组合的完整落地源码包。上一轮交付过的2048-小程序.zip还只是一个单页游戏不能算业务系统这一轮的项目从“用户扫码进店”到“下单支付”跑通了完整的点餐业务闭环。我把它从工程结构、页面流程、后端建模到启动排错完整过了一遍这篇就把源码里值得拆解的部分和实际运行中会踩的坑一次性说清楚。无论你是做课程设计、毕业设计还是准备给中小餐饮门店做一套点餐系统都能在这套工程里找到可直接参考和复用的东西。1. 整套点餐工程的形态前端、后端、数据库是怎么分工的1.1 为什么微信小程序 SpringBoot 会成为默认组合现在做餐厅点餐类的项目微信小程序几乎是必选的前端载体。核心原因不是因为它“新”而是它的使用路径实在太适合餐饮了用户不用下载安装扫一个桌台码或者搜一下小程序就能直接进入菜单页用完关掉下次再来仍然在微信入口里找得到。这个体验比让顾客下载一个原生 App 轻太多也比让顾客打开浏览器输网址更顺。后端选择 SpringBoot 则是开发效率上的考量。点餐业务的接口并不复杂无非是菜品查询、购物车提交、订单创建、订单状态查询这几类SpringBoot 的 starter 机制把这些基础设施全部架好了——内嵌 Tomcat、自动装配数据源、引入 MyBatis-Plus 后连 SQL 都不用手写太多。你只需要把精力放在业务逻辑上而不是纠结配置文件写三小时。整套工程的架构可以概括为三条线小程序端负责界面展示与用户交互所有数据通过 HTTP 请求发送到后端SpringBoot 后端暴露 RESTful 接口处理登录鉴权、菜品数据、订单事务MySQL 负责持久化存储Redis 处理库存扣减和热点数据缓存。熟悉校园食堂订餐系统这类场景的人应该对这个组合有很强的既视感传统食堂高峰期排队取餐效率低点餐小程序把“选菜”环节提前到用户手机上后厨直接按订单出餐前后端解耦明显。这套工程本质上就是把这种业务模型用最稳妥的技术栈落地了一遍。1.2 交付内容与模块边界拿到手解压源码包里面大致包含三块内容内容说明小程序前端工程微信开发者工具可直接导入包含首页菜单、购物车、订单确认、订单列表等页面SpringBoot 后端工程Maven 结构包含实体类、Mapper、Service、Controller 以及配置文件数据库脚本建库建表 SQL 及初始化数据管理员账号、测试菜品都直接写在脚本里从业务模块上看这套工程以“用户点餐闭环”为主线覆盖了用户登录与手机号绑定、菜品分类浏览、菜品加购、订单创建、订单状态流转这几个核心环节。如果你在找带完整后台管理界面的项目可能需要再考虑一下——这套源码的交付重点在用户端点餐与后端接口服务管理端的菜品上下架、订单管理更多是以后端接口形式提供。个人建议是拿到源码后先不要急着改代码按“数据库脚本 → 后端启动 → 小程序导入”的顺序跑通一遍看清每个模块真实的数据流再动手二次开发。这样后面改什么都心里有底。1.3 工程目录和标识“weixin185”到底是什么意思你可能留意到了工程包名前缀带了weixin185很多课程设计和毕业设计出题时都会按编号命名方便区分不同批次的交付内容。之前那一轮交付2048-小程序这一轮是weixin185餐厅点餐编号对应的就是题目编号。这种命名方式在源码分享、作业提交场景里很常见不是代码本身的组成部分二开时完全可以把包名、工程名改成自己的业务标识。后端工程内部是标准的 SpringBoot 分层结构src/main/java ├── controller # 接口层接收前端请求 ├── service # 业务逻辑层下单事务、库存扣减等都在这层 ├── mapper # 数据访问层基于 MyBatis-Plus ├── entity # 数据库实体类 └── config # 配置类如登录拦截器、全局异常处理小程序前端则是典型的原生小程序目录pages下按业务页面划分menu、cart、orderConfirm、orderList、orderDetail等utils目录里放着封装好的 request 请求工具。整体来说目录不算复杂适合拿来做二次开发底子。2. 小程序端的核心页面从选菜到订单数据到底怎么转2.1 用户进店后的完整操作闭环一个用户从打开小程序到完成点餐要经过的路径是首页加载菜品分类 → 点击某个分类浏览菜品 → 点击菜品加入购物车 → 进入购物车调整数量 → 确认订单页填写备注/选择配送或自取 → 提交订单 → 支付 → 订单列表查看状态。这套工程在小程序端把这条链路完整串起来了。首页菜单页通常是左右两栏布局左侧是分类列表右侧是对应分类下的菜品卡片菜品卡片上展示图片、名称、价格、销量和是否售罄。用户点“加入购物车”后底部购物车栏会实时显示已选数量和总金额点击可进入购物车页进行加减操作。这里有个重要的数据流转原则页面之间只传必要的业务参数不传重数据。比如从菜品卡片跳转到订单确认页只需要把购物车数据通过本地存储带过去而不是每次跳转都重新请求接口。这样页面的切换响应会非常快体验上更接近原生 App。2.2 微信小程序登录与手机号获取code 在前端只走了一圈点餐系统里登录是绕不开的环节。这套工程采用的是微信生态的标准登录流程而不是让用户手动输入账号密码。小程序端调用wx.login()获取一个临时 code这个 code 有效期很短把它发给后端接口后后端拿着 code 去微信服务端换openid和session_key。其中openid是用户在当前小程序下的唯一标识后端用它可以判断用户是否已注册并生成自己的登录态 token 返回给前端。前端拿到 token 后存到 storage 里后续所有请求都在请求头带上这个 token后端拦截器据此识别用户身份。手机号获取则是点餐场景里的一个硬需求因为订单通知、取餐提醒通常要发到用户手机号。小程序端不能直接拿到明文手机号需要在页面里放一个button open-typegetPhoneNumber用户点击授权后前端拿到一个手机号临时 code再传给后端。后端用这个 code 调用微信官方接口换取真实手机号然后绑定到当前用户账号上。这里要特别提醒一个点千万别把微信小程序的 AppSecret 写在代码里更不要传到前端工程中。AppSecret 是后端调用微信接口时用的凭证一旦泄露别人就能冒充你的小程序去换用户信息。正确的做法是把配置写在application.yml或环境变量里由后端持有。2.3 菜品规格选择与库存约束餐饮点餐和普通商品加购最大的区别在于“规格”。一道菜可能有大份/小份、辣度选择、加料项这些在页面上通常用单选组或复选组来实现也就是微信小程序里的radio-group、checkbox-group。早期版本的小程序单选控件样式比较有限二开时要注意自定义样式尤其是选中态的颜色和菜品卡片背景色要区分开不然用户在快速加购时容易点错。库存约束这块前端能做的只是展示层面的“售罄置灰”。真实的库存校验必须放到后端做原因是小程序端可以随时被绕过修改请求参数模拟下单。后端在创建订单时需要通过数据库或 Redis 的库存数据校验菜品是否还有余量如果库存不足则返回明确的错误提示例如“菜品已售罄”。前端拿到这个错误提示后在购物车中标记对应菜品引导用户更换或移除。把库存判断放在后端同时用 Redis 扣减库存再配合 MySQL 做最终一致性是这套工程最值得学习的设计思路。后文讲下单接口时会专门展开。2.4 购物车为什么放在本地缓存而不是服务端很多初学者拿到这套工程会疑惑购物车数据怎么不存数据库实际上点餐业务中购物车属于高频临时的会话数据用户加购、减购、清空都在极短时间内发生如果每一步都请求后端更新数据库会产生大量无意义的写入请求压力大且响应慢。把购物车数据放在小程序本地 storage 中前端增删改查零延迟用户结算时一次性把购物车明细提交给后端创建订单。后端收到订单明细后只需做两件事校验菜品当前价格和库存、在事务中扣减库存并写入订单表。这种做法既减少了后端负担也贴合真实点餐场景——购物车本来就是用户自己的草稿箱不需要和后端实时同步。本地缓存有两个细节值得提。第一缓存的数据结构建议用“菜品ID为 key 的对象数组”而不是纯数组因为按 key 增删查重快很多第二金额计算不要依赖本地缓存的单价结算页展示的金额只能作为参考后端创建订单时会根据数据库当前价格重新计算总价。这样即使前端数据被篡改后端也能拦截保证金额不被恶意修改。2.5 下单与订单状态流转用户提交订单后订单会有几个状态待支付、已支付、制作中、待取餐/已完成。这个小程序的订单列表页就是围绕这些状态做的不同状态显示不同的操作按钮——待支付显示“去支付”制作中显示“等待出餐”待取餐显示取餐码。订单状态的更新可以有两种触发方式用户付款后回调更新为已支付商家在管理端操作变更状态。这里要注意状态流转必须是单向的不允许从已完成回退到待支付后端 Service 层要做状态值的校验。很多人在二开时忽略这一点导致订单状态错乱尤其是并发场景下用户和商家同时操作同一条订单时容易出现库存和订单不匹配的情况。3. SpringBoot 后端接口设计、数据库建模和几个关键“为什么”3.1 后端接口总览后端接口大体上围绕两类对象用户和订单。我把工程里的核心接口整理出来方便你对照前端页面去理解方法路径功能POST/api/auth/login用户 code 登录换取 tokenPOST/api/auth/phone绑定用户手机号GET/api/category/list菜品分类列表GET/api/dish/list按分类查询菜品可带上架状态过滤POST/api/order/create创建订单入参为购物车明细和地址备注GET/api/order/list当前用户订单列表GET/api/order/detail订单详情含菜品明细快照接口路径设计上遵循了 REST 的基本规范Controller 层很薄核心逻辑都在 Service 层。这样做的直接好处是后续如果要把接口暴露给管理后台或者新增一个小程序商家版Service 层可以直接复用不需要大改。3.2 订单表为什么要“冗余”菜品快照数据库建模通常是这套工程里最值得研究的部分。菜品模块设计了分类表和菜品表用户模块设计了用户表订单模块分成了订单主表和订单明细表。其中订单明细表除了记录订单ID、菜品ID、数量外还会冗余一份菜品名称和单价进去。为什么要冗余因为菜品价格和名称不是一成不变的。商家今天搞促销把鱼香肉丝从 18 元改成 16 元明天可能又改名。如果订单明细表里只存菜品ID下单后菜品改了价格历史订单再查详情时就会显示新的价格对账和用户投诉都会出问题。冗余快照后订单一旦生成其明细中的价格和名称就固化了之后无论菜品如何变化历史订单都保持原样。这是业务系统设计里很经典的一个取舍。数据库第三范式要求尽量减少冗余但业务场景又要求订单快照不可变两者冲突时通常以业务需求优先。课程设计里如果能把这一点写进设计文档会是很明显的加分项。3.3 下单接口的核心逻辑事务、订单号与库存扣减下单接口是整个后端工程的重头戏。看源码时会发现创建订单的方法上加了Transactional注解。这个注解保证了下单过程要么全部成功要么全部回滚——订单写入失败时库存不能减少库存扣减失败时订单不能写入。这样一个多表操作的整体原子性是点餐系统稳定性的根基。订单号生成也是值得关注的地方。数据库自增ID不适合直接作为对外订单号一是会暴露每日订单量二是有些场景需要提前生成业务流水号。工程里一般会采用“时间戳 随机数 用户标识”的方式生成订单号例如String orderNo ORD System.currentTimeMillis() String.format(%04d, new Random().nextInt(10000));这个方案虽然简单但并发量高时仍可能碰撞更稳妥的是利用 Redis 自增序列生成每日递增编号。二开时如果订单量预期比较大建议把订单号生成逻辑抽成独立的组件用 RedisINCR配合日期前缀。库存扣减的推荐写法也不是直接UPDATE dish SET stock stock - 1 WHERE id ?这么简单而是配合 Redis 做预扣减用户提交订单时先从 Redis 扣减并校验是否成功下单完成后异步把最终库存回写数据库。如果你的课程设计不打算引 Redis也可以先用乐观锁实现在数据库加version字段更新时携带版本号防止并发超卖。3.4 统一返回结构与全局异常处理后端接口的返回结构如果不统一前端联调会非常痛苦。这套工程定义了统一的Result返回体结构大致是code msg data。code 为 200 表示成功其他为业务错误码前端可以根据 code 做统一提示而不是每个接口都单独解析数据格式。配合统一返回结构的还有全局异常处理。SpringBoot 的RestControllerAdvice注解可以把 Service 层抛出的业务异常统一拦截转换成规范化的错误响应。比如库存不足、菜品已下架、token 过期这些情况不用在每个 Controller 里写重复的 try-catch异常处理器会自动接管。这个机制对代码整洁度帮助特别大也是像 MyBatis-Plus 这类框架能把 CRUD 做得如此简洁的原因之一——框架通过自动配置把重复基础设施全部兜住了。4. 前后端联调最容易断的三个环节登录、手机号、订单数据格式4.1 登录链路code 换 token 的完整流程前后端联调时第一个最容易卡住的地方就是登录。前端wx.login()拿到的 code必须被后端用appid secret去请求微信的jscode2session接口才能换取openid。这套工程里后端代码通常长这样String url https://api.weixin.qq.com/sns/jscode2session?appid appid secret secret js_code code grant_typeauthorization_code;这里有个实际的麻烦本地开发时后端机器可能没有被微信服务器信任或者你暂时没有可用的 appid 和 secret。我的习惯是在配置里加一个mock-login开关本地联调时自动用一串固定字符串作为模拟 openid不需要真实请求微信接口。第一次把整套工程跑通时这个开关可以省下大量时间。4.2 手机号获取的两个高频坑手机号获取是另一个联调重灾区。现在推荐的做法仍然是前端用getPhoneNumber组件获取临时 code把 code 传给后端由后端调用微信接口换取真实手机号。第一个坑是 code 的一次性getPhoneNumber返回的 code 只能用一次换到结果后立即失效。如果你在前端调试时重复调用第二次就会报错。第二个坑是旧版手机号解密方式依赖session_key并且受会话有效性影响很多老代码还在用 AES 解密手机号但现在微信已逐步收紧这类接口新开发时优先采用后端请求官方接口换手机号的方式具体接口名和参数以当前官方文档为准不要照抄旧文章里的代码。移动端还有安卓和 iOS 的差异。有些机型在用户拒绝授权后getPhoneNumber的返回码不同前端要对“主动拒绝”和“系统错误”分别提示不能都当成“获取失败”弹窗了事。4.3 token 鉴权与请求头规范用户登录后后端返回的 token 会存在小程序 storage 里。前端封装request工具时需要从 storage 读取 token 并放进请求头wx.request({ url: https://your.domain.com/api/order/list, header: { Authorization: Bearer token } })后端用一个拦截器统一校验 token对/api/auth/login、/api/auth/phone这类无需登录的接口做白名单放行其他接口全部校验。校验不通过返回 401前端拿到 401 应该做统一处理清除本地 token、跳转登录页重新登录。这里建议二开时把 token 过期时间设置为 24 小时并且后端支持刷新机制避免用户点餐到一半突然被踢下线体验特别差。4.4 联调时的高频报错排查表报错现象常见原因解决方法request fail域名未配置或不在合法域名列表或本地未勾选“不校验合法域名”开发工具详情里勾选“不校验合法域名”上线前配置 HTTPS 合法域名404 url not found路径拼写错误或 Controller 没扫描到检查 RequestMapping 拼写确认启动日志中 mapper 扫描路径401token 缺失或过期检查请求头是否带 Authorization后端检查 token 有效期手机号解密失败code 已失效或选用了过时的解密方案确认 code 一次性使用按最新官方接口实现数据库连接失败MySQL 未启动或账号密码配置错误核对 application.yml 数据源配置确认数据库服务运行中联调时我习惯在微信开发者工具的 Network 面板里直接看请求足够了。如果想看更详细的请求内容也可以用 Charles 抓包小程序流量能看到完整的请求头、请求体和响应体排查数据格式问题很方便。5. 拿到源码后从 0 到 1 跑起来以及 3 个高频启动报错5.1 后端环境准备与配置核对先把后端跑起来需要准备的本地环境是 JDK 8 或 JDK 17、Maven、MySQL 和 Redis。如果你的机器上还没有这些先装好再继续。后端工程里需要重点关注application.yml或application.properties配置文件以下几项必须改成你自己的数据库地址、账号、密码Redis 连接信息小程序 appid 和 secret本地模拟登录时可不填但要保持 mock-login 开关开启。数据库脚本导入方式很简单创建一个新的数据库执行工程里的.sql脚本即可。脚本里通常会包含用户表、菜品表、订单表建表语句以及几条测试菜品数据和初始管理员账号。5.2 前端工程导入与参数修改后端启动成功后用微信开发者工具导入小程序前端工程。导入后第一件事是把project.config.json里的 AppID 换成自己的测试号 AppID。没有 AppID 的话开发者工具也支持使用测试号但部分接口如手机号获取依赖真实权限本地跑业务流程时可以先忽略。本地开发时在微信开发者工具的“详情 → 本地设置”里勾选“不校验合法域名、web-view业务域名、TLS 版本以及 HTTPS 证书”这样请求http://localhost:8080或局域网 IP 也不会被拦截。前端工程里如果有写死的接口地址 baseURL需要一并改成你后端实际启动的地址。注意真机预览时localhost指向的是手机本身要改成电脑的局域网 IP比如http://192.168.x.x:8080。5.3 三个高频启动报错版本太高、时区、端口占用第一类报错和 SpringBoot 版本有关。如果你本机的 Maven 默认拉取的是 Spring Boot 3.x而工程基于 Spring Boot 2.x 编写就会出现包名冲突或者自动配置失效的问题最常见的是javax和jakarta命名空间不一致。遇到这种情况不要急着改代码先在pom.xml里固定工程原本使用的 Spring Boot 版本并确保本地 JDK 版本与之匹配。Spring Boot 版本不是越高越好题目的工程依赖什么版本就尽量用对应版本启动否则排除兼容问题就要花掉半天。第二类报错是 MySQL 连接时区问题报错信息类似于The server time zone value Öйú±ê׼ʱ¼ä is unrecognized。这是因为 MySQL 连接串里没有指定 serverTimezone。在数据库 URL 后面加上?serverTimezoneAsia/ShanghaiuseUnicodetruecharacterEncodingutf8即可解决同时注意保持数据库和连接串的字符集一致防止中文乱码。第三类报错是端口占用。默认 8080 端口如果被其他服务占用后端启动会直接失败。两种处理方式改掉后端配置里的端口或者本地停掉占用进程。我建议直接改端口例如 18080顺便把前端 baseURL 同步改掉避免每次启动都被这个报错打断思路。5.4 怎么判断整套系统真的跑通了跑通的标准不是后端控制台没有红色报错而是走完整条业务链路。我会按下面的顺序验证打开小程序首页能看到分类和菜品数据点击菜品加入购物车底部购物车数量和总金额变化正确进入购物车调整数量金额同步变化提交订单后端日志出现订单创建记录数据库订单表新增一条记录在订单列表页能看到刚创建的订单状态为“待支付”。如果这五步都符合预期说明前后端联调已经通了。之后再去做手机号绑定、支付回调这类依赖真实微信能力的环节就不会因为基础链路没通而找不到问题在哪。6. 提审上线前必须处理的事账号认证、支付、隐私协议与扩展方向6.1 账号主体与认证如果你不满足于在开发者工具里自嗨想把这个小程序真正发布到微信生态里第一关就是账号主体和认证。个人主体和企业主体能申请的能力差别很大点餐场景涉及的支付、会员、信息收集等能力企业主体才能完整支持。认证本身需要一定费用而且按年计算这个成本在项目启动前就要想清楚不要做完才发现主体资质不匹配。课程设计或者学习演示用的小程序通常用一个测试号就够了不需要做正式认证。但如果有真实商家准备投入使用建议尽早注册企业主体小程序账号并提前规划好小程序名称——餐厅名称如果被占用后面再改名很麻烦。6.2 微信支付申请与“模拟支付”方案支付是小程序点餐闭环里最敏感也最麻烦的环节。微信支付商户号的申请需要企业资质涉及营业执照、对公账户等一堆材料个人开发者基本走不通这个流程。课程设计场景下工程里通常会预留一个“模拟支付”开关提交订单后不真实调起微信支付而是直接把本地订单状态置为“已支付”然后进入制作中流程。这样能完整演示业务闭环又不依赖真实商户资质。我建议在二开时把支付能力抽象成一个接口正式环境走微信支付回调演示环境走模拟支付。这样以后拿到商户资质只需要替换支付的实现类业务层不用任何改动。6.3 用户隐私保护指引与 HTTPS 合法域名小程序审核最容易被忽略的是用户隐私保护指引。小程序里获取了用户手机号就必须在后台配置隐私保护指引声明收集手机号的目的——比如“用于订单状态通知和取餐提醒”。如果未声明真机调用getPhoneNumber时会直接失败这个坑在开发阶段不明显提审时却会被卡得很死。同时正式环境要求所有请求域名必须是 HTTPS 且在小程序后台完成合法域名配置。HTTP 的本地开发地址无法用于线上版本需要后端部署到带 HTTPS 证书的服务器并在小程序管理后台的“开发管理 → 服务器域名”中添加 request 合法域名。这一步不做上线后小程序里所有请求都发不出去。6.4 从课程设计到真实商用这个工程还能往哪些方向扩展如果你不满足于把作业交掉想把这个餐厅点餐小程序做成真正能用的产品下面几个方向是性价比最高的桌台码点餐每张桌子生成带 scene 参数的专属二维码用户扫码进入小程序时自动带上桌号下单后订单直接关联桌台后厨出餐和前台叫号都更精准取餐叫号大屏后厨或前台放一个电视看板实时滚动展示“制作中”状态的订单出餐后在客户端同步推送取餐通知后厨出餐单给后厨单独做一个简化版界面只显示当前需要制作的菜品和数量按时间倒序排列菜品评价与商家回复点餐闭环完成后增加评价入口商家可以在管理后台回复提升复购率管理后台如果当前只有后端接口没有页面可以用 Vue 写一个后台管理界面构建后把静态文件丢进 SpringBoot 的static目录统一部署一个人运维也方便。这轮的源码工程把点餐核心闭环搭好了接上上面任意一个方向都比从零开始做一个完整系统省太多事。最后聊个我自己的习惯拿到带编号的源码工程我先做的不是急着启动而是把包名、应用名、数据库名这些占位标识统一改掉再把配置里的账号密码换成自己的占位符。这样后面无论是提交作业还是做二次开发都不会出现泄露或命名混乱的隐患。这个餐厅点餐工程最值得保留的设计就是订单快照和库存扣减流程改业务时优先动前端页面后端表结构和事务逻辑建议保持稳定。祝你跑通顺利。
返回列表