SSM+微信小程序社区团购系统:毕业设计资源包全解析

发布时间:2026/10/7 13:22:06
SSM+微信小程序社区团购系统:毕业设计资源包全解析 简介面向计算机相关专业学生的毕业设计/课程设计场景这份基于SSM微信小程序的社区团购系统是一套可运行的高分毕业设计项目涵盖用户端小程序与后台管理端适合用于学习前后端服务、小程序页面与管理界面搭建。包内包含源码、数据库SQL、答辩PPT、开题报告、使用文档和演示视频压缩包整体52.07MB共1149个文件除118个Java后端类、109个Vue组件、160个JS脚本外还有75个WXML页面、73个WXSS样式、229个PNG图片等资源前端页面与逻辑文件齐全可对应模块阅读与调试。项目已在Window10/11环境调试通过答辩评审97分下载后按部署文档即可运行并附演示视频。目前已有142人学习下载适合需要快速搭建同类课题或参考完整毕业设计流程的开发者。1. SSM微信小程序社区团购系统一份毕业设计资源包到底值不值得跟“Java毕业设计-基于SSM微信小程序的社区团购系统”这类压缩包在毕业季几乎是高出场率的关键词。它解决的问题很实际用 SpringSpringMVCMyBatis 搭后端用微信小程序做用户端拼一个“社区团购”的完整业务闭环覆盖小程序商城、下单、后台管理、数据库设计等毕设必考环节。SSM 虽然不像 Spring Boot 那样“零配置”但正因为手动组装的三层结构明显答辩时能讲的东西反而更多。适合两类人一是 Java 基础一般、想让毕设带微信端的学生二是想拿高分、但不敢碰微服务大架构的稳妥派。下面我按自己带项目的习惯把这个资源包拆开说清楚。2. 把社区团购拆开看业务模型、SSM 三层分工与前后端数据契约2.1 业务角色与核心流程团长、自提点、商品、订单怎么闭环社区团购和普通商城最大的区别是“按团采购线下自提”。在这个系统里通常有三类角色普通用户业主登录小程序浏览商品、下单团长管理自提点负责收货分拣后台管理员维护商品分类、商品上下架、订单查询、数据统计。用户不直接收快递而是到自提点取货。这个“团长自提点”的模型是社区团购系统的业务灵魂也是写开题报告和论文时最值得展开的部分。对应的数据库设计一般会拆出这些核心表用户表含角色、openid、商品分类表、商品表、团长/自提点表、购物车表、订单主表、订单明细表。订单主表和明细表拆成两张是为了下单和统计时能分开查询也符合经典电商设计。自提点表会关联团长 id一个团长可以管理多个自提点但一个自提点在一个团购周期里最好只有一个团长。库存字段放在商品表里每次下单后做扣减如果要支持“拼团价”可以把促销价设计在商品表或者单独的团购活动表。按标题“社区团购系统”来要求最小的业务闭环至少要有用户浏览商品→加入购物车→创建订单→模拟支付→后台发货/自提核销。这段业务梳理不是空话它会直接影响后面 Mapper 怎么写。比如库存扣减放在哪个 SQL 里、订单流水要不要单独建表都要回到这个流程去定。很多同学拿到源码先急着跑起来结果跑起来之后不知道怎么改核心原因就是没先画业务流程图。我一般会建议拿到资源包第一件事不是导数据库而是先打开 README 或开题报告把角色和流程在图里走一遍。拿订单拆表来说订单主表存的是订单号、用户 id、自提点 id、订单状态、总金额、创建时间订单明细表存的是每一件商品的商品 id、数量、成交单价。为什么要拆因为一个订单可能包含多个商品如果都塞进一张表后台查“今天卖了多少斤白菜”会非常痛苦拆开后可以用 order_id 关联也能在明细表上做销量统计。很多毕设做得“还行但拿不了高分”差的就是这种建模时能不能说出理由。2.2 SSM 在项目里各管哪一段Spring、SpringMVC、MyBatis 的分工SSM 是三个框架协同工作不是各写各的。它之所以适合毕设是因为每一层都有明确“负责人”回答老师“你用了什么技术”时可以一句一个功能点。Spring 是容器负责创建和管理 Bean以及事务和 AOP。项目里那些 Service、Repository、Autowired 注解背后都是 Spring 在做依赖注入。社区团购里的下单事务、用户注册时的重复检查都可以用 Spring 的事务管理。SpringMVC 负责 Web 层把小程序发来的 HTTP 请求映射到 Controller 方法上顺便做参数绑定、JSON 序列化、异常处理。MyBatis 负责持久层和 MySQL 打交道。你看的源码里一般会有一堆 Mapper 接口和一个 Mapper XML 文件里面放着手写 SQL。为什么不用 JPA社区团购的订单、库存统计 SQL 比较复杂用 MyBatis 可以精确控制每条 SQL调优时也直观这也是很多老项目选 MyBatis 的原因。与 Spring Boot 相比SSM 需要手动配置 spring-mvc.xml、mybatis-config.xml、web.xml但这不是坏事。答辩时老师很爱问“你怎么配置映射路径的”“DispatcherServlet 为什么拦截 /”如果你亲手配过就能讲清楚。如果直接拿 Spring Boot 一顿注解反倒容易被追问到框架原理。这个角度可以作为你“为什么选 SSM”的开题理论依据。我习惯用一个包结构图来理解源码大部分 SSM 项目会按这个分层com.example.community ├── controller // 接收微信小程序请求 ├── service // 业务逻辑层接口 实现 ├── mapper // MyBatis Mapper 接口 ├── entity // 数据库实体类 ├── common // 统一返回体、异常、工具类 └── config // 拦截器、事务配置逻辑说明controller 层只做参数接收和结果返回不写 SQLservice 层处理业务规则比如下单时先校验库存再扣减mapper 层只做数据读写。如果你看到某个 Controller 里直接出现了 SqlSession 或者 JdbcTemplate说明项目分层不够干净答辩前最好重构掉。Spring 的事务就是在这个三层结构里生效的请求进入 ControllerService 方法被 Spring 的事务代理包裹如果方法里抛出了 RuntimeException事务自动回滚。这也是为什么下单要放在 Service 方法里而不是在 Controller 里写多条 Mapper 调用。参数上需要重点注意的是 Transactional 默认只回滚 RuntimeException如果你们代码里把库存不足包装成检查异常需要显式配置 rollbackForException.class。2.3 小程序端与后端的数据契约字段命名、状态码和分页结构微信小程序和后端不在同一个进程两边唯一的连接是 HTTP JSON。因此接口契约比代码本身更重要。常见的数据交互格式是统一返回体里面包含 code、msg、data 三个字段。 code 为 0 表示成功非 0 表示失败data 根据接口不同可能是对象、数组或 null。这样小程序端就能统一做成功判断res.data.code ! 0 时弹出提示而不是每个接口单独去猜。分页交互也需要提前约定。小程序端首页商品列表、搜索列表、订单列表都需要“加载更多”所以后端接受 pageNum 和 pageSize 两个参数返回数据里带上 total、list、hasMore。我建议统一参数名避免一个接口用 current另一个用 page。你看到的源码里如果没有统一也最好在答辩演示前把字段名整理统一这是代码质量的一个加分点。接口路径一般按模块划分比如 /api/category/list 获取分类/api/goods/list 获取商品分页/api/order/create 提交订单/api/user/login 处理微信登录。下面给一个简化的接口清单来自我习惯的拆分方式。模块接口语义请求方式关键参数返回 data用户微信登录POST /api/user/logincodetoken、userInfo分类分类列表GET /api/category/list无分类数组商品商品分页GET /api/goods/listpageNum、pageSize、categoryId{total, list}购物车加购POST /api/cart/addgoodsId、count购物车 id订单提交订单POST /api/order/createaddressId、items[]orderId、payAmount这个契约一旦定下来前后端就可以并行开发。小程序端的 wx.request 封装、后端 Controller 的 ResponseBody 返回值都围绕这张表展开。后面第 4 章会挑其中三条链路详细说。在第 2 章结束前我建议你动手做一件事把自己手里的接口全部列成一张这样的表放到开题报告或论文附录里。老师看到你连参数类型和返回结构都定义好了第一印象会好很多。3. 从压缩包到本地跑通JDK、Tomcat、MySQL、微信开发者工具的 6 个关键步3.1 环境版本怎么选不折腾社区团购这个 SSM 项目不是越新越好。我见过太多人 JDK 17 配 Tomcat 10然后被 Servlet 命名空间改名折腾到怀疑人生。常见的稳定组合是JDK 1.8、Maven 3.6 左右、Tomcat 8.5 或 9、MySQL 5.7。微信开发者工具用稳定版即可基础库版本选当前调试基础库就行不需要追最新。如果你本机已经装了新版 JDK也不用卸只需要在 IDEA 里给这个项目单独配置 Project SDK 为 1.8并把语言级别和模块 SDK 都切到 8。注意 Maven 的 settings.xml 里配置的 JDK 编译参数也要对应否则会出现“class file has wrong version”之类的错误。数据库方面MySQL 8.0 也能跑但驱动名和连接串不同后面会单独说。“选旧不选新”的核心原因是 SSM 生态本来就不再演进太多老项目在 Spring 5 之后需要额外处理兼容问题。如果你是为了学技术以后可以再玩 Spring Boot但为了毕业设计能交付稳定压倒一切。3.2 数据库导入与连接配置先改这里再启动拿到压缩包后第一步不是导入 IDEA而是先把数据库建好。不要直接双击.sql文件建议用命令行或 Navicat 执行。用命令行可以在出错时看得更清楚mysql -u root -p -e CREATE DATABASE community_group_buy DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; mysql -u root -p community_group_buy group_buy.sql逻辑说明第一条命令创建数据库显式指定 utf8mb4 字符集避免中文乱码第二条命令把 sql 文件里的表结构和初始数据导入。如果你用 Navicat也是在“新建数据库”里把字符集选为 utf8mb4然后再运行 SQL 文件。如果你手里的 sql 文件里已经带了 CREATE DATABASE那第一步可以跳过但要留意它创建的库名和你后面连接的库名是否一致。连接配置一般在 src/main/resources/jdbc.properties 里长这样jdbc.drivercom.mysql.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/community_group_buy?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai jdbc.usernameroot jdbc.password123456参数说明driver 在 MySQL 5.7 时代用 com.mysql.jdbc.DriverMySQL 8.0 则要改成 com.mysql.cj.jdbc.Driverurl 里的 characterEncodingutf8 是让 Java 往数据库写中文不乱码serverTimezoneAsia/Shanghai 解决日期差 8 小时的问题。username 和 password 一定改成你自己本机的否则后端起服务必报“Access denied for user”。注意很多资源包里为了安全会留一个默认密码你不改的话启动直接翻车。另外如果 sql 脚本是由低版本 MySQL 导出的在高版本导入可能有兼容问题失败时留意第几行报错一般是字段类型或索引名冲突。3.3 后端工程导入 IDEA 并部署到 Tomcat数据库就绪后用 IDEA 打开项目。如果是 Maven 工程直接选择 pom.xml 导入如果不是就重新配置为一个 Web 项目。等待依赖下载时检查每个模块的包名和配置文件扫描范围。我一般会先打开 spring-mvc.xml 看两样东西一是context:component-scan base-packagecom.example.community/是否覆盖到了 controller、service 的实现包二是视图解析器配置。因为小程序接口只返回 JSON不需要 JSP所以只要确保项目里有ResponseBody或RestController就不会出现“请求成功但返回 404 页面”的情况。IDEA 部署 Tomcat 的经典配置步骤是Run - Edit Configurations - 左上角加号 - Tomcat Server - Local。在 Deployment 页签里加一个 artifact通常选引擎会自动给你生成但注意 Application context 要设置成/community。如果你的小程序端请求 url 是http://localhost:8080/community/api/...那 Application context 必须叫 community否则路径对不上。点启动前建议先在 IDEA 的 Terminal 里跑一次mvn clean package -DskipTests。如果出现“Failed to execute goal”十有八九是依赖没下载全或 JDK 版本不对。本地 maven 仓库里缺包时可以去阿里云镜像仓库的配置这个是老生常谈不展开。3.4 小程序端导入与接口地址配置后端跑起来后再打开微信开发者工具。选择“导入项目”AppID 可以用你注册的小程序 AppID也可以点“测试号”测试号无法使用部分 API但对社区团购这种普通商城功能够用。项目目录指向解压出来的小程序文件夹不是仓库根目录别选错了。小程序端的关键配置在 app.js 或一个单独 config.js 里module.exports { BASE_URL: http://localhost:8080/community, LOCAL_DEBUG: true }逻辑说明BASE_URL 是所有 wx.request 请求的公共前缀。LOCAL_DEBUG 只是一个开关开发时如果为 true则请求地址不变发真机预览时需要把它改成 false并使用本机局域网 IP例如http://192.168.1.5:8080/community。这里最容易踩的坑是手机真机预览时请求 localhost 访问的是手机自己不是你的电脑。解决方法是让手机和电脑连同一个 Wi-Fi把 BASE_URL 里的 localhost 换成电脑的局域网 IP并保证防火墙允许 8080 端口入站。如果不想动防火墙也可以临时关闭 Windows 防火墙测试但这只是开发期做法。微信开发者工具右上角“详情 - 本地设置”里务必勾选“不校验合法域名、web-view业务域名、TLS 版本以及 HTTPS 证书”。因为本地开发用的是 http不勾选会被拦截。这个选项只对开发工具有效真机预览也需要在调试模式下才生效上线前还是得配合法 HTTPS 域名。4. 核心实现从首页商品列表到提交订单接口和小程序页面怎么配合4.1 先把统一返回体写好code、msg、data 的 SpringMVC 实现还记得第 2 章的接口契约吗现在把它落到代码里。社区团购系统里几乎所有 Controller 都返回同一个结构通常长这样public class ResultT { private Integer code; private String msg; private T data; public static T ResultT success(T data) { ResultT r new Result(); r.code 0; r.msg ok; r.data data; return r; } public static T ResultT error(String msg) { ResultT r new Result(); r.code 500; r.msg msg; return r; } // getter / setter 省略 }逻辑说明这里的泛型 T 让所有接口都能复用同一个类。code0 表示成功非 0 时小程序端直接读取 msg 弹提示。如果你用的是 Spring 4.3 以上Controller 里直接标注 RestController返回对象时会自动序列化成 JSON不需要手动再写 ResponseBody。参数说明data 里放业务数据。比如登录接口放 token商品分页放 {total, list}订单创建放 orderId。只要保证字段名稳定小程序端就可以通过 res.data.code 判断请求结果而不是依赖 HTTP 状态码。4.2 首页商品列表与“加载更多”后端分页 小程序列表拼接商品列表是首页的门面。后端用 PageHelper 插件可以少写很多重复代码。常见做法是GetMapping(/api/goods/list) public ResultPageResultGoods list( RequestParam(defaultValue 1) Integer pageNum, RequestParam(defaultValue 10) Integer pageSize, RequestParam(required false) Integer categoryId) { PageHelper.startPage(pageNum, pageSize); ListGoods list goodsMapper.selectByCategory(categoryId); return Result.success(PageResult.of(list)); }逻辑说明PageHelper.startPage 会把下一个查询包装成带 LIMIT 的分页 SQL所以它后面必须紧跟 Mapper 查询中间不能再执行任何数据库操作否则分页条件可能作用到别的查询上。PageResult 里封装了 total、list、hasMore其中 hasMore pageNum * pageSize total小程序端用它判断是否还能继续上拉加载。Mapper XML 里对应的查询要指定排序否则分页结果不稳定select idselectByCategory resultMapGoodsResultMap SELECT id, name, price, stock, image, category_id FROM goods where if testcategoryId ! null category_id #{categoryId} /if /where ORDER BY id DESC /select参数说明排序字段建议用自增主键 id desc而不是按价格排序价格相同的商品如果排序不稳定分页会出现重复。如果社区团购后台设置了“置顶商品”可以把置顶字段加入排序ORDER BY is_top DESC, id DESC但 is_top 的索引最好加上。小程序端“加载更多”的逻辑核心在于列表是追加而不是覆盖const pageSize 10 function loadGoods(pageNum, categoryId, isRefresh) { wx.request({ url: ${BASE_URL}/api/goods/list, data: { pageNum, pageSize, categoryId }, success: res { if (res.data.code ! 0) { wx.showToast({ title: res.data.msg, icon: none }) return } const { list, hasMore } res.data.data const newList isRefresh ? list : this.data.goodsList.concat(list) this.setData({ goodsList: newList, hasMore: hasMore, pageNum: pageNum, loading: false }) } }) }逻辑说明isRefresh 为 true 时表示下拉刷新直接覆盖列表否则 concat 拼接下一页数据。每次请求前设置 loading 状态避免用户快速上拉时触发多个请求。这里还顺手解决了“微信小程序页面列表加载更多”最常见的问题数据重复和请求抖动。参数说明pageNum 初始为 1每次加载下一页后传 pageNum 1。hasMore 来自后端理论上不要在小程序端自己判断 list.length % pageSize 0因为最后一页正好整除时会多请求一次。4.3 提交订单的 SSM 事务链路Controller、Service、Mapper 怎么协同订单功能是社区团购的评分核心。一个不规范的下单流程老师随便问一句“并发怎么办”就会露馅。常见做法是 Controller 只做参数接收业务逻辑放在 Service事务注解加在 Service 实现类方法上。Override Transactional(rollbackFor Exception.class) public Long createOrder(OrderCreateParam param) { // 1. 检查自提点是否正常营业 PickupPoint point pickupPointMapper.selectById(param.getPickupPointId()); if (point null || point.getStatus() ! 1) { throw new BizException(自提点不可用); } // 2. 创建订单主表 Order order new Order(); order.setUserId(param.getUserId()); order.setPickupPointId(param.getPickupPointId()); order.setStatus(0); // 0 待支付 order.setTotalAmount(calcTotalAmount(param.getItems())); orderMapper.insert(order); // 3. 创建订单明细 for (OrderItemParam item : param.getItems()) { int rows goodsMapper.reduceStock(item.getGoodsId(), item.getCount()); if (rows 0) { throw new BizException(item.getGoodsName() 库存不足); } orderItemMapper.insert(buildOrderItem(order.getId(), item)); } return order.getId(); }逻辑说明Transactional 保证这三个步骤要么全部成功要么全部失败。库存扣减通过 reduceStock 的“乐观扣减”实现SQL 里带了 stock #{count} 条件返回 0 说明扣减失败。这样做比“先 select 判断后 update”更抗并发。参数说明param.getItems() 是前端传来的购买商品列表每条包含 goodsId 和 count。如果你手里的源码是先查库存再更新库存答辩前建议改成这种单条 SQL 原子扣减这非常体现你对数据一致性的理解。对应的 Mapper XML 里reduceStock 写起来很简单update idreduceStock UPDATE goods SET stock stock - #{count} WHERE id #{goodsId} AND stock #{count} /update参数说明这里没有用乐观锁版本号而是直接依赖 SQL 的原子性。当两条请求同时减库存时MySQL 的行锁会让第二条更新等待最后只剩一条成功另一条影响行数为 0Service 层就抛“库存不足”。这样即使小程序端连点下单也不会把库存扣成负数。4.4 SSM 常用注解在项目里怎么对应背面试题不如看业务用法很多人刷“SSM 常用注解”八股时背得一清二楚写代码却不知道用在哪。这里我按社区团购业务给你对应一遍注解作用在本项目里的位置Controller / RestController标记 Web 层组件商品、订单、用户 Controller 上Rest 前缀表示直接返回 JSONService标记业务层组件OrderServiceImpl、UserServiceImpl 上事务的入口Autowired依赖注入Service 注入 MapperController 注入 ServiceRepository标记 Mapper 层组件在 Mapper 接口上配合 MyBatis 扫描GetMapping / PostMapping路由注解商品列表、订单创建接口上RequestParam参数绑定分页接口接收 pageNum、pageSizePathVariable路径参数绑定如 /api/goods/{id} 获取商品详情Transactional声明事务下单、扣库存等写操作上ResponseBody响应体序列化旧版 Controller 里配合 Controller 使用这个表格可以直接放进论文的“技术介绍”章节比长篇抄文档更贴合项目。不过要注意如果你用的 Spring 版本较老RestController 不一定可用那就统一用 Controller ResponseBody。如果源码里两种混着来最好统一风格再答辩。第 4 章把这些链路拆完你应该能讲清楚“一次下单请求从小程序到数据库”的全过程页面触发 wx.request - Tomcat 按上下文路径映射到 Controller - SpringMVC 绑定参数 - Service 开启事务 - Mapper 执行 SQL - 返回统一 JSON - 小程序根据 code 反馈。这条主线讲顺了答辩已经成功一半。5. 避坑排查指南社区团购系统从后端到小程序的常见翻车点5.1 数据库与后端启动类问题排查先看现象。Tomcat 启动日志没有报错但访问http://localhost:8080/community/api/goods/list返回 404。原因通常是 IDEA 的 Application context 配置不对或者部署时没有把项目识别为 Web 工程导致 artifact 没带community上下文。解决方法是重新检查 Deployment 里的 Application context确认它是/community再打开 Project Structure 检查 Web 部分是否存在Facet 是否正确。如果用了 maven 插件启动还可以看看 plugin 的path配置。第二个高发问题是数据库连接报错或者中文乱码。现象是启动时抛 “Unknown database” 或 “Communications link failure”运行后商品名显示 ???。原因基本集中在三处数据库库里确实没建连接串里的库名对不上以及连接串没指定 utf8mb4。解决时先回到第 3.2 节的命令行确认 CREATE DATABASE 成功再检查 jdbc.properties 是否写了characterEncodingutf8最后确认不仅库的字符集是 utf8mb4表也是。Navicat 里可以右键表查看表选项如果表是 latin1执行ALTER TABLE goods CONVERT TO CHARACTER SET utf8mb4;。还有一个隐藏坑Maven 依赖下载不全导致启动时ClassNotFoundException: org.springframework.web.servlet.DispatcherServlet。原因是网络不稳定或私服配置导致 spring-webmvc 没有完整下载。解决方法是删除本地仓库对应目录重新 maven reimport或者换阿里云镜像仓库。这不是项目问题是环境问题但经常让新手误以为源码坏了。5.2 小程序请求与微信登录类问题排查小程序端最经典的报错是 “request:fail url not in domain list”。现象电脑上用微信开发者工具请求后端控制台提示 url 不在合法域名列表里。原因小程序默认禁止访问 http 接口除非开启本地校验关闭。解决在开发者工具右上角“详情 - 本地设置”里勾选“不校验合法域名”。但要注意这个勾选只对当前工具窗口生效真机预览时同样需要在真机调试模式下才有效。上线时则必须在小程序后台配置 HTTPS 合法域名这是硬性要求。第二个高频坑是微信登录 code 换 session_key 的位置不对。现象用户登录接口报 “openid is null”或者登录状态一会儿就失效。原因很多人把 AppSecret 写在小程序前端直接用 wx.request 调微信接口或者后端换到 session_key 后不知道怎么处理。解决小程序端只做wx.login()拿 code然后把 code 传到后端/api/user/login后端拿着 code AppSecret 去请求微信接口拿到 openid 和 session_key 后只把 openid 用来查/建用户再生成一个自定义 token 返回前端。session_key 永远不要返回前端否则数据有被解密的泄露风险。如果登录接口在开发者工具中正常、真机预览却失败优先检查 BASE_URL 是否改成了局域网 IP。现象是手机网络请求直接超时电脑却正常。原因是真机上 localhost 指向手机本身不是你电脑。解决方法是保证手机和电脑在同一局域网把 IP 换成电脑的 IPv4 地址同时确认电脑防火墙允许外部访问 8080 端口。这一步不改演示现场经常当场翻车。5.3 数据一致性库存超卖、列表重复和事务失效库存扣减如果做不对演示时连点下单就能看出一堆负数库存。现象是商品库存明明只剩 5用户连续快速提交 6 单库存变成 -1。原因是常见写法是select stock出来判断再update stock两个请求同时读到库存 1都通过校验。解决方法是把校验和扣减合并成一条 SQLUPDATE goods SET stock stock - #{count} WHERE id #{goodsId} AND stock #{count}影响行数为 0 就抛库存不足。这个话题在第 4.3 节已经写过这里强调的是如果答辩前没改老师用 Postman 并发测一下就会露馅。事务失效也常常被忽略。现象订单主表插入成功但订单明细插入失败后主表数据仍然存在。原因方法没有被 Spring 事务代理。常见场景是同一个类内部调用this.createOrder()调自己类的另一个方法Transactional 会失效。解决把事务方法放在单独 Service 实现里通过外部 Bean 调用或者使用代理对象调用。另外确认 spring-mvc.xml 里是否配置了tx:annotation-driven transaction-managertransactionManager/以及 Transactional 是否加在 public 方法上。分页列表重复同样属于数据一致性范畴。现象小程序端加载更多时第一页和第二页出现了同一条商品。原因ORDER BY 字段不唯一比如只按价格排序价格相同的记录在分页查询中可能被重复返回。解决SQL 里补上唯一排序键ORDER BY id DESC如果后台有置顶逻辑写ORDER BY is_top DESC, id DESC。还有一个小坑是 PageHelper 的 count 查询和分页查询顺序被打断比如在 startPage 和 select 之间加了其他 MyBatis 方法解决办法是保证 startPage 后紧跟目标查询。6. 验收与加分部署前最后一轮自测以及两个值得讲的优化点6.1 三分钟接口自测脚本答辩前一天不要只点小程序界面建议用 curl 或 Postman 把核心接口按顺序调一遍。下面是我常用的一组命令curl http://localhost:8080/community/api/category/list curl http://localhost:8080/community/api/goods/list?pageNum1pageSize5 curl -H Content-Type: application/json \ -d {userId:1,pickupPointId:1,items:[{goodsId:1,count:2}]} \ http://localhost:8080/community/api/order/create逻辑说明第一条验证分类接口第二条验证分页参数是否正确第三条验证订单创建能否成功。如果第三条返回 code0 且能看到 orderId说明数据库连接、Mapper 映射、事务配置基本可用如果返回 404 或 500按第 5 章的方法逐层排查。参数说明curl 中的 -H 指定 JSON 头-d 发送请求正文。实际参数名要根据你的源码调整但建议答辩前把这三个接口的示例请求和响应截图存下来演示时网络断了还有兜底。6.2 两个能写进答辩 PPT 的优化点第一个优化是给商品列表加 Redis 缓存。社区团购首页访问量大商品列表读多写少可以缓存第一页热门商品key 设为goods:hot:page1设置更新时间 5 分钟。代码上不用大改只需要在 Service 层先查缓存、缓存没有再去查数据库并回填。这样一个小点既能体现你知道“缓存穿透”问题又能体现你对性能的考虑。第二个优化是给未支付订单增加自动关闭。Spring 的 Scheduled 可以每分钟扫一次订单表关闭创建超过 30 分钟且状态为待支付的订单并释放对应库存。这个功能在工作量上不大但演示时如果做出来效果非常直观。实现时注意把定时任务的线程池配置好避免阻塞正常接口。我自己的习惯是答辩前一周不再动新功能只做回归测试和演示数据准备。几年前带过一个学弟演示前临时改商品图片 URL结果图片域名过期首页一片裂图直接影响打分。做毕设最怕的就是在最后一晚手痒改配置。把这套自测跑通把两个优化点写进 PPT剩下就是稳住心态把项目从数据库到小程序完整讲一遍。希望帮到你。本文还有配套的精品资源点击获取