ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

微信小程序+Java+MySQL餐饮外卖系统:毕业设计项目从跑通到答辩全攻略

2026/9/1 2:37:23 拓冰建站 浏览量
微信小程序+Java+MySQL餐饮外卖系统:毕业设计项目从跑通到答辩全攻略 简介这是一套面向计算机专业本科生的微信小程序毕业设计实战资源聚焦餐饮外卖业务场景采用Java后端微信小程序前端的B/S架构完整覆盖从需求分析、系统开发到部署演示的全流程。资源包共2166个文件包含211个Java核心业务类、256个JS交互逻辑、462个HTML页面模板、314个CSS样式文件及265个WXML/WXSS小程序组件辅以MySQL数据库脚本3个SQL文件与详细说明文档整体压缩包大小为23.18MB。已有832人学习下载适用于毕业设计选题参考、全栈开发能力训练及小程序Java技术栈整合实践。读者可直接运行演示视频中的全部功能小程序端支持菜单分类浏览、购物车管理与在线支付后台提供商品、订单、用户及营收数据的可视化管理且源码中大量使用MyBatis自动生成的Example类如OrderMainExample、EvaluateExample等便于理解DAO层规范设计与CRUD扩展逻辑。 每年毕业设计季我都会被问到同一种问题“学长/学姐传给我一个压缩包里面写着微信小程序、餐饮外卖系统、Java还有数据库和演示视频但我根本不知道从哪开始看。”这种包确实常见标题格式通常就是“(微信小程序毕业设计)餐饮外卖系统(java)cx1(源码说明数据库演示视频).zip”。作为帮人调试过几十个类似项目的人我想认真聊聊拿到这种毕设项目包后怎么在最短时间内跑通、看懂、讲清楚。很多人拿到包的第一反应是解压然后打开 IDEA接着就卡在“先运行哪个文件”上。折腾两三天连个登录页面都看不到。其实这类微信小程序 Java MySQL 的外卖系统结构套路非常固定。源码是骨架数据库是血液演示视频是效果参考说明文档是答辩的命根子。下面我就从解压开始一步步拆。1. 解压前先看懂结构项目包里的四样东西分别是什么1.1 “源码、说明、数据库、演示视频”各自的定位压缩包名字里已经写清楚了四样东西源码、说明、数据库、演示视频。很多人直接忽略上来就开 IDEA这其实是最大的错误。先花 10 分钟把目录结构搞清楚后面能省一下午。源码目录一般会包含两个部分小程序端通常叫miniprogram、wxml或uniapp也可能是pages加app.js这种典型的小程序项目结构。Java 后端典型 Maven 工程包含pom.xml、src/main/java、src/main/resources下的application.yml或application.properties。数据库脚本就是一个.sql文件里面是建库、建表和初始化数据的语句。演示视频一般是一段录屏演示“用户点餐—商家接单—配送完成”这条主流程。说明文档则是配合论文用的可能叫“需求分析.docx”“设计文档.md”之类。这些小文件的用途完全不同源码决定功能数据库决定跑起来有没有数据演示视频是你要复现的目标说明文档是你答辩时要讲的东西。所以第一步不是运行而是把四个部分都定位出来。1.2 判断是前后端分离还是老式服务端渲染现在 90% 以上的 Java 小程序毕设项目都是前后端分离小程序发 HTTP 请求Java 后端返回 JSON 数据后端再去读写 MySQL。判断方式很简单看后端代码里有没有controller、service、mapper/dao这类包名有就是接口型项目。再看小程序端代码里有没有wx.requesturl 指向http://localhost:8080或http://192.168.x.x:8080说明确实是前后端通过接口联调。这类项目的好处是职责清晰小程序管页面Java 管业务MySQL 管数据。坏处是环境配置点比较多任何一个环节断了页面就白屏。所以我在下文把整个冷启动过程拆成了几个固定检查点——你照着做就行。1.3 外卖系统的三类角色与业务闭环不管你手里是完整版还是简化版餐饮外卖系统基本都围绕三个角色用户打开小程序浏览分类、选菜品、加购物车、下单、看订单状态、确认收货、评价。商家/管理员在管理端维护菜品分类、菜品信息处理订单更新出餐和配送状态。配送员很多毕设把配送角色合并到管理员端里由管理员模拟接单、点击“开始配送”。整条业务闭环是用户下单 → 商家接单 → 出餐/配送 → 用户确认完成 → 发表评价。看懂这个闭环很重要因为数据库里的订单状态字段、后端的事务方法、演示视频的录制顺序全都在围绕这条线设计。后面改代码时别只看单个页面要把它放到这个闭环里理解。2. 冷启动跑通从空数据库到小程序首页出菜2.1 后端启动前必须确认的四件事很多人一上来就双击运行报错后一脸懵。我建议先确认四件事按顺序排查基本能解决 80% 的启动问题。第一JDK 版本。这类毕设项目绝大多数是 JDK 8或者 JDK 11。如果你的电脑装的是 JDK 17 甚至更高pom.xml里的编译插件和 Spring Boot 版本很可能不兼容启动直接报错“UnsupportedClassVersionError”或各种依赖冲突。先看pom.xml里的spring-boot-starter-parent版本再决定要不要降级 JDK。第二Maven 依赖下载。首次加载会从中央仓库下载大量依赖网络不好时卡半天。建议在 Maven 的settings.xml里配置阿里云镜像下载速度会快很多。第三MySQL 环境。确认 MySQL 服务已经启动5.7 或 8.0 都行但要注意驱动配置。老项目用com.mysql.jdbc.Driver新项目用com.mysql.cj.jdbc.Driver搞错了启动时报ClassNotFoundException。第四配置文件。打开application.yml或application.properties把数据库地址、账号、密码改成你自己的。最常见的配置长这样server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/food_delivery?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver很多同学在 java 环境变量配置那一步就卡住了其实JAVA_HOME配好PATH里加上%JAVA_HOME%\bin命令行里执行java -version能输出版本号基本就没问题。2.2 数据库导入最容易踩的三个坑数据库脚本导入不成功是冷启动失败的第二大头。我见过的最离谱的情况是学生只建了个空库忘了执行.sql文件然后盯着“菜品列表为空”的页面发呆。第一次导入建议在 Navicat 里先手动新建一个数据库名字跟配置文件里一致然后右键“运行 SQL 文件”选择.sql脚本。不要在一个已经存在的数据库里直接执行避免表名冲突。如果.sql文件开头有CREATE DATABASE语句用命令行导入更稳mysql -u root -p food_delivery.sql导入完成后重点检查三张表user、dish、orders。看有没有数据表结构对不对。再回过去看配置文件里的数据库名是不是跟.sql里创建的库名一致。数据库名在 Linux 下区分大小写Windows 下不区分但建议统一用小写省得部署到服务器时踩坑。另外注意字符集。外卖系统涉及中文菜品名、备注信息建议库和表都用utf8mb4不要用utf8否则表情符号或部分生僻字会变成问号。2.3 微信开发者工具导入小程序端的正确姿势后端启动成功后浏览器访问接口能返回 JSON说明接口层没问题。接下来打开微信开发者工具导入小程序目录——注意选择miniprogram文件夹或包含app.json的那个目录而不是整个后端工程。AppID 可以用测试号。如果用别人的 AppID后续发布会有问题本地调试一般没问题但我还是建议换成自己的。关键步骤是在“详情 → 本地设置”里勾选“不校验合法域名、web-view业务域名、TLS 版本以及 HTTPS 证书”。不勾选的话小程序请求http://localhost或http://192.168.x.x会被拦截Console 里报url not in domain list。接口连不通时优先看两个地方后端端口是不是 8080小程序代码里wx.request的 url 端口是不是一致。真机调试时localhost指向手机自己所以要用电脑的局域网 IP并且手机和电脑连同一个 WiFi。在开发者工具的 Console 和 Network 面板能看到请求状态和返回结果。如果Network显示请求失败按“后端是否启动 → 数据库是否连接 → url 是否写对 → 域名校验是否关闭”的顺序排查。这一套走下来正常半小时内就能看到“菜品列表加载出来”的首页。3. 数据模型背后九张核心表与订单状态机3.1 九张核心表的结构与职责外卖系统虽然功能看着多但表结构翻来覆去就那几张。我把最常见的九张核心表梳理成一张表你自己对号入座表名中文含义核心字段说明user用户表id, openid, nickname, avatar, phoneopenid 是微信侧的全局唯一标识address收货地址表id, user_id, name, phone, detail下单时生成地址快照category菜品分类表id, name, sort, status控制首页分类展示顺序dish菜品表id, category_id, name, image, price, stock, salesprice 必须用 decimalcart购物车表id, user_id, dish_id, count, selected可用 userId 区分用户orders订单主表id, order_no, user_id, address_snapshot, total_amount, status, remark一条订单对应多个明细order_detail订单明细表id, order_id, dish_id, dish_name_snapshot, price_snapshot, count冗余菜品名称和价格快照delivery配送表id, order_id, courier_name, status, delivery_fee可与订单表合并看项目版本comment评价表id, order_id, user_id, rating, content, create_time关联订单而非菜品这里有两个非常关键的设计点很多人答辩时讲不清楚。第一orders表存的是address_snapshot不是address_id。因为订单是历史事实用户后来改地址不能影响已经下单的记录。所以下单时把完整地址字符串存进订单表。第二order_detail表存了dish_name_snapshot和price_snapshot。商家后面改菜品名、改价格历史订单里的明细不能跟着变。这是电商系统里典型的“快照模式”讲出来很加分。3.2 订单状态流转用状态码而不是字符串订单状态是整个系统的核心脉博。通常用 int 类型状态码0 待支付1 待接单已支付2 制作中/待配送3 配送中4 已完成5 已取消6 退款中7 已退款为什么不用字符串“待支付”直接存数据库因为 int 占用小、判断高效前端通过字典映射显示成“待支付”等文字。而且状态码方便扩展以后想加“超时未支付自动关闭”只需加一个状态值。更重要的是一套状态机校验逻辑后端在更新状态时不能允许任意跳转。比如状态 4已完成不能直接改回 3配送中状态 0待支付也不能直接跳到 3配送中。常见做法是在 Service 层写一个状态流转校验private static final MapInteger, ListInteger STATUS_TRANSITIONS new HashMap(); static { STATUS_TRANSITIONS.put(0, Arrays.asList(1, 5)); // 待支付 - 待接单、取消 STATUS_TRANSITIONS.put(1, Arrays.asList(2, 5)); // 待接单 - 制作中、取消 STATUS_TRANSITIONS.put(2, Arrays.asList(3)); // 制作中 - 配送中 STATUS_TRANSITIONS.put(3, Arrays.asList(4)); // 配送中 - 已完成 } private void checkStatusTransition(int oldStatus, int newStatus) { ListInteger allowed STATUS_TRANSITIONS.get(oldStatus); if (allowed null || !allowed.contains(newStatus)) { throw new RuntimeException(非法状态流转); } }这段代码在答辩时直接背下来老师追问也能答得上来。3.3 字段设计容易忽略的边界情况很多项目跑起来没问题但一深究全是坑。我总结几个典型的字段设计问题。金额字段必须用decimal(10,2)不能用float或double。二进制浮点数的精度问题会导致“0.1 0.2 0.30000000000000004”金额这种敏感字段绝对不能出现这种问题。用户唯一标识用openid不要用数据库自增 id。微信登录后返回的 openid 才是用户在小程序侧的身份证。如果项目里用自增 id 跟微信侧数据做对应以后换用户或合并数据会非常痛苦。逻辑删除。菜品表、分类表建议加deleted字段默认 0删除时改成 1。因为订单明细关联了菜品历史数据物理删除菜品会导致关联信息丢失到时候查历史订单就变成空壳了。时间字段。create_time设置默认CURRENT_TIMESTAMPupdate_time在更新时自动刷新。这样代码里就不用每次手动setCreateTime(new Date())简单又不容易漏。订单号不要用自增 id。自增 id 会暴露订单量而且多表联调时不方便。常见的做法是yyyyMMddHHmmss 随机数既保证可读性又能减小碰撞概率。4. Java 后端三个关键链路4.1 微信登录code 换取 openid 的完整流程小程序登录跟传统账号密码登录不太一样。整个流程分五步小程序端调用wx.login()获取一个临时code。小程序通过wx.request把code传给后端。后端拿着codeappidsecret请求微信的code2Session接口拿到openid和session_key。后端查user表如果 openid 不存在就创建新用户。生成自定义 tokenJWT 或 UUID返回给小程序后续请求通过请求头Authorization携带。后端核心逻辑大致如下public LoginResult wxLogin(String code) { String url https://api.weixin.qq.com/sns/jscode2session?appid appid secret secret js_code code grant_typeauthorization_code; String response restTemplate.getForObject(url, String.class); JSONObject json JSON.parseObject(response); String openid json.getString(openid); User user userMapper.selectByOpenid(openid); if (user null) { user new User(); user.setOpenid(openid); userMapper.insert(user); } String token UUID.randomUUID().toString().replace(-, ); redisTemplate.opsForValue().set(token: token, user.getId().toString()); return new LoginResult(token, user); }有几个注意点appid和secret一定要放配置文件不要硬编码在代码里更不要写在小程序前端。code只能用一次所以后端接口要在有效期内及时处理。如果毕设不打算对接真实微信登录用 mock 方式直接生成用户也行但说明书里要写清楚答辩时也别含糊其辞。4.2 购物车存前端还是后端两种方案的取舍购物车是一个典型的争议点。存前端storage简单存后端表更体现能力。前端storage方案用户加购、修改数量、删除都直接操作本地缓存。优点是响应快、后端代码少适合只讲前端效果的演示。缺点很明显——换设备数据丢失无法在后端做优惠计算、限购校验。后端cart表方案每次操作购物车都调接口后端通过user_id查表。优点是数据持久化换设备不丢还能在提交订单时统一做库存校验。缺点是接口多、事务复杂。我的建议是毕设项目尽量选后端方案。一方面答辩时老师爱问“购物车存哪了”后端方案有东西可讲另一方面它让购物车、订单、库存这条链路串起来技术深度明显高一些。4.3 提交订单的事务边界与库存扣减顺序下单是外卖系统里最核心、最考验逻辑的操作。它同时涉及多个表创建订单主表、插入订单明细、清空购物车、扣减菜品库存。任何一个环节失败都不能留下半截数据。所以这个接口必须加事务而且类型要选对。Spring 的Transactional默认只回滚RuntimeException如果在 try-catch 里把异常吞了事务不会回滚。正确做法是用rollbackFor Exception.classTransactional(rollbackFor Exception.class) public OrderDTO createOrder(OrderDTO dto) { // 1. 校验用户、地址、菜品状态 // 2. 计算订单总金额以数据库价格为准不能信任前端传的金额 // 3. 扣减库存更新菜品销量 // 4. 插入 orders 主表 // 5. 批量插入 order_detail 明细表 // 6. 删除该用户的购物车记录 // 7. 返回订单号 }顺序上有个小技巧先扣库存再生成订单。如果顺序反过来订单生成了但库存不足事务回滚也能保证数据一致但逻辑上容易遗漏。先扣库存还能提前暴露问题减少无效订单量。库存扣减这一步是并发场景下最容易出 bug 的地方。单纯的“先查库存够再扣”在并发下会超卖。用乐观锁思路一句话就能搞定UPDATE dish SET stock stock - #{count} WHERE id #{id} AND stock #{count}受影响行数为 1 说明扣减成功为 0 说明库存不足直接抛出异常事务回滚。这个方法不需要引入额外的锁机制简单好用已经在生产环境里验证过无数次。如果不加事务最常见的现象就是订单主表有记录但点进去明细是空的或者提示“下单失败”但库存已经被扣了。这些都是典型的脏数据问题在答辩演示时非常致命。5. 演示视频、说明文档和答辩把别人的代码讲成自己的5.1 演示视频怎么录才加分很多人录演示视频就是把界面从头到尾点一遍全程沉默像在刷手机。这种视频别说老师你自己看一遍都困。正确方法是按业务故事线录制让人能看懂“这个系统在解决什么问题”。推荐顺序打开小程序完成登录/授权。浏览首页分类和菜品列表。挑选 2-3 个菜品加入购物车。进入购物车修改数量提交订单。切换到管理端商家接单、点击出餐。回到用户端看到订单状态变成“配送中”。模拟配送完成用户确认收货并发表评价。整个流程控制在 5 到 8 分钟。关键操作可以放大屏幕重要的接口返回结果用文字标注一下。录制前把数据库重置到初始状态别让上一轮测试产生的脏数据出现在演示里。5.2 说明文档改造补齐需求分析、E-R 图和接口设计压缩包里的说明文档质量参差不齐但无论质量如何你都必须自己读懂再改写。直接照搬答辩时老师问两句就露馅。建议在文档里补齐以下内容需求分析用文字加用例图描述三类角色分别能做什么。数据库设计画出 E-R 图把九张表的核心字段写清楚每个字段解释一句为什么这么设计。接口设计列出核心接口的表格包含路径、方法、请求参数、返回结果。运行说明从导入数据库、配置后端到小程序预览的完整步骤写给你同组的同学看确保按文档能复现。关键逻辑说明订单状态机、下单事务、微信登录流程这些是展示技术深度的重点。文档和代码不一致是答辩时最容易暴露的问题。如果文档里写着“支持微信支付”但代码里只是payment_status 1的模拟支付老师追问时你就得解释清楚。我的建议是在文档里明确写“本系统实现了模拟支付流程真实支付需要接入微信商户平台”这样反而显得严谨。5.3 答辩现场的高频追问与应答思路根据我带过的学生反馈外卖系统答辩时这几个问题被问得最多。“为什么选微信小程序而不是 App”— 可以回答外卖属于高频、轻量、用完即走的场景小程序免安装天然和微信生态打通用户从分享链接到下单的路径更短开发和审核成本也比原生 App 低。“订单状态是怎么流转的”— 这是送分题。把状态码和允许流转的路径画出来讲清楚从待支付到已完成经历了哪些步骤哪些状态允许取消、哪些状态不能跳转。“购物车数据存在哪里”— 如果项目用的是后端表方案直接说购物车由后端cart表持久化通过user_id关联用户这样换设备不丢提交订单时还能统一校验。如果用的是前端 storage 方案也别慌承认取舍说清楚这么做的好处是实现轻量、响应快后续可以扩展。“如果并发下单库存怎么保证”— 讲乐观锁那条 SQL 就够用了。重点说明UPDATE ... WHERE stock count通过数据库行锁天然避免了超卖不需要额外引入 Redis 分布式锁。“如果要上线你最想改进什么”— 这是一个展示思考深度的机会。可以回答接入真实微信支付、增加实时配送位置跟踪、接入地图选点、增加优惠券和会员体系、管理端增加数据统计报表。我个人的体会是答辩考察的其实不是代码本身而是你对自己项目的理解程度。能独立解释清楚表结构、状态机和事务逻辑的人哪怕项目简单一点老师也不会为难。反过来代码功能再多你含含糊糊说不出来龙去脉反而容易被抓住漏洞追问。所以拿到这种餐饮外卖系统压缩包第一要务不是改花活而是把下面这个闭环完全走一遍从数据库表到接口从接口到页面从下单到订单状态更新每一环都亲手验证过你才真正成为这个项目的作者。本文还有配套的精品资源点击获取