恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
微信小程序+SSM+MySQL购物商城毕设实战指南
首页
资讯中心
/
微信小程序+SSM+MySQL购物商城毕设实战指南
微信小程序+SSM+MySQL购物商城毕设实战指南
发布时间:2026/10/6 8:17:35
简介本资源是一套面向计算机专业本科生的毕业设计实战项目基于微信小程序前端SSMSpringSpringMVCMyBatis后端MySQL数据库技术栈构建的完整购物商城系统适用于课程设计、毕设开题与答辩全流程支撑。资源包共791个文件35.98MB涵盖140个Java后端业务类、140个Vue组件含小程序WXML/WXSS/JS逻辑、125张PNG/JPG商品图、114个SQL与配置脚本、66个JS交互逻辑及4个MP4视频含开题讲解、论文演示与部署教程另有开题报告、论文视频、bat一键部署脚本等教学辅助材料。已有175人学习下载内容组织清晰模块划分明确——从前端页面结构、后端分层架构到数据库ER设计与初始化脚本均完整提供特别适合初学者理解电商系统核心功能商品管理、订单流程、用户权限、评价体系的代码实现与工程落地路径。1. 毕业设计选题落地为什么一个「微信小程序 SSM MySQL 购物商城」能稳过答辩、还能当简历硬通货你不是在做一个玩具 demo而是在交付一套可运行、可调试、可讲清楚技术链路闭环的工程级毕业作品。这个标题里的三个关键词——「微信小程序」是用户触达层必须真机扫码能用「SSMSpring SpringMVC MyBatis」是后端骨架得体现分层设计、事务控制、接口规范「MySQL」不是只建几张表而是要看到索引优化、外键约束、数据一致性保障。它解决的不是“能不能跑”而是“答辩老师问‘订单超卖怎么防’‘小程序登录态怎么续’‘MyBatis 为什么不用 XML 改用注解’时你能掏出源码指着某一行说‘我在这儿用了 Redis 分布式锁 数据库乐观锁双校验’”。适合两类人一是大三下刚定题、怕踩坑延期的本科生二是想用毕设项目直接投 Java 开发岗或小程序全栈岗的同学——因为这套组合拳覆盖了企业招聘 JD 中高频出现的「前后端分离」「RESTful 接口设计」「数据库建模」「小程序原生开发规范」四大硬指标。别被“开题报告”“论文视频”这些字眼带偏真正决定你能否顺利毕业、甚至拿到实习 offer 的是pom.xml里那 17 个关键依赖版本是否兼容、wx.request的header是否正确携带Authorization、Transactional注解是否真的生效了。2. 从零搭起可运行骨架微信小程序前端 SSM 后端 MySQL 数据库三端联调最小可行路径2.1 微信小程序端用原生框架快速构建首页商品列表购物车三页闭环微信小程序不等于 H5它的生命周期、网络请求、本地存储、页面路由都自成体系。我们不碰 uni-app 或 Taro就用官方原生方案确保答辩时老师用真机扫二维码能立刻看到效果。核心是三页index轮播分类导航、product-list商品瀑布流下拉加载、cart本地缓存提交订单。注意两个易错点一是app.json中tabBar的list必须按顺序写图标路径必须是本地相对路径不能是网络地址二是wx.request默认不带 Cookie登录态必须靠header: { Authorization: wx.getStorageSync(token) }手动透传。// app.json 关键配置注意 tabBar 图标尺寸必须为 81x81px { tabBar: { list: [ { pagePath: pages/index/index, text: 首页, iconPath: assets/icons/home.png, selectedIconPath: assets/icons/home-active.png }, { pagePath: pages/cart/cart, text: 购物车, iconPath: assets/icons/cart.png, selectedIconPath: assets/icons/cart-active.png } ] } }提示小程序顶部导航栏高度不是固定值iOS 和 Android 不同真机调试务必用wx.getSystemInfoSync().statusBarHeight动态计算否则 iPhone X 以上机型状态栏会遮挡内容。我在app.js的onLaunch里统一存到 globalData所有页面 onLoad 时读取。2.2 SSM 后端用 Spring Boot 2.7.x MyBatis-Plus 快速搭建 RESTful 接口服务别再手写web.xmlspring-mvc.xml那套老 SSM 了。毕业设计时间紧直接上 Spring Boot 2.7.x兼容 JDK 8避免 JDK 17 兼容问题用 MyBatis-Plus 替代原生 MyBatis——它能省掉 70% 的 CRUD XML 映射文件。关键依赖如下注意版本对齐!-- pom.xml 核心依赖 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId version2.7.18/version /dependency dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.3.1/version /dependency dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version8.0.33/version /dependency后端接口命名严格遵循 RESTful 规范GET /api/products查商品列表、POST /api/orders创建订单、GET /api/orders/{id}查单个订单。Controller 层只做参数校验和结果封装业务逻辑全部下沉到 Service 层。比如下单接口Controller 只负责接收RequestBody OrderDTO orderDTO校验orderDTO.getItems()非空然后调orderService.createOrder(orderDTO)绝不写 SQL。2.3 MySQL 数据库按电商场景设计 6 张核心表附建表脚本与索引说明毕业设计的数据库不能只有user、product、order三张表。真实购物商城至少需要以下 6 张表形成闭环user用户、product商品、product_category分类、cart_item购物车项、order_header订单主表、order_item订单明细。重点看order_header表的设计CREATE TABLE order_header ( id bigint NOT NULL AUTO_INCREMENT COMMENT 主键, order_no varchar(64) NOT NULL UNIQUE COMMENT 订单号格式ORD20240520102030123456, user_id bigint NOT NULL COMMENT 用户ID, total_amount decimal(10,2) NOT NULL DEFAULT 0.00 COMMENT 总金额, status tinyint NOT NULL DEFAULT 1 COMMENT 状态1待支付2已支付3已发货4已完成5已取消, create_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, update_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY idx_user_status (user_id,status) COMMENT 用户状态联合索引用于我的订单列表查询, KEY idx_order_no (order_no) COMMENT 订单号单独索引用于根据订单号查单 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT订单主表;注意order_no字段加了UNIQUE约束这是防止并发下单生成重复订单号的底层保障idx_user_status是高频查询“我的订单”的命脉索引没它10 万订单数据一查就卡死。2.4 三端联调用 Postman 测试接口 小程序真机扫码 MySQL Workbench 查数据联调不是“前端调后端”而是验证整个数据流小程序发起请求 → Nginx/网关可选→ Spring Boot Controller → Service → MyBatis-Plus → MySQL 写入 → 小程序收到响应 → 页面刷新。步骤必须闭环用 Postman 发送POST http://localhost:8080/api/ordersBody 选 raw/JSON填入合法 JSON后端日志打印Order created: ORD20240520102030123456且 MySQL 中order_header表新增一行小程序中点击“去结算”触发相同请求真机扫码后能看到订单号弹窗用 MySQL Workbench 连接本地库执行SELECT * FROM order_header WHERE user_id 123 ORDER BY create_time DESC LIMIT 10;确认数据一致。这一步卡住90% 是跨域问题。Spring Boot 解决方案在Configuration类中加Bean WebMvcConfigurer重写addCorsMappings方法允许http://localhost:5000微信开发者工具端口和https://servicewechat.com真机域名。3. 毕业设计高危雷区SSM 小程序商城项目中 4 个让答辩老师当场皱眉的致命错误3.1 现象小程序登录成功但后续所有接口返回 401 Unauthorized原因后端用AuthenticationPrincipal获取当前用户但未配置 Spring Security 或 Shiro也未手动解析微信code换取openid并存入 session/Redis。更常见的是前端把token存在wx.setStorageSync(token, res.data.token)但每次wx.request都忘了在header中带上Authorization: Bearer token。解决后端提供/api/auth/login接口接收小程序传来的code调用微信https://api.weixin.qq.com/sns/jscode2session换取openid生成 JWT Token 返回前端全局 request 拦截器app.js中wx.addInterceptor自动注入 header后端用RequestHeader(Authorization) String authHeader提取 token并用JwtUtil.parseToken(authHeader)解析出openid。3.2 现象商品列表页下拉加载更多第二页开始数据重复或跳页原因前端用page1, size10分页但后端 MyBatis-Plus 的Page对象未设置orders排序字段导致 MySQL 默认排序不稳定InnoDB 索引顺序非物理顺序。当商品有新增/删除时第一页末尾商品可能在第二页开头再次出现。解决强制按create_time DESC, id DESC排序。后端接口代码必须显式指定PageProduct page new Page(current, size); page.addOrder(OrderItem.desc(create_time)).addOrder(OrderItem.desc(id)); PageProduct result productMapper.selectPage(page, wrapper);同时数据库product表create_time字段必须加索引KEY idx_create_time (create_time, id)。3.3 现象下单成功但数据库order_item表没数据或数量对不上原因Service 方法上Transactional注解失效。常见于方法是private、自调用A 方法调 B 方法B 加了Transactional但 A 和 B 在同一个类里、或者事务管理器没配对EnableTransactionManagement缺失或DataSourceTransactionManagerBean 名不是默认transactionManager。解决把下单逻辑拆成两个 public 方法createOrderHeader()和createOrderItems()前者负责写order_header后者循环写order_item并在createOrder()外层方法加Transactional(rollbackFor Exception.class)。用Transactional的rollbackFor显式指定回滚异常类型避免RuntimeException以外的异常不回滚。3.4 现象MySQL 中文乱码商品名称显示为????原因四个环节任一出错① MySQL 服务端字符集不是utf8mb4② 创建数据库时没指定CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci③application.yml中 JDBC URL 缺少?characterEncodingutf8mb4serverTimezoneAsia/Shanghai④ MyBatis-Plus 的GlobalConfig未开启dbConfig.setTableUnderline(true)虽不直接导致乱码但影响字段映射。解决四步全检MySQL 命令行执行SHOW VARIABLES LIKE character_set_%;确保character_set_server utf8mb4建库语句CREATE DATABASE shop_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;application.yml中 JDBC URLjdbc:mysql://localhost:3306/shop_db?useUnicodetruecharacterEncodingutf8mb4serverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrueuseSSLfalseMybatisPlusConfig.java中GlobalConfig设置dbConfig.setTableUnderline(true)。4. 让答辩老师眼前一亮3 个毕业设计加分项——从“能跑”升级到“专业级”4.1 订单超卖防护Redis 数据库乐观锁双保险实现附完整代码单纯数据库UPDATE product SET stock stock - 1 WHERE id ? AND stock 1在高并发下仍可能超卖。必须引入 Redis 预减库存 数据库最终校验。流程用户点击下单 → 先DECR stock:{productId}→ 若返回值 ≥ 0再走数据库扣减带version字段乐观锁→ 成功则生成订单失败则INCR回滚 Redis 库存。// ProductServiceImpl.java Transactional(rollbackFor Exception.class) public boolean createOrder(Long productId, Integer quantity) { // 1. Redis 预减库存 String redisKey stock: productId; Long remain redisTemplate.opsForValue().decrement(redisKey, quantity); if (remain 0) { redisTemplate.opsForValue().increment(redisKey, quantity); // 回滚 throw new RuntimeException(库存不足); } // 2. 数据库乐观锁扣减product 表需有 version 字段 UpdateWrapperProduct updateWrapper new UpdateWrapper(); updateWrapper.eq(id, productId) .gt(stock, quantity - 1) // stock quantity .setSql(stock stock - quantity); int updated productMapper.update(new Product(), updateWrapper); if (updated 0) { redisTemplate.opsForValue().increment(redisKey, quantity); // 再次回滚 throw new RuntimeException(库存更新失败请重试); } return true; }注意Redis key 必须带业务前缀stock:避免和其他模块冲突decrement操作是原子的无需额外加锁数据库UPDATE的WHERE条件必须包含stock quantity这是最终防线。4.2 小程序登录态持久化用wx.checkSession() 后端 Token 自动续期微信小程序wx.login()获取的code5 分钟有效但用户不可能每 5 分钟重新登录。解决方案前端在onShow时调wx.checkSession()若失效则静默重新wx.login()并传新code到后端换新 Token后端 Token 设 2 小时过期但每次接口请求时若 Token 剩余时间 30 分钟则在响应头中返回新 TokenX-Auth-Token前端自动更新本地存储。// utils/request.js 全局请求拦截 wx.request({ url: /api/products, header: { Authorization: getToken() }, success: (res) { const newToken res.header[X-Auth-Token]; if (newToken) { wx.setStorageSync(token, newToken); } } });后端在JwtFilter中判断token.getExpiresAt().getTime() - System.currentTimeMillis() 30 * 60 * 1000满足则生成新 Token 并塞入响应头。4.3 数据库敏感字段加密用户手机号、收货地址 AES 加密存储毕业设计若涉及真实用户信息明文存user.phone是重大安全隐患。必须用 AES-128-CBC 加密。MyBatis-Plus 提供TableField的typeHandler机制自定义AesTypeHandler// AesTypeHandler.java public class AesTypeHandler implements TypeHandlerString { private static final String KEY your-32-byte-aes-key-1234567890123456; private static final String IV 16-byte-iv-123456; Override public void setParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException { if (parameter ! null) { ps.setString(i, AesUtil.encrypt(parameter, KEY, IV)); } else { ps.setString(i, null); } } Override public String getResult(ResultSet rs, String columnName) throws SQLException { String encrypted rs.getString(columnName); return encrypted ! null ? AesUtil.decrypt(encrypted, KEY, IV) : null; } // ... 其他方法 }然后在User实体类中标注TableField(typeHandler AesTypeHandler.class) private String phone;提示AES 密钥KEY必须是 32 字节UTF-8 编码IV 是 16 字节密钥绝不能硬编码在代码里应放在application.yml的encrypt.key配置项中用Value(${encrypt.key})注入。5. 毕业设计交付物清单与答辩话术如何把“源代码”变成“技术叙事力”5.1 完整交付物结构5 个目录 3 份文档缺一不可你的压缩包不是代码堆砌而是有清晰叙事逻辑的工程包。按此结构组织答辩老师一眼看出你懂工程规范shop-mall-final/ ├── 01_source_code/ # 微信小程序源码含 project.config.json │ ├── miniprogram/ │ └── project.config.json ├── 02_backend_springboot/ # SSM 后端Spring Boot 项目 │ ├── src/main/java/com/example/shop/ │ └── pom.xml ├── 03_database/ # MySQL 脚本含建库、建表、初始化数据 │ ├── create_database.sql │ ├── init_data.sql # 插入测试商品、用户、分类 │ └── index_optimization.sql # 创建所有索引语句 ├── 04_document/ # 开题报告、论文、答辩 PPT │ ├── 开题报告_张三_20240520.docx │ ├── 毕业论文_张三_20240520.pdf │ └── 答辩PPT_张三_20240520.pptx └── 05_video_tutorial/ # 录屏教程MP4含操作演示讲解 ├── 1_小程序真机调试.mp4 ├── 2_SSM后端启动与接口测试.mp4 └── 3_数据库导入与数据验证.mp4注意project.config.json中appid必须填你自己的小程序 AppID开发版不能留空或写wx123456pom.xml中properties里java.version必须是1.8spring-boot.version是2.7.18版本号写死避免答辩时因环境差异编译失败。5.2 答辩 PPT 核心 3 页用技术决策代替功能罗列别放“系统有首页、商品页、购物车页”这种截图流水账。PPT 只需 3 页讲清技术深度第 1 页架构图 技术选型理由画一张三层架构图小程序 ↔ Nginx可选↔ Spring Boot ↔ MySQL在箭头旁标注技术点HTTPS JWT、RestTemplate Feign如用、Druid 连接池 监控、InnoDB 事务隔离级别 RR。下方用表格对比选型组件选项A选项B本项目选择理由前端框架uni-app原生小程序原生微信官方支持无兼容层性能可控答辩可现场真机演示ORMMyBatisMyBatis-PlusMyBatis-Plus自动生成 CRUD减少样板代码LambdaQueryWrapper类型安全第 2 页核心难点与解决方案聚焦 1 个最硬核问题比如“高并发下单超卖”。左侧放问题现象模拟 1000 用户抢购数据库记录超卖 3 单右侧放你的双保险方案Redis 预减 数据库乐观锁并贴出关键代码片段DECR和UPDATE ... WHERE stock ?。第 3 页可验证成果不放截图放可量化的证据✅ 小程序真机扫码3 秒内打开首页附录录屏时间戳✅ Postman 调用/api/products?page1size10响应时间 200ms附 Postman Console 截图✅ MySQLEXPLAIN分析SELECT * FROM order_header WHERE user_id123 AND status2typerefkeyidx_user_status证明索引生效5.3 答辩高频问题预演5 个必问 你的标准答案老师不会考你Autowired和Resource区别但会揪住你代码里的具体实现问到底Q微信登录为什么不用 OpenID 直接当用户 ID而要自己生成 UUIDA“OpenID 是微信对每个小程序的唯一标识同一用户在不同小程序 OpenID 不同无法跨小程序识别。我用openid appid生成 UUID 作为用户主键既保证唯一性又保留微信生态关联性未来扩展多小程序共用账户时只需改生成规则。”QMyBatis-Plus 的saveBatch()和循环save()有什么区别你订单明细为什么用循环插入A“saveBatch()在数据量大时会内存溢出且无法获取每条记录的主键。订单明细必须按顺序插入且order_item表order_id是外键需先有order_header.id。我用for循环 insertSelective()每条插入后item.setId(idGenerator.nextId())确保主键连续可追溯。”QMySQL 的utf8mb4和utf8到底差在哪为什么必须用前者A“MySQL 的utf8实际是utf8mb3最多存 3 字节字符不支持 emoji4 字节和部分生僻汉字。utf8mb4才是真正的 UTF-8。我建库时强制CHARACTER SET utf8mb4JDBC URL 加characterEncodingutf8mb4连起来才能保证用户昵称‘张三’不乱码。”QTransactional在 Service 方法上如果调用另一个没有Transactional的 DAO 方法事务还生效吗A“只要 DAO 方法在同一个 Service Bean 内被调用且 Service 方法有Transactional事务就生效。因为 Spring AOP 代理的是 Service Bean事务切面在代理对象上。但如果 DAO 是独立的RepositoryBean且被其他 Bean 调用就必须给 DAO 方法也加Transactional。”Q你的购物车是存在小程序本地还是后端为什么A“双端存储未登录时存在wx.setStorageSync(cart)登录后立即同步到后端cart_item表并清空本地。这样既保证用户体验离线可加购又保证数据一致性登录后所有设备购物车统一。同步逻辑在loginSuccess回调里触发用Promise.all()并发提交所有本地项。”我带过 12 届毕业设计最深的教训是答辩不是考试是技术叙事。你不需要背下 Spring 源码但必须能指着pom.xml说清为什么选 2.7.18 不选 3.x能打开product_list.js讲出onReachBottom里this.setData({ loading: true })这行代码是为了防抖能对着OrderService.java解释Transactional(rollbackFor Exception.class)里Exception.class是为了捕获检查异常。这些细节比任何 PPT 动画都管用。希望帮到你。本文还有配套的精品资源点击获取