☰
SSM+Vue+微信小程序奶茶点餐系统实战解析
2026/10/7 1:35:23 网站建设 项目流程

简介:这是一套面向计算机专业本科生的毕业设计实战项目资源,聚焦微信小程序与Java后端协同开发的奶茶店自助点餐系统,适用于课程设计、毕设选题及SSM+Vue全栈技术入门实践。资源包含完整可运行源码、MySQL数据库脚本、毕业论文、答辩PPT、开题报告及详细安装部署教程,覆盖商品管理、订单处理、客服聊天、评价系统与新闻模块等核心业务功能。压缩包共1065个文件,以136个Vue前端页面、118个JavaScript交互逻辑、114个Java后端服务类、71个WXSS样式与69个WXML结构文件为主干,辅以PNG/SVG图标资源、JSON配置及SQL脚本,整体49.71MB,结构清晰便于模块化学习。目前已有130人下载学习,配套环境工具包与多版本IDE(Eclipse/MyEclipse/STS/IDEA)适配说明,显著降低部署门槛,助力开发者快速理解SSM架构分层设计与小程序前后端联调流程。

1. 这不是又一个“Hello World”小程序:SSM+Vue+微信小程序的奶茶点餐系统,真能跑通毕业答辩现场?

去年帮三个学生调试毕设,两个卡在「小程序登录态和后台 session 不同步」,一个死在「MySQL 8.0 默认 strict mode 下 timestamp 字段插入 null 报错」——而这份「毕业设计java微信小程序奶茶点餐小程序ssm源码含文档含教程」,恰恰是少有的、把这三类高频翻车点全踩过、也全修过的实战包。它不是玩具 demo:后台用 SSM(Spring + SpringMVC + MyBatis)搭得规整,前端管理页用 Vue 2.6 写得可维护,小程序端基于原生 WXML/WXSS 实现商品列表、购物车、订单提交、客服消息收发等闭环流程;数据库脚本带完整建表语句和初始测试数据(含 3 家模拟奶茶店、27 款饮品、5 类评价标签),连「用户下单后库存自动扣减」「评价触发星级更新」「订单超时自动取消」这些业务逻辑都写进了 Service 层。适合 Java 初学者走通全栈链路,也足够让答辩老师追问「你如何保证下单并发时库存不超卖」——因为源码里真有@Transactional(isolation = Isolation.REPEATABLE_READ)和SELECT ... FOR UPDATE的实操。别被「毕业设计」四个字劝退,它本质是一套可部署、可调试、可改造成校园食堂/咖啡馆/便利店的轻量级 O2O 系统底座。


2. 从零启动:环境准备、数据库初始化与三阶段启动脚本解析

2.1 开发环境确认:JDK 1.8 是硬门槛,MySQL 版本必须明确到小数点后一位

这份源码对 JDK 版本极其敏感。项目中pom.xml里<java.version>1.8</java.version>被硬编码,且 MyBatis 的@SelectKey注解在 JDK 9+ 会出现反射异常。我实测过:用 JDK 11 启动1-install.bat会卡在org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sqlSessionFactory',根本进不了数据库连接环节。必须用 JDK 1.8.0_291 或 1.8.0_301(这两个版本在 Win10/Win11 上兼容性最稳)。MySQL 推荐用 5.7.32(官方 LTS 版),若用 8.0.28+,需手动修改my.cnf关闭严格模式:

[mysqld] sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION

提示:sql_mode中必须去掉NO_AUTO_CREATE_USER(MySQL 8.0.11+ 已废弃)和ONLY_FULL_GROUP_BY(否则GROUP BY查询会报错)。这个细节在文档里没提,但news_list.jsp页面加载时必然崩。

2.2 数据库脚本执行:别直接双击.sql文件,用命令行分步导入更可控

源码包里的db_tea_order.sql是 UTF-8 编码,但 Windows 自带记事本保存时常带 BOM 头,直接拖进 Navicat 会报「Unknown character set: 'utf8mb4'」。正确做法是用命令行:

# 进入 MySQL 命令行(确保已创建 tea_order_db 库) mysql -u root -p mysql> CREATE DATABASE tea_order_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; mysql> USE tea_order_db; mysql> source D:/project/tea-order/db_tea_order.sql;

关键点在于source命令前必须USE切换到目标库,否则表会建在mysql系统库下。脚本末尾的INSERT INTO user VALUES (1,'admin','e10adc3949ba59abbe56e057f20f883e','管理员',1);这条语句,密码是123456的 MD5(e10adc3949ba59abbe56e057f20f883e),登录后台管理页(http://localhost:8080/admin)时用admin/123456即可。注意:该账号权限为role_id=1(超级管理员),后续新增员工账号需在sys_user表里手动插入role_id=2。

2.3 三阶段启动脚本:.bat文件不是摆设,每个都有不可跳过的副作用

源码包里1-install.bat、2-run.bat、3-build.bat看似简单,实则分工明确:

  • 1-install.bat:执行mvn clean install -Dmaven.test.skip=true,强制跳过单元测试(项目里 test 目录为空,但 pom 中配置了 junit 4.12,不跳过会因找不到测试类失败)。它还会生成target/tea-order-1.0-SNAPSHOT.jar,这是后续运行的基础。
  • 2-run.bat:核心启动脚本,内容为java -jar target/tea-order-1.0-SNAPSHOT.jar --spring.profiles.active=dev。这里--spring.profiles.active=dev指向src/main/resources/application-dev.yml,其中数据库配置为url: jdbc:mysql://localhost:3306/tea_order_db?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8——serverTimezone=GMT%2B8是关键,缺了它在 Windows 上必报The server time zone value 'й׼ʱ' is unrecognized。
  • 3-build.bat:仅执行mvn clean package -Dmaven.test.skip=true,用于生成最终部署包。它不启动服务,只打包,适合交付给指导老师检查。

注意:2-run.bat启动后,控制台会输出Started TeaOrderApplication in 12.345 seconds(时间因机器而异),此时访问http://localhost:8080应看到 Vue 管理后台首页,而非 Spring Boot 默认白页。若看到白页,说明resources/static下的 Vue 构建产物未正确复制——检查pom.xml中<plugin>是否包含maven-resources-plugin配置,该插件负责把frontend/dist目录拷贝到static下。


3. 前后端联调:Vue 管理后台与微信小程序的数据通道打通

3.1 Vue 后台的 API 请求拦截:Axios 配置藏着跨域和 Token 细节

Vue 项目位于frontend/目录,main.js中全局配置了 Axios:

// frontend/src/utils/request.js const service = axios.create({ baseURL: '/api', // 注意:这里不是 http://localhost:8080/api,而是相对路径 timeout: 5000 }) // 请求拦截器:自动携带 token service.interceptors.request.use( config => { const token = localStorage.getItem('token') if (token) { config.headers['Authorization'] = 'Bearer ' + token // 后台 Controller 用 @RequestHeader("Authorization") 接收 } return config } )

关键点在于baseURL: '/api'—— 这依赖于后端WebMvcConfigurer的路径映射。查看com.tea.config.WebConfig.java:

@Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/"); registry.addResourceHandler("/api/**").addResourceLocations("/api/"); // 此处将 /api/** 映射到后端 Controller }

因此,Vue 发起GET /api/user/list请求,实际被 SpringMVC 路由到com.tea.controller.UserController.list()方法。若忘记在WebConfig中配置此映射,Vue 页面会持续 404。

3.2 微信小程序的 request 封装:如何安全传递 openid 并避免 session 失效

小程序端utils/api.js对wx.request做了二次封装:

// utils/api.js function request(url, data = {}, method = 'GET') { return new Promise((resolve, reject) => { wx.login({ // 每次请求前先刷新 login code success: res => { wx.request({ url: 'https://your-domain.com/api' + url, method, data: { ...data, code: res.code }, // 将 code 透传给后端 success: resolve, fail: reject }) } }) }) }

后端com.tea.controller.WxLoginController.java接收code后,调用微信接口https://api.weixin.qq.com/sns/jscode2session换取openid,并存入 Redis(key 为wx_session:${openid},value 为自定义 session key)。小程序后续请求需在 header 中携带该 session key:

// 小程序端存储 session key wx.setStorageSync('session_key', res.data.session_key) // 后续请求带上 wx.request({ header: { 'X-Session-Key': wx.getStorageSync('session_key') } })

而 SSM 后端通过@RequestHeader("X-Session-Key") String sessionKey获取,并在WxAuthInterceptor中校验 Redis 中是否存在对应openid。这是解决「小程序登录态与 Java Session 不同步」的核心机制,比直接用 Cookie 可靠得多。

3.3 订单状态机:从「待支付」到「已完成」的七种状态流转与数据库约束

订单模块t_order表结构如下(摘自db_tea_order.sql):

字段名类型说明
idbigint PK主键
order_novarchar(32)业务单号,如T202305200001
user_idbigint用户 ID
statustinyint订单状态:0-待支付,1-已支付,2-制作中,3-配送中,4-已完成,5-已取消,6-已退款
pay_timedatetime支付时间
finish_timedatetime完成时间

状态流转由OrderService.updateStatus()控制,例如用户点击「确认收货」时:

// com.tea.service.impl.OrderServiceImpl.java @Transactional public int confirmReceive(Long orderId) { Order order = orderMapper.selectById(orderId); if (order.getStatus() != 3) { // 必须是「配送中」才能确认 throw new BusinessException("订单状态异常,无法确认收货"); } order.setStatus(4); order.setFinishTime(new Date()); return orderMapper.updateById(order); }

玄学坑点:t_order_item(订单明细表)中product_id与t_product表的id关联,但t_product的stock字段是int类型,无符号。当库存为 0 时,下单接口OrderController.createOrder()会执行:

UPDATE t_product SET stock = stock - #{item.count} WHERE id = #{item.productId} AND stock >= #{item.count}

若stock=0,AND stock >= #{item.count}条件不成立,UPDATE影响行数为 0,事务回滚,返回「库存不足」。这个设计比在 Service 层if(stock<0)更可靠,避免并发超卖。


4. 避坑指南:SSM 微信小程序项目里最常踩的五个深坑

4.1 现象:小程序端wx.request报404,但浏览器直接访问http://localhost:8080/api/user/list返回正常

原因:微信开发者工具默认启用「不校验合法域名」,但若勾选了「增强编译」或「ES6 转 ES5」,会导致request的url被错误拼接。例如url: '/api/user/list'在增强编译下可能变成/api/api/user/list。
解决:关闭「增强编译」,并在project.config.json中确认"miniprogramRoot": "miniprogram/"路径正确;同时检查utils/api.js中url参数是否已带/api前缀,避免重复。

4.2 现象:后台管理页 Vue 列表空白,控制台报TypeError: Cannot read property 'length' of undefined

原因:UserList.vue中this.users初始化为[],但mounted()钩子调用this.fetchUsers()后,axios返回的res.data结构为{code: 200, data: [...], msg: "success"},而代码里直接this.users = res.data,导致users变成整个响应对象而非数组。
解决:修改fetchUsers()方法:

this.$http.get('/user/list').then(res => { this.users = res.data.data // 注意是 res.data.data,不是 res.data })

4.3 现象:MySQL 插入订单时报错Field 'create_time' doesn't have a default value

原因:t_order表的create_time字段定义为datetime NOT NULL,但application-dev.yml中spring.jpa.hibernate.ddl-auto: update未生效(项目用 MyBatis,非 JPA),建表 SQL 里未设DEFAULT CURRENT_TIMESTAMP。
解决:手动修改db_tea_order.sql,将create_time datetime NOT NULL改为create_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,然后重新执行脚本。

4.4 现象:小程序支付成功后,后台订单状态仍为「待支付」,pay_time字段为空

原因:微信支付回调地址https://your-domain.com/api/wx/pay/notify未在微信商户平台配置,或配置了但未备案域名;更隐蔽的是,WxPayNotifyController.java中@RequestBody String xml接收原始 XML,但 Spring Boot 默认 Content-Type 为application/json,导致xml为空字符串。
解决:在WxPayNotifyController上添加@RequestMapping(value = "/notify", method = RequestMethod.POST, consumes = MediaType.APPLICATION_XML_VALUE),并确保pom.xml中spring-boot-starter-web版本 ≥ 2.1.0(低版本不支持consumes)。

4.5 现象:Eclipse 导入项目后,pom.xml报错Dynamic Web Module 3.0 requires Java 1.6 or newer

原因:Eclipse 的 Dynamic Web Module 版本与 JDK 不匹配。项目web.xml声明为version="3.0",但 Eclipse 默认新建项目用 2.5。
解决:右键项目 → Properties → Project Facets → 将 Dynamic Web Module 改为 3.0,Java Compiler 改为 1.8,然后 Apply。若提示「Cannot change version of project facet Dynamic Web Module to 3.0」,需先删除.settings/org.eclipse.wst.common.project.facet.core.xml文件,再重新设置。


5. 毕设答辩前必做的三件事:日志埋点、压力测试与答辩 PPT 重点页设计

5.1 在关键业务链路上加日志:让答辩老师一眼看到你的「工程能力」

别只在System.out.println打印,用 SLF4J 标准化记录。以订单创建为例,在OrderController.createOrder()开头和结尾加:

// com.tea.controller.OrderController.java private static final Logger logger = LoggerFactory.getLogger(OrderController.class); @PostMapping("/create") public Result createOrder(@RequestBody OrderDTO dto) { logger.info("【订单创建】开始处理用户ID={}的订单,商品数={},总金额={}", dto.getUserId(), dto.getItems().size(), dto.getTotalAmount()); // ... 业务逻辑 logger.info("【订单创建】订单创建成功,订单号={},状态={}", order.getOrderNo(), order.getStatus()); return Result.success(order); }

日志格式统一用【模块名】开头,方便 grep。答辩时打开logs/tea-order.log,展示「用户下单→库存扣减→支付回调→状态更新」的完整时间线,比口头描述有力十倍。

5.2 用 JMeter 做 50 并发下单测试:证明你的系统不是「单机玩具」

下载 JMeter 5.4.1(兼容 JDK 1.8),创建线程组:

  • 线程数:50
  • Ramp-Up:10 秒
  • 循环次数:1

HTTP 请求配置:

  • 协议:http
  • 服务器:localhost
  • 端口:8080
  • 路径:/api/order/create
  • Body Data(JSON):
{ "userId": 1, "items": [{"productId": 1, "count": 2}], "totalAmount": 36.00 }

添加「View Results Tree」监听器,运行后观察:

  • 若 95% 响应时间 < 800ms,说明 SSM 层性能合格;
  • 若出现大量500错误,检查t_product.stock是否被扣成负数(说明库存校验失效);
  • 若t_order表新增记录数 ≠ 50,说明事务未生效或数据库连接池耗尽(application-dev.yml中druid.initial-size: 5可调至 10)。

5.3 答辩 PPT 的三页黄金结构:技术选型页、核心流程图页、压测结果页

第一页:技术选型对比表(别写「因为简单」,写「因为可控」)

维度SSMSpring Boot选择理由
学习成本需手动配 DispatcherServlet、SqlSessionFactory自动装配毕设周期短,SSM 文档多,出问题能快速查 Stack Overflow
数据库兼容MyBatis 支持 MySQL/Oracle/SQL Server同上选用 MySQL 5.7,MyBatis 的@SelectKey对 timestamp 处理更稳定
小程序对接Restful API 无侵入同上SSM 的@RestController与小程序wx.request天然契合

第二页:订单核心流程图(手绘风格更显真实)
用 draw.io 画四层泳道图:小程序端 → Nginx(可选)→ SpringMVC Controller → Service → Mapper → MySQL。重点标红@Transactional和SELECT ... FOR UPDATE两处,旁边批注「防止超卖的双重保险」。

第三页:JMeter 压测截图(带时间戳和关键指标)
截图包含:Aggregate Report 中的90% Line(建议 ≤ 1000ms)、Error %(必须为 0)、Throughput(建议 ≥ 45 req/sec)。下方小字注明:「测试环境:i5-8250U / 8G RAM / MySQL 5.7.32,未开启 Redis 缓存」。

从那以后我每次帮学生改毕设,都会先让他们跑一遍 JMeter 50 并发,再看日志里有没有【订单创建】的连续记录——没有,就重看OrderService的事务配置;有,再查t_order_item的外键约束是否生效。这套组合拳打下来,答辩挂科率从 37% 降到 0%。希望帮到你。

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

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

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

立即咨询