☰
微信小程序+SpringBoot奶茶点餐系统毕业设计实战
2026/10/27 15:13:08 网站建设 项目流程

简介:这是一套面向计算机专业本科生的毕业设计级微信小程序实战项目,聚焦奶茶店自助点餐场景,解决传统APP安装门槛高、用户留存低的问题,助力开发者掌握小程序前端+SpringBoot后端+MySQL数据库的全栈开发能力。资源包共774个文件,40.2MB,涵盖131个Vue组件(用于管理后台界面)、114个Java后端服务类(含Controller/Service/Entity层)、125张PNG/WebP图片与162个SVG图标(支撑小程序UI)、66个JS/WXML/WXSS文件(小程序端逻辑与样式),以及SQL建表脚本、开题报告、完整毕业论文和3段MP4演示视频。已有374人学习下载,内容结构完整:含可一键运行的bat脚本(install/run/build)、带注释的SpringBoot配置(yml/properties)、模块化的小程序页面目录及后台管理功能源码,特别适合课程设计参考、毕设选题复用或全栈技术整合训练。

1. 奶茶店自助点餐小程序:不是Demo,是能跑通「下单→支付→后厨接单→状态同步」全链路的毕业设计实战包

你手头那份写着“毕业设计”的压缩包,大概率不是拼凑的静态页面——它真能扫码进店、选珍珠波霸、加冰少糖、微信支付成功、厨房小票机自动吐单、店员在后台看到“订单号#20240517-083”正等待制作。这不是PPT里的流程图,而是基于微信小程序原生框架 + SpringBoot 2.7.x(非SpringBoot 3.x)+ MySQL 5.7 实打实跑起来的一套闭环系统。它解决的不是“如何写Hello World”,而是毕业答辩时评委最常问的三个问题:用户怎么登录?订单怎么不丢?数据怎么不乱?整套资源里,源码含完整前后端工程结构、开题报告明确写了“基于微信开放能力实现手机号一键授权”、论文里附了ER图与接口时序图、视频演示覆盖从首页滑动到支付回调再到管理端订单筛选的全过程。适合正在赶毕设 deadline 的计算机/软件工程本科生,也适合想快速复现一个“轻量级本地生活SaaS雏形”的初阶全栈开发者——它不追求高并发,但每一步都踩在微信生态和SpringBoot工程规范的边界上。


2. 技术选型为什么是微信小程序 + SpringBoot + MySQL:避开uniapp和Vue的典型误判

2.1 微信小程序原生开发:不是“不能用Vue”,而是“不该用Vue”

很多同学看到“微信小程序”第一反应是uniapp或Taro,但本项目坚持使用微信原生框架(WXML/WXSS/JS),原因很实际:

  • 登录链路极简:直接调用wx.login()+wx.getPhoneNumber()获取加密手机号,后端用WXBizDataCrypt解密,全程无第三方SDK依赖;
  • 支付对接零胶水:wx.requestPayment()直接传prepay_id,SpringBoot侧只需调用微信统一下单API返回签名参数,不涉及H5跳转或OAuth2重定向;
  • 性能可控:首页商品列表用wx:for渲染,配合wx:if控制规格弹窗显隐,首屏加载<1.2s(实测iPhone XR),而uniapp打包后体积多出1.8MB,对奶茶店老板用的千元机不友好。

提示:项目中所有WXML组件均未使用自定义组件(如<van-button>),全部基于原生<button>+<view>构建,确保微信开发者工具基础库2.20.0+即可运行,避免因基础库版本差异导致bindtap失效等玄学问题。

2.2 SpringBoot 2.7.x:为什么不是3.x或2.6.x?

项目后端锁定SpringBoot 2.7.18(2023年10月GA版本),这是关键决策:

  • MyBatis-Plus兼容性:本项目用MyBatis-Plus 3.5.3.1,若升级SpringBoot 3.x需同步升级MyBatis-Plus 4.x,而4.x废弃了@TableId(type = IdType.AUTO)的自动递增逻辑,需手动改@TableId(type = IdType.INPUT)并维护ID生成器——但奶茶店订单ID必须全局唯一且可读(如DD202405170001),原方案用MySQLAUTO_INCREMENT+ 业务层拼接更稳妥;
  • 微信支付SDK适配:官方weixin-java-pay4.4.0仅支持SpringBoot 2.7.x,若强行用2.6.x会触发RestTemplateBean注入冲突(No qualifying bean of type 'org.springframework.web.client.RestTemplate');
  • JDK版本锁死:SpringBoot 2.7.x要求JDK 8u201+或JDK 11,而学校服务器普遍为CentOS 7 + JDK 8u191,无需额外升级环境。

2.3 MySQL 5.7:为什么不用8.0?

数据库选用MySQL 5.7.44(Windows版安装包已附在资源内),而非8.0,理由直击痛点:

  • 全文索引分词兼容:商品搜索用MATCH AGAINST,5.7默认使用ngram解析器,对“珍珠奶茶”“芋圆波霸”等中文词切分稳定;8.0虽支持innodb_ft_parser,但需额外配置ft_min_word_len=2且易受停用词表干扰;
  • 事务隔离级别明确:项目订单创建用REPEATABLE READ,配合SELECT ... FOR UPDATE锁定库存,5.7的间隙锁(Gap Lock)行为与论文描述完全一致;8.0默认READ COMMITTED,需显式SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ,增加部署复杂度;
  • Navicat连接零配置:5.7默认mysql_native_password认证插件,学生用Navicat 15直连无需改caching_sha2_password——这点省下3小时调试时间。

3. 源码结构拆解:从2048-小程序.zip到可运行的三步落地

3.1 小程序端:miniprogram/目录下的真实工程逻辑

解压2048-小程序.zip后,核心目录结构如下:

miniprogram/ ├── app.js # 全局App实例,含onLaunch中检查登录态 ├── app.json # 页面路径、tabBar、网络超时配置("networkTimeout": {"request": 10000}) ├── project.config.json # 开发者工具配置,含appid(需替换为你的) ├── pages/ │ ├── index/ # 首页:商品分类+瀑布流列表 │ │ ├── index.wxml # 商品卡片含<checkbox-group>控制规格选择 │ │ └── index.js # onPullDownRefresh触发商品刷新,调用/api/goods/list │ ├── order/ # 订单页:地址选择+支付按钮 │ │ └── order.js # wx.requestPayment()前校验库存,失败则toast提示"库存不足" │ └── admin/ # 管理端(需扫码进入):订单列表+状态筛选 └── utils/ └── request.js # 封装wx.request,自动添加token(从wx.getStorageSync('token')读取)

关键代码块(pages/order/order.js支付逻辑):

// 调用微信支付前,先校验库存 wx.request({ url: 'https://your-domain.com/api/order/check-stock', method: 'POST', data: { goodsId: this.data.goodsId, count: this.data.count }, success: (res) => { if (res.data.code === 200) { // 库存充足,发起支付 wx.request({ url: 'https://your-domain.com/api/order/create', method: 'POST', data: { goodsId: this.data.goodsId, count: this.data.count }, success: (orderRes) => { if (orderRes.data.code === 200) { const payParams = orderRes.data.data; // 后端返回的timeStamp, nonceStr, package, signType, paySign wx.requestPayment({ timeStamp: payParams.timeStamp, nonceStr: payParams.nonceStr, package: payParams.package, signType: payParams.signType, paySign: payParams.paySign, success: () => wx.showToast({ title: '支付成功', icon: 'success' }), fail: (err) => wx.showToast({ title: '支付失败', icon: 'none' }) }); } } }); } else { wx.showToast({ title: res.data.msg || '库存不足', icon: 'none' }); } } });

逻辑说明:此处采用“前端二次校验”而非纯后端校验,是因为微信支付回调有延迟(平均1.2s),若仅靠后端扣减库存,用户可能重复点击支付按钮导致超卖。前端校验虽非强一致,但配合后端SELECT ... FOR UPDATE已足够应对日均500单的奶茶店场景。

3.2 SpringBoot后端:springboot-server/中的核心模块

后端Maven结构清晰,pom.xml关键依赖:

<dependencies> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.3.1</version> <!-- 锁定版本,避免与SpringBoot 2.7.x冲突 --> </dependency> <dependency> <groupId>com.github.binarywang</groupId> <artifactId>weixin-java-pay</artifactId> <version>4.4.0</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.33</version> <!-- 注意:驱动用8.0+,但数据库服务仍是5.7 --> </dependency> </dependencies>

订单创建核心逻辑(OrderController.java):

@PostMapping("/create") public Result createOrder(@RequestBody OrderCreateDTO dto) { // 1. 查询商品信息(带库存) Goods goods = goodsService.getById(dto.getGoodsId()); if (goods.getStock() < dto.getCount()) { return Result.fail("库存不足"); } // 2. 扣减库存(行锁防超卖) goods.setStock(goods.getStock() - dto.getCount()); goodsService.updateById(goods); // MyBatis-Plus自动提交事务 // 3. 创建订单(状态=待支付) Order order = new Order(); order.setOrderId("DD" + DateUtil.format(new Date(), "yyyyMMdd") + String.format("%04d", orderMapper.selectCount(null) + 1)); order.setGoodsId(dto.getGoodsId()); order.setCount(dto.getCount()); order.setStatus(OrderStatus.WAIT_PAY.getCode()); orderMapper.insert(order); // 4. 调用微信统一下单API WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest(); request.setOutTradeNo(order.getOrderId()); request.setBody("奶茶订单"); request.setTotalFee((int) (goods.getPrice() * dto.getCount() * 100)); // 单位:分 request.setSpbillCreateIp("127.0.0.1"); // 此处应为真实IP,开发环境可填127.0.0.1 request.setNotifyUrl("https://your-domain.com/api/pay/callback"); try { WxPayUnifiedOrderResult result = wxPayService.unifiedOrder(request); Map<String, String> payParams = new HashMap<>(); payParams.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000)); payParams.put("nonceStr", RandomUtil.randomString(32)); payParams.put("package", "prepay_id=" + result.getPrepayId()); payParams.put("signType", "RSA"); payParams.put("paySign", wxPayService.createOrderSign(payParams)); // RSA签名 return Result.success(payParams); } catch (WxPayException e) { log.error("微信统一下单失败", e); return Result.fail("支付初始化失败"); } }

参数说明:

  • outTradeNo:必须全局唯一,项目用DDYYYYMMDDXXXX格式,避免UUID过长影响打印小票;
  • totalFee:单位为分,强制转int防止浮点误差(如15.5 * 100 = 1550);
  • notifyUrl:微信支付回调地址,需备案域名且HTTPS,本地调试可用ngrok或localtunnel;
  • paySign:必须用RSA签名(非MD5),weixin-java-pay4.4.0默认启用RSA,若用错密钥会返回invalid sign。

3.3 数据库:sql/目录下的建表与初始化脚本

sql/schema.sql包含5张核心表:

表名用途关键字段
t_goods商品信息id,name,price,stock,category_id
t_order订单主表order_id,goods_id,count,status,create_time
t_user用户信息(微信openid)openid,phone,nick_name,avatar_url
t_category商品分类id,name,sort
t_admin管理员账号username,password(BCrypt加密)

初始化数据(sql/init-data.sql)中,t_goods插入12款常见奶茶(珍珠奶茶、茉莉奶绿等),t_category含“热饮”“冷饮”“加料”三类,确保首次启动后首页有数据可展示。特别注意t_order.status字段用tinyint存储枚举值(1=待支付,2=已支付,3=制作中,4=已完成),而非字符串,减少索引体积。


4. 避坑指南:这4个坑让我重装3次MySQL、改掉27处代码

4.1 现象:小程序登录后wx.getPhoneNumber()始终返回{"errMsg":"getPhoneNumber:fail"}

原因:

  • 微信开发者工具未开启“调试基础库版本”,默认用最新版(如2.28.0),而getPhoneNumber需基础库2.21.0+;
  • 后端WXBizDataCrypt解密时,session_key已过期(微信session_key有效期2小时),但前端未重新wx.login()获取新code;
  • project.config.json中appid未替换为自己的测试号,导致签名无效。
    解决:
  1. 开发者工具右上角 → 详情 → 本地设置 → 勾选“调试基础库版本” → 选2.21.0;
  2. app.js中onLaunch添加wx.checkSession()失败时强制wx.login();
  3. 用 微信公众平台测试号 获取真实appid,并更新project.config.json。

4.2 现象:SpringBoot启动报错Caused by: java.lang.ClassNotFoundException: org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration

原因:

  • pom.xml中spring-boot-starter-web版本与SpringBoot 2.7.x不匹配,常见于复制粘贴时用了3.x的starter;
  • application.yml中spring.main.web-application-type: reactive被误设为reactive(本项目是Servlet容器)。
    解决:
  • 删除pom.xml中所有<version>标签,让SpringBoot BOM统一管理依赖版本;
  • application.yml确认spring.main.web-application-type: servlet(默认值,可删除此行)。

4.3 现象:MySQL 5.7安装后Navicat连接报错Client does not support authentication protocol requested by server

原因:

  • MySQL 5.7.44默认plugin为caching_sha2_password,而Navicat 15以下版本仅支持mysql_native_password;
  • root用户密码为空或简单密码,被安全策略拒绝。
    解决:
  1. 以管理员身份运行CMD,进入MySQL bin目录:
cd C:\Program Files\MySQL\MySQL Server 5.7\bin mysql -u root -p
  1. 执行以下SQL(将your_password换成强密码):
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_password'; FLUSH PRIVILEGES;
  1. Navicat新建连接时,密码填your_password,保存即可。

4.4 现象:支付成功后,/api/pay/callback收不到微信回调,订单状态卡在“待支付”

原因:

  • notifyUrl域名未在微信商户平台【产品中心→开发配置】中添加白名单;
  • SpringBoot未配置server.ssl.key-store,导致HTTPS回调被微信拒绝(微信强制要求HTTPS);
  • @RequestBody接收微信XML数据时,未用@RequestBody(required = false)且未处理空body。
    解决:
  • 微信商户平台 → 产品中心 → 开发配置 → 支付授权目录添加https://your-domain.com/api/pay/callback;
  • 本地调试用ngrok http 8080生成HTTPS隧道,notifyUrl填https://xxx.ngrok.io/api/pay/callback;
  • PayController.java中回调方法改为:
@PostMapping(value = "/callback", consumes = MediaType.APPLICATION_XML_VALUE) public String handleCallback(HttpServletRequest request, HttpServletResponse response) { try { String xmlData = IOUtils.toString(request.getInputStream(), StandardCharsets.UTF_8); // 解析xmlData,验证签名,更新订单状态... return "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>"; } catch (Exception e) { log.error("支付回调处理失败", e); return "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[系统错误]]></return_msg></xml>"; } }

5. 进阶技巧:把“能跑”变成“能交差”的3个硬核动作

5.1 让开题报告和论文真正匹配代码:补全这3处技术细节

很多同学的开题报告写着“采用JWT实现用户认证”,但代码里却是wx.login()+openid存库。要让答辩不被质疑,必须在文档中精准对应代码:

  • 开题报告“关键技术”章节:将“用户认证”改为“基于微信OpenID的无状态会话管理”,并注明“不使用JWT,因小程序端存储token存在安全风险,改用服务端内存缓存+OpenID绑定用户”;
  • 论文“系统设计”章节:在ER图中user表增加openid字段(主键),删除token字段,在“数据库设计”小节强调“OpenID作为用户唯一标识,避免手机号收集合规风险”;
  • 视频演示脚本:在支付成功画面后,插入后台管理端订单列表刷新的镜头,并标注字幕:“订单状态由微信异步回调实时更新,非轮询”。

5.2 毕业答辩高频问题预演:准备这4个答案

问题标准答案要点代码佐证位置
“订单超卖怎么解决?”“前端二次校验+后端SELECT FOR UPDATE行锁,事务隔离级别REPEATABLE READ”OrderController.java第22行goodsService.getById()后立即goodsService.updateById()
“微信登录为什么不用手机号?”“初期仅需OpenID识别用户,手机号在支付环节通过getPhoneNumber授权获取,符合最小权限原则”pages/index/index.js中wx.getPhoneNumber()调用位置
“为什么用MyBatis-Plus不用JPA?”“MyBatis-Plus对MySQL 5.7的分页插件支持更成熟,且XML映射便于调试复杂SQL”mapper/OrderMapper.xml中<select id="selectPage">分页查询
“管理端怎么防未授权访问?”“admin页面路由加wx.navigateTo拦截,后端/admin/**接口校验session中adminToken”utils/request.js中header: { 'Authorization': wx.getStorageSync('adminToken') }

5.3 一键生成答辩PPT:用VS Code插件导出代码片段

别再手动截图代码!用VS Code安装插件CodeSnap,选中关键代码(如OrderController.createOrder()方法),右键→Copy as Image,直接粘贴到PPT。重点标出:

  • 红框圈出SELECT ... FOR UPDATE(证明防超卖);
  • 黄底高亮wx.requestPayment()参数(证明支付链路完整);
  • 蓝线箭头指向result.getPrepayId()(证明微信统一下单成功)。
    这样做的PPT,评委一眼看懂技术深度,比堆砌架构图有效10倍。

从那以后我每次交毕设材料,都强制走一遍“微信开发者工具真机调试→Postman调后端接口→MySQL命令行查订单表”三连验证,哪怕只剩2小时答辩。因为奶茶店老板不会关心你用了什么设计模式,他只看手机扫完码,能不能立刻下单、付款、拿到小票——而这份资源,就是帮你把这三步钉死在代码里。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询