资讯动态

社区团购小程序毕设:微信小程序+SSM+MySQL全链路解析

发布时间:2026/10/27 15:18:56 来源:尧图企业网站定制
简介一份基于微信小程序SSMMySQL的社区团购系统毕业设计源码包面向需要完成毕设或快速搭建团购小程序的开发者完整覆盖管理员、商家、会员三类角色功能上从前台商品展示、购物车、下单支付到后台订单、退货退款、评价管理等均有代码实现。资源共1148个文件单压缩包约52MB包含java后端与vue管理端源码、微信小程序页面文件wxml、wxss、js、数据库脚本sql、界面素材png/svg以及开题报告、毕业论文doc、答辩PPT、演示视频mp4等全套文档目录结构清晰还附有安装、运行、构建脚本便于本地部署调试与二次开发。目前已有163人学习参考适合作为毕业设计选题方案、论文写作参考或实际项目脚手架可有效降低从零开发的工作量。1. 社区团购小程序毕业设计微信小程序、SSM 与 MySQL 三层合起来到底做了什么很多学生拿到这个题目第一反应是先把源码跑起来、把演示视频看完。我带过几轮这类项目后有个反直觉的结论把系统点开只占毕设三成工作量剩下七成是你能不能讲清楚「用户在小程序里点下下单按钮请求怎么被 SSM 后端接收、怎么读写 MySQL、最终怎么把结果渲染回小程序」这条完整链路。社区团购小程序不是玩具项目它覆盖了一条真实业务线登录、商品浏览、加购、下单、成团后端是经典的 SSM 组合数据落在 MySQL 里。它适合计算机、软件工程、信息管理等专业做毕设也适合想把微信小程序 Java 后端串起来练一遍的人。除了源码和数据库文件还配套开题报告、毕业论文、答辩 PPT 和演示视频这几份文档怎么和代码配合我放到第四章细说。2. 先搭数据库与 SSM 后端社区团购的业务实体、接口与取舍做这个题目的第一步不是写代码而是把数据模型立住。社区团购和普通电商的区别在于多了一个「团长」和「成团」的概念会员不是直接对平台下单而是先选定一个团长、加入某个团购活动再按团购价下单。这个业务特点直接决定了表结构怎么拆、状态字段怎么设计也决定了后面 SSM 后端里 Service 层要处理哪些逻辑。这章先讲表怎么建再讲 MyBatis 的映射写法最后解释为什么这个题目用 SSM 而不是 Spring Boot——这三块都是答辩时大概率被问到的地方。2.1 六张核心表怎么设计团长、商品、订单与成团的字段和状态我见过不少学生把社区团购做成单表大而全用户、商品、订单全塞在几个字段里团长概念干脆用 user 表里一个 role 字段代替。短期能跑但论文里「数据库设计」写不了几行答辩一问就露馅。常见做法是把业务拆成六张表用户表 user、团长表 group_leader、团购活动表 activity、商品表 product、购物车表 cart、订单表 orders外加一个订单明细表 order_item用于记录一单里多个商品。为什么团长要单独建表而不是在 user 表里加 role因为团长有自己专属的字段审核状态、佣金比例、所属小区、服务区域。这些字段放在 user 表里会让普通用户的记录产生大量 null而且团长审核、佣金结算这些操作在后端 Service 层也不好定位。单独立表后用户表只关心登录和身份团长表只关心团购业务职责清晰也好写论文。下面是精简后的建表语句保留了核心字段注释直接写在 SQL 里-- 用户表小程序端用户注册来源为微信登录 CREATE TABLE user ( id BIGINT PRIMARY KEY AUTO_INCREMENT, openid VARCHAR(64) NOT NULL UNIQUE COMMENT 微信 openid一个用户一条, nickname VARCHAR(50) DEFAULT COMMENT 微信昵称, avatar VARCHAR(255) DEFAULT COMMENT 头像地址, phone VARCHAR(20) DEFAULT COMMENT 手机号非必填, create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT 注册时间 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; -- 团长表与 user 是一对一关系但独立成表 CREATE TABLE group_leader ( id BIGINT PRIMARY KEY AUTO_INCREMENT, user_id BIGINT NOT NULL COMMENT 关联 user.id, community VARCHAR(100) NOT NULL COMMENT 负责小区/社区, commission_rate DECIMAL(5,2) DEFAULT 10.00 COMMENT 佣金比例如 10.00 表示 10%, status TINYINT DEFAULT 0 COMMENT 0待审核 1已通过 2已驳回, create_time DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; -- 团购活动表一次成团活动的标题、时间与成团门槛 CREATE TABLE activity ( id BIGINT PRIMARY KEY AUTO_INCREMENT, title VARCHAR(100) NOT NULL COMMENT 活动名称, leader_id BIGINT NOT NULL COMMENT 关联 group_leader.id, start_time DATETIME NOT NULL, end_time DATETIME NOT NULL, min_buyers INT DEFAULT 10 COMMENT 成团最低人数0为不限, status TINYINT DEFAULT 1 COMMENT 1进行中 0已结束 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; -- 商品表属于某个团购活动同一个商品在不同活动里是不同的记录 CREATE TABLE product ( id BIGINT PRIMARY KEY AUTO_INCREMENT, activity_id BIGINT NOT NULL COMMENT 关联 activity.id, name VARCHAR(100) NOT NULL, price DECIMAL(10,2) NOT NULL COMMENT 团购价用十进制避免浮点误差, stock INT DEFAULT 0 COMMENT 库存, sales INT DEFAULT 0 COMMENT 销量下单成功后累加, deleted TINYINT DEFAULT 0 COMMENT 逻辑删除0正常 1已删除 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; -- 订单表一单对多商品状态机是业务核心 CREATE TABLE orders ( id BIGINT PRIMARY KEY AUTO_INCREMENT, order_no VARCHAR(32) NOT NULL UNIQUE COMMENT 业务订单号前端展示用, user_id BIGINT NOT NULL, activity_id BIGINT NOT NULL, status TINYINT DEFAULT 0 COMMENT 0待支付 1已支付 2已取消 3已退款, total_price DECIMAL(10,2) NOT NULL, create_time DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; -- 订单明细表记录每个商品的购买数量 CREATE TABLE order_item ( id BIGINT PRIMARY KEY AUTO_INCREMENT, order_id BIGINT NOT NULL, product_id BIGINT NOT NULL, product_name VARCHAR(100) NOT NULL COMMENT 冗余商品名防止商品删除后订单显示异常, price DECIMAL(10,2) NOT NULL, quantity INT NOT NULL ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;几个关键设计说清楚价格和佣金比例一律用DECIMAL不用 FLOAT 和 DOUBLE这是 MySQL 浮点精度问题的典型来源差一分钱在支付场景里就是事故。订单状态用TINYINT存数字不直接存字符串因为状态判断在后端 Java 里用常量比对比字符串快而且数据库体积更小真正展示给用户的「待支付」「已支付」字样由前端映射后端只认数字。order_item里冗余存了一份product_name原因注释里写了商品改名或删除后历史订单依然能正确展示这叫「用空间换稳定」。另外所有表都建了create_time并给了DEFAULT CURRENT_TIMESTAMP省得每次插入都在 Java 里手动 new Date()。2.2 SSM 四层分包与 MyBatis 动态 SQL商品分页查询怎么从 Mapper 走到 Controller数据库建好后SSM 后端的代码分包是这套项目的主线。常见分包方式是一组顶层包entity放与表对应的 JavaBeanmapper放 MyBatis 接口service放业务逻辑controller放请求入口再加一个common放工具类和统一返回体。整个系统的增删改查就沿着这条线走Controller 收参数、Service 做业务判断、Mapper 落 SQL。刚开始写的时候不要自作主张多包一层dao再包一层serviceimpl毕业设计的代码量四层足够了包太深答辩反而难讲。商品列表页是最典型的一个查询场景按关键词模糊搜索、按销量或价格排序、分页返回。MyBatis 的动态 SQL 在这里比 JDBC 舒服得多下面这段是 Mapper XML 里的写法select idpageProducts resultTypecom.example.entity.Product SELECT id, activity_id, name, price, stock, sales FROM product where if testkeyword ! null and keyword ! AND name LIKE CONCAT(%, #{keyword}, %) /if if testactivityId ! null AND activity_id #{activityId} /if AND deleted 0 /where choose when testorderBy sales ORDER BY sales DESC /when when testorderBy price ORDER BY price ASC /when otherwise ORDER BY create_time DESC /otherwise /choose LIMIT #{offset}, #{pageSize} /select这段有个容易被忽略的细节where标签会自动去掉第一个if前面多出来的 AND所以每个条件里写AND name LIKE ...是安全的。choose实现「多选一」的排序逻辑比在 Java 代码里拼接 SQL 更直观也避免了 SQL 注入风险。分页用LIMIT #{offset}, #{pageSize}手写先算好 offset (page - 1) * pageSize这个方案在数据量不超十万的毕设场景足够如果想少写点代码也可以引入 PageHelper 插件但答辩时你要能说清它是用拦截器改写 SQL 实现的说不清就别用。ORDER BY sales DESC 这种排序看着简单实际是 MySQL 里最需要关注索引的写法数据量大了必须给排序字段建索引毕设阶段数据量小这个坑先知道就行。Controller 层的写法更套路化全部返回 JSON前端小程序直接消费RestController RequestMapping(/api/product) public class ProductController { Autowired private ProductService productService; RequestMapping(/page) public Result page(RequestParam(defaultValue 1) Integer page, RequestParam(defaultValue 10) Integer pageSize, RequestParam(required false) String keyword, RequestParam(required false) String orderBy) { // service 内部完成分页计算与查询返回 PageResult PageResult data productService.pageProducts(page, pageSize, keyword, orderBy); return Result.success(data); } }注意RequestParam里 defaultValue 的写法前端不传 page 和 pageSize 时也能兜住orderBy用 requiredfalse允许不传排序条件让 Mapper 里的otherwise走默认的按时间倒序。这里统一返回Result封装体里面放 code、message、data 三个字段前端判断 code 为 200 才取 data。用这种统一返回体是毕业设计答辩的加分项比直接返回 HashMap 更像工程化代码。2.3 为什么这套毕设选 SSM 而不是 Spring Boot答辩视角下的技术选型理由现在新项目基本都 Spring Boot 起步很多学生拿到这个 SSM 题目会犯嘀咕老框架还有必要做吗从做毕设的角度看SSM 恰恰是更稳的选择。多数高校的 Java 课程主线还是 Spring SpringMVC MyBatis答辩老师对这个组合的提问预期非常明确Spring 的 IoC 和 AOP、SpringMVC 的 DispatcherServlet 流程、MyBatis 的映射原理每一个都有标准答案且能展开讲。Spring Boot 虽然用起来省事但大量配置被自动装配黑匣子化学生如果只停留在「加依赖就能跑」的层面答辩反而容易被追问到底。另外一点很实际论文里的系统架构图、技术路线图通常都是照着 SSM 这套画的三层架构拿到源码后文档和代码能对上。而 Spring Boot 的自动配置、内嵌 Tomcat 这些概念要写进论文里解释成本高也和课程设计模板不吻合。如果你导师明确要求必须用 Spring Boot那第六章我留了一条平滑迁移的路改造成本不算大——但默认状态下跟着题目走 SSM 是风险最低的选择。环境组合上这套项目最常见的运行环境是 JDK 1.8 Tomcat 8.5 Maven 3.6 MySQL 5.7。MySQL 安装教程网上搜「mysql 5.7.44 安装过程详细」能对应上但如果你本机装的是 MySQL 8.0驱动类名和连接串要改这个坑我在第五章单独列了一条。这里先给一个判断标准看项目里的pom.xml依赖版本mysql-connector-java 是 5.x就用 5.7 数据库最省事是 8.x就用 8.0 数据库并配套改驱动。版本对齐能省掉后面几小时的排错时间。3. 微信小程序端登录、首页商品流与下单闭环后端接口准备好后小程序端的工作就是把这些接口串成用户能操作的页面。小程序端的技术栈不复杂就是原生 WXML WXSS JavaScript没有引入第三方框架的必要。整个端按 TabBar 拆四个页面首页、分类或团购列表、购物车、我的订单列表和结算页作为普通页面跳转。这章讲首页请求怎么写、登录和手机号获取怎么处理以及购物车到下单这条链路上最容易出问题的细节。3.1 小程序目录结构与首页商品流wx.request 的最小写法和自定义导航栏高度拿到源码后先看pages目录结构一般是这样pages/index首页、pages/activity团购活动列表、pages/cart购物车、pages/order订单列表、pages/mine个人中心。每个页面是一个文件夹内含 .js、.wxml、.wxss、.json 四个文件。.json文件里可以配页面标题和导航栏样式这是小程序和普通 HTML 页面不一样的起点——每个页面的配置是独立的。首页最核心的动作是进入后拉取当前进行中的团购活动及其商品。这里的请求写法是微信小程序的标准动作wx.request下面是一段最小代码// pages/index/index.js Page({ data: { products: [], loading: true, page: 1, hasMore: true }, onLoad() { this.loadProducts() }, loadProducts() { wx.request({ url: http://localhost:8080/api/product/page, method: GET, data: { page: this.data.page, pageSize: 10, orderBy: sales }, success: (res) { if (res.data.code 200) { this.setData({ products: this.data.products.concat(res.data.data.list), loading: false }) } }, fail: () { wx.showToast({ title: 加载失败, icon: none }) } }) } })wx.request的写法有几个讲究url 在开发阶段可以直接写本地接口http://localhost:8080但微信开发者工具默认会拦截 http 请求需要在「详情 - 本地设置」里勾选「不校验合法域名」这个开关我第五章展开讲。success 回调里有个常见错误是直接this.setData({ products: res.data.data.list })整表覆盖正确做法是concat追加这样配合上拉加载不会丢前面的数据。fail回调一定要给用户提示否则后端没启动时页面白屏且没有任何反馈排查时会以为是前端 Bug。还有一个高频问题是导航栏高度。如果你在app.json或页面.json里把navigationStyle设成了custom整个页面顶部的标题栏要自己画此时刘海屏适配全靠wx.getMenuButtonBoundingClientRect()这个方法——它返回胶囊按钮的位置和尺寸用胶囊顶部位置加上胶囊高度就能算出自定义导航栏应该占多高。网上搜「微信小程序顶部导航栏高度」能看到大量讨论核心代码就三行const menu wx.getMenuButtonBoundingClientRect() // statusBarHeight 来自 wx.getSystemInfoSync() const navBarHeight (menu.top - statusBarHeight) * 2 menu.height为什么是* 2 menu.height因为这个公式能覆盖胶囊上下留白视觉上导航栏和胶囊垂直居中。不同机型胶囊位置有差异用这个公式算出来的高度在各机型上基本一致。如果源码里用的还是写死的 44px、48px强烈建议改成动态计算答辩时演示一部 iPhone 一部 Android对比效果就是亮点。3.2 微信小程序登录与获取手机号wx.login 与 openid 的交换链路登录是这套系统里答辩必问的环节也是微信小程序和网页开发最大的差异点。网页登录靠用户名密码小程序没有密码输入框它靠微信身份体系。整个链路是这样的小程序端调用wx.login()拿到一个临时凭证 code这个 code 有效期只有五分钟后端拿这个 code 加上小程序的 appid 和 appsecret调用微信的接口换回 openid——openid 是用户在这个小程序里的唯一身份标识。appsecret 绝对不能出现在小程序代码里一旦打包到前端任何人反编译都能拿走所以换 openid 的动作必须放在 SSM 后端做。小程序端登录代码常见写法// pages/mine/mine.js login() { wx.login({ success: async (res) { if (res.code) { // 把 code 发给后端后端换 openid 并返回登录状态 const loginRes await new Promise((resolve) { wx.request({ url: http://localhost:8080/api/user/login, method: POST, data: { code: res.code }, success: resolve }) }) if (loginRes.data.code 200) { // 把 token 存入本地后续请求带上 wx.setStorageSync(token, loginRes.data.data.token) } } } }) }后端收到 code 后做的事可以概括成三步调微信jscode2session接口换 openid用 openid 查 user 表查不到就插入一条新用户查到就更新最近登录时间然后生成一个 token 返回前端。这里用 token 而不是直接暴露 openid是避免每次请求都拿 openid 当凭证也方便后端做登录拦截。答辩被问「token 怎么生成的」你至少要能说出「用 UUID 或 JWT存 Redis 或数据库」哪怕项目里简单用 UUID 放内存也比完全没有概念强。再说获取手机号。小程序的button组件有一个open-typegetPhoneNumber属性用户点击授权后前端会拿到一个加密的手机号数据或一个 code需要后端配合解密或换号。这个接口有个硬性限制只有企业主体的小程序才能正常获取用户手机号个人主体的开发版和体验版调用会报错。如果你做毕设用的是个人主体小程序建议在用户表里保留一个手动输入手机号的入口或者用「模拟手机号」方式把获取手机号的完整逻辑写进论文但不在演示时死磕。展示时可以说「生产环境这里会走微信手机号快速验证组件」这句话本身就是加分项。3.3 购物车与拼团下单后端落库与前端防重复的配合购物车有两种实现路线存在小程序本地 storage或存在后端数据库表。很多前端出身的同学习惯第一种因为省接口。但毕设不推荐本地 storage原因有两个一是换设备购物车就丢了论文的「系统功能」没法写购物车表设计二是后端 cart 表能参与到订单流程里下单时直接从库读购物车生成订单逻辑上更顺。用后端购物车加购接口长这样// 加购幂等的关键在于先查后插 addToCart(product) { wx.request({ url: http://localhost:8080/api/cart/add, method: POST, data: { productId: product.id, quantity: 1 }, success: (res) { if (res.data.code 200) { wx.showToast({ title: 已加入购物车, icon: success }) } } }) }后端加购接口的常规逻辑是「先查 cart 表里有没有同一用户同一商品的记录有就数量加一没有才插入新记录」。如果你在 mapper 里直接写INSERT INTO cart ...用户每点一次就多一条脏数据购物车列表会看到一排相同商品。这就是接口幂等性的基础理解答辩时可以主动讲出来。从购物车到订单还有一个隐藏问题下单按钮被用户快速双击会发出两次请求产生两条一模一样的订单。前端层面的解决是点击后立即把按钮设为 disabled并显示 loading 状态这在小程序里是常规操作button bindtapsubmitOrder disabled{{submitting}} loading{{submitting}} {{submitting ? 提交中 : 立即下单}} /button但前后端分离的项目里防重复不能只靠前端按钮。后端下单接口常见的做法是生成唯一订单号order_no并加唯一索引生成规则用「时间戳 用户ID 随机数」重复提交时第二次插入会因为唯一索引冲突失败返回「订单已提交请勿重复操作」。这是在 MySQL 层面兜底比任何后端判断都可靠。商品规格选择这类交互小程序里用radio-group组件就能实现注意在 change 事件里取到的值是 radio 的 value不是 index。4. 把交付源码跑成自己的系统建库、导项目和文档对照源码交付物和你自己从零搭的项目有个关键差异你不会逐行写过它。所以「跑起来」不是双击就行而是要主动把它变成有实感的东西。这章按顺序讲三件事数据库文件怎么导入、SSM 工程怎么导入 IDEA 并部署到 Tomcat、以及开题报告等文档到底怎么配合源码改。每一步都是为了同一个目标——答辩时被问到的任何细节你都能在源码里找到对应的位置。4.1 建库与初始化数据MySQL 命令行怎么执行 SQL 文件交付物里的数据库文件一般是一个.sql脚本里面包含了建库语句、建表语句和初始数据。拿到后先在本地建库并导入最常见的两条命令如下# 登录 MySQLroot 密码按自己环境改 mysql -uroot -p # 登录后执行建库库名按项目文档来通常叫 community_group CREATE DATABASE community_group DEFAULT CHARACTER SET utf8mb4; # 退出后用 source 导入 SQL 文件 mysql -uroot -p community_group /path/to/community_group.sql或者直接在 MySQL 命令行里用source /path/to/community_group.sql;也可以效果一样。这里要注意字符集建库时指定utf8mb4否则商品名里的生僻字和 emoji 会变成问号。导入完成后用SHOW TABLES;确认表数量再用SELECT COUNT(*) FROM product;看初始数据是不是空的。交付源码的数据库一般都会带几条商品和团购活动的初始数据这是演示的基础如果导入后是空的多半是 SQL 文件里没有INSERT语句需要自己补几条数据否则小程序端打开首页是白屏。顺带提一句我一般不建议为了这个毕设专门用 Docker 跑 MySQL。Docker 虽然装起来快但端口映射、容器重启后数据持久化这些概念对没接触过的学生来说多了一层变量出了问题更难排查。本地直接装 MySQL 服务Windows 下走安装包下一步到底macOS 下用 Homebrew 一条命令反而最省心。4.2 IDEA 导入 SSM 项目并部署到 Tomcatjdbc.properties 三个必改项SSM 项目导入 IDEA 的常规流程是File - New - Project from Existing Sources选到项目根目录里的pom.xmlMaven 会自动拉依赖。第一次导入会下载大量 jar 包耗时长是正常的只要右下角没有报红就继续等。导入后第一件事不是启动而是改数据库连接配置这个文件通常叫jdbc.properties在src/main/resources下内容长这样jdbc.drivercom.mysql.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/community_group?useUnicodetruecharacterEncodingutf8 jdbc.usernameroot jdbc.password123456这里三个必改项要检查清楚。第一jdbc.password必须改成你自己 MySQL 的密码这也是新手最常忽略的启动时报Access denied for user才想起来。第二jdbc.driver要看 pom.xml 里的 mysql-connector-java 版本5.x 用com.mysql.jdbc.Driver8.x 用com.mysql.cj.jdbc.Driver写错直接ClassNotFoundException。第三jdbc.url里如果同时用了 MySQL 8.0必须加两个参数serverTimezoneAsia/Shanghai和useSSLfalse。时区参数不加启动时会报The server time zone value is unrecognizeduseSSL 不加控制台会刷一堆 SSL 警告虽然不影响功能但答辩演示时很掉价。这三个参数整理成一张表改的时候逐项核对参数位置常见错误解决方式jdbc.password默认密码与本地不符报 Access denied改为本机 MySQL 实际密码jdbc.driverMySQL 8.0 用了 5.x 驱动名报 ClassNotFound按 pom.xml 版本换com.mysql.cj.jdbc.Driverjdbc.url8.0 缺时区与 SSL 参数追加serverTimezoneAsia/ShanghaiuseSSLfalse部署到 Tomcat 时IDEA 里点 Run - Edit Configurations新增一个 Tomcat Server - LocalDeployment 里选 war exploded 包Application context 改成/这样访问路径就是http://localhost:8080而不是http://localhost:8080/项目名_war_exploded省得小程序端 url 还要拼接。启动成功的判断标准是 Tomcat 控制台出现Started且没有红色 Exception然后浏览器打开后端地址能看到登录接口返回一个 JSON 格式的错误信息因为没带参数这就说明后端已经活了。如果启动失败先去logs/catalina.out或 IDEA 控制台找第一条Caused by那一行才是真正的病根。4.3 开题报告、毕业论文、答辩 PPT 与视频演示四份文档怎么配合源码改交付物里这四份文档的作用不一样但有一条共同原则必须以你手上这份源码为准不能反过来拿文档去套代码。拿到后先看论文里的功能模块图再对照源码里的包结构正常的对应关系是controller 包对应「系统接口设计」那一章service 包对应「业务逻辑设计」sql文件里的建表语句对应「数据库设计」。如果发现论文里的表名或者字段和实际 SQL 文件对不上修改文档永远比改代码成本低尤其是表名这种一改要牵连 Mapper 的东西能不碰就不碰。开题报告的核心任务是「可行性分析」和「技术路线」这两部分几乎可以直接从源码的技术栈抄答案前端微信小程序原生框架后端 SSM 分三层数据库 MySQL开发工具 IDEA 微信开发者工具 Navicat。这里有个常见盲区开题报告的完成时间通常比最终代码早一两个月所以报告里如果写的是「系统将采用 Spring Boot」就属于明显失误不一定要重写报告但论文里必须和源码保持一致。毕业论文里最容易拿分也最好改的是「系统实现」章节。把源码跑通后按论文的功能模块顺序逐一截图替换掉文档里的示意图截图内容最好是小程序页面 后端接口返回的 JSON 放在同一张图里答辩老师一看就知道你真的跑过。视频演示同理录屏时覆盖一条完整链路进入首页 - 选商品 - 加购物车 - 提交订单 - 在我的订单里看到这条记录整个过程控制在三分钟内不要加音乐不要加转场老师看重的是能不能对上号。答辩 PPT 则是在论文框架上进一步精简每页放一个功能点加一张截图技术架构页用一张图把「微信小程序 - SSM - MySQL」画清楚即可。记住一个判断标准PPT 上出现的每一个技术名词你都要能接住追问。如果写不了三层握手就别说 TCP讲不清 MyBatis 缓存机制就别写「集成 Redis 缓存」那是给自己挖坑。5. 本地联调踩坑与排查域名校验、MySQL 8.0 与 MyBatis 映射的五个典型问题跑这套项目时超过一半的报错集中在五个固定位置。这些问题不是你的代码写得不对而是「环境规则」和「框架边界」导致的我把它们按现象、原因、解决的顺序写在下面遇到时可以一条条对照。5.1 小程序请求报「url not in domain list」本地调试的一个开关现象在微信开发者工具里打开项目首页请求http://localhost:8080时报错request:fail url not in domain list页面白屏。原因微信小程序对请求地址有安全管控正式环境只允许请求已配置的合法域名且必须是 HTTPS。开发环境的本地地址http://localhost不在任何域名白名单里于是开发者工具默认拦掉。解决点击开发者工具右上角「详情」-「本地设置」勾选「不校验合法域名、web-view业务域名、TLS 版本以及 HTTPS 证书」。这一步只影响开发者工具不影响真机预览——真机预览时手机访问的是你本机电脑需要在同一个网络里并且也要在项目配置里打开同样的跳过校验选项。提交审核上线时这个开关必须关掉换成在微信公众平台配置你真正备案过的 HTTPS 域名这里提前知道就行。5.2 MySQL 8.0 驱动类找不到和时区报错版本对齐问题现象Tomcat 启动时报java.lang.ClassNotFoundException: com.mysql.jdbc.Driver或者报The server time zone value йʱ is unrecognized。原因pom.xml 里依赖的是 mysql-connector-java 8.x但jdbc.properties里 driver 还写着老版本的com.mysql.jdbc.Driver8.x 里这个类被改名为com.mysql.cj.jdbc.Driver。时区报错则是 MySQL 8.0 对连接串里的时区参数是强校验的不写就报。解决驱动类名改为com.mysql.cj.jdbc.Driver连接串补齐?serverTimezoneAsia/ShanghaiuseSSLfalse。顺手检查 pom.xml 里 MySQL 驱动的版本号如果依赖是 5.1.x 而本机数据库是 8.0尽量把依赖升到 8.0.x否则即使驱动类名改对了也可能因为旧版驱动不支持新认证方式报错。5.3 MyBatis 的 resultType 和 resultMap联表查询返回 null现象订单列表接口能通但返回的 JSON 里orderItems字段是 null或者商品名称不显示。原因查询订单时需要把订单明细一起返回代码里用了resultTypeOrderVO但 OrderVO 里有一个ListOrderItem嵌套对象resultType 的自动映射只处理平铺字段遇到嵌套集合根本不知道往哪塞于是静默置 null。这是 resultType 和 resultMap 的核心边界单表查询用 resultType 映射省事涉及关联对象必须用 resultMap 显式声明。解决在 Mapper XML 里加一个resultMap指定collection propertyorderItems ofTypeOrderItem把子查询的列一一对应到集合的字段上。如果嫌 resultMap 繁琐另一个常见做法是写一个扁平化的查询 VO把商品名、数量、价格全部查成一行前端展示时自己拼装这个方案适合订单里商品数量少、结构固定的场景。5.4 快速双击下单生成重复订单唯一约束兜底现象演示时手快点了两次「立即下单」订单列表里出现两条内容完全一样的订单数据看着很假。原因前端按钮没有加 loading 防连点后端下单接口也没有防重逻辑两次请求都正常执行了插入操作。解决前端按钮在请求期间设置disabled和loading后端在下单逻辑里生成唯一订单号order_no字段已经加了 UNIQUE 索引。同一用户同一毫秒内生成相同订单号的概率极低第二次插入会因为唯一索引冲突抛异常接口捕获后返回「订单已提交」的提示。数据上如果已经产生了重复脏数据写一条DELETE FROM orders WHERE ...手动清掉就可以但根子还是要靠索引兜底——这也是最常见的血泪经验前端限制是体验问题后端约束才是数据正确性的最后一道门。5.5 setData 大数组导致页面卡顿分页与懒加载现象商品列表拉到 100 条以后滑动卡顿加载新数据时页面白一下。原因小程序setData会把数据从逻辑层传到渲染层是一个完整的通信过程。一次性把几百条商品全部setData数据量越大开销越大卡顿是必然的。解决接口层做分页前端每次请求 pageSize10 或 20用concat追加而不是覆盖。图片渲染加lazy-load属性只在滚动到可视区附近才下载。还有一个细节不要把后端返回的整包数据直接塞进 data比如每件商品的description长文本就很容易超过渲染压力列表页只保留 name、price、图片地址这几个展示字段点进详情页再请求完整信息。6. 验证登录链路与留后路抓包确认接口数据再看 SSM 到 Spring Boot 的迁移项目能跑通之后我建议你做一件「超额」的事把登录这条链路用抓包工具完整看一遍。常见做法是用 Charles 这类 HTTP 调试工具在电脑上启动后配置好端口微信开发者工具里的请求会自动经过它。这样你能看到小程序发给后端的请求体长什么样、后端返回的 JSON 结构是什么、token 放在 header 还是 body 里。这一步的价值不在于「会用一个工具」而在于答辩时如果老师问「wx.login 之后到底发生了什么」你能把 code 换 openid 的交互过程画出时序图而不是背概念。需要注意抓取 HTTPS 请求需要在本机安装并信任 Charles 的 CA 证书这是开发环境的常规操作只针对你自己的调试流量。如果不想引入抓包工具用 Postman 直接调后端接口也能达到同样的验证效果只是看不到小程序真实传参。有余力的话可以提前了解 SSM 往 Spring Boot 迁移的路径这是此项目最有价值的延伸方向。Mapper 接口和 XML 完全不用动Service 层也基本原样保留主要改动集中在三个地方pom.xml 把 spring-webmvc、mybatis-spring 等依赖替换成 spring-boot-starter-web 和 mybatis-spring-boot-starterapplicationContext.xml、spring-mvc.xml里的配置改写成application.yml的spring.datasource和mybatis.mapper-locations配置Controller 类上把Controller换成RestControllerweb.xml里的 DispatcherServlet 配置直接删除由内嵌 Tomcat 接管。改动量对已经写完 SSM 的人来说大概半天但论文里可以多写一小节「系统扩展性设计」答辩时主动提到这个方向属于明显的亮点。最后说一点个人教训。当年我做毕设拿到类似的一套代码和文档图省事没去核对论文和源码的一致性结果答辩时老师照着论文里的架构图问「这个模块对应代码里哪个包」我盯着 IDE 里的目录结构答不上来场面一度很尴尬。后来学聪明了拿到任何交付源码先把文档里的功能模块图、数据库表、环境版本这三样和代码逐一核对对不上的地方改文档花不了两小时但能让答辩的底气完全不同。这个习惯我一直保持到现在接手任何项目的第一件事始终是「文档和代码对齐」。这套社区团购小程序的硬骨架不错业务链路完整技术栈也好讲花一周时间把它跑通、改顺、讲明白你的毕业设计会是一份拿得出手的作品。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑