拓冰建站拓冰建站
首页 / 资讯中心 / 正文

微信小程序+SSM校园二手交易平台毕业设计:从架构到避坑全指南

简介这份毕业设计资源面向高校计算机相关专业学生与Java全栈初学者提供一套完整的大学生闲置物品交易小程序实现方案可用于课程设计、毕业设计或小程序开发练手。项目采用微信小程序前端搭配SSM框架与MySQL数据库划分管理员、卖家、用户三类角色覆盖商品发布、购买、商品类型与广场管理等核心业务模块并附有毕业论文与视频演示便于理解系统分析与数据库设计思路。资源包共1180个文件约51.16MB包含127个Java后端源码、137个Vue组件、160个JS脚本、72个WXML与74个WXSS小程序页面文件以及PNG、SVG等界面素材和SQL脚本、配置文件结构完整便于二次开发。目前已有162人学习适合需要完整赛题方案、可运行源码与配套文档的读者参考借鉴。1. 大学生闲置物品交易小程序从选题到跑通一套能写进毕业设计的技术方案每年毕业季计算机相关专业的选题里总有一类特别稳的方向——校园二手交易平台。需求真实、场景清晰、技术栈成熟答辩时老师也容易理解。但真正动手做的时候很多人卡在第一步微信小程序前端怎么和 SSM 后端对接MySQL 表怎么设计才够用又不臃肿论文里的系统架构图到底该画哪些模块这个标题对应的是一套完整的毕业设计交付物微信小程序端 SSM 后端 MySQL 数据库 论文 演示视频。我做过几套类似的东西也帮人排查过不少翻车现场。常见的问题不是技术本身有多难而是前后端联调时参数对不上、数据库字段类型选错导致中文乱码、小程序请求封装没做好导致每个页面都在重复写 wx.request。这套方案适合谁如果你是计算机、软件工程、信息管理相关专业的应届生需要在一个月内完成一个能演示、能写论文、能答辩的项目那这条路线是经过验证的。下面按实际开发顺序把每个环节拆开讲。2. 技术选型与整体架构为什么是微信小程序 SSM 而不是别的2.1 小程序端选型原生开发还是 uniapp微信小程序开发目前主流两条路原生 WXML/WXSS/JS 和 uniapp 跨端框架。毕业设计场景下我一般建议用原生。原因很直接SSM 后端返回的是 JSON原生小程序的 wx.request 直接就能用不需要额外适配层。uniapp 虽然能一套代码多端发布但它的条件编译和生命周期在小程序端有坑调试时容易把简单问题复杂化。原生小程序的目录结构清晰pages 放页面utils 放工具函数app.js 管全局状态。对于闲置物品交易这种功能模块首页列表、发布商品、商品详情、个人中心、订单管理原生足够覆盖。而且答辩时老师问“你这个请求怎么发的”你能直接指出 wx.request 的封装文件比解释 uniapp 的编译产物要轻松。2.2 后端选型SSM 的适用边界SSM 是 Spring SpringMVC MyBatis 的缩写。这套组合在毕业设计里出现频率极高原因是Spring 的 IOC 和 AOP 概念好写论文SpringMVC 的注解开发上手快MyBatis 的 XML 映射适合展示 SQL 能力。但要注意SSM 不是 Spring Boot。SSM 需要手动配置 web.xml、applicationContext.xml、spring-mvc.xmlTomcat 要单独部署。很多教程直接给 Spring Boot 的代码你复制过来发现没有启动类这就是没分清。如果你的学校要求必须体现“框架整合能力”SSM 是合适的。如果只是想做功能Spring Boot 更省事。但既然标题写的是 SSM下面所有配置都按 SSM 来。2.3 数据库设计几张表能撑起一个交易流程MySQL 表设计不需要太复杂但几个核心实体必须覆盖用户、商品、分类、订单、收藏。下面是我常用的最小可用表结构字段类型和索引都经过实际跑通。-- 用户表 CREATE TABLE user ( id int(11) NOT NULL AUTO_INCREMENT, openid varchar(64) DEFAULT NULL COMMENT 微信openid, nickname varchar(64) DEFAULT NULL, avatar varchar(255) DEFAULT NULL, phone varchar(20) DEFAULT NULL, create_time datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY idx_openid (openid) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; -- 商品表 CREATE TABLE goods ( id int(11) NOT NULL AUTO_INCREMENT, user_id int(11) NOT NULL, category_id int(11) DEFAULT NULL, title varchar(128) NOT NULL, description text, price decimal(10,2) DEFAULT 0.00, images varchar(1024) DEFAULT NULL COMMENT 逗号分隔图片路径, status tinyint(4) DEFAULT 1 COMMENT 1在售 2已售 3下架, create_time datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY idx_user (user_id), KEY idx_category (category_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; -- 订单表 CREATE TABLE orders ( id int(11) NOT NULL AUTO_INCREMENT, order_no varchar(32) NOT NULL, goods_id int(11) NOT NULL, buyer_id int(11) NOT NULL, seller_id int(11) NOT NULL, amount decimal(10,2) DEFAULT 0.00, status tinyint(4) DEFAULT 1 COMMENT 1待确认 2已完成 3已取消, create_time datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY idx_order_no (order_no) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;字符集统一用 utf8mb4不要用 utf8。utf8 在 MySQL 里是阉割版存 emoji 会报错而微信昵称里带 emoji 太常见了。价格用 decimal 不用 float避免 0.10.2 这种精度问题。images 字段用逗号分隔存多张图路径毕业设计够用不用单独建图片表。注意openid 字段必须加唯一索引。同一个微信用户重复插入会导致数据混乱这个坑我在早期项目里踩过。3. 后端接口开发从 MyBatis 映射到 Controller 返回3.1 MyBatis 映射文件与 DAO 层SSM 里 MyBatis 负责 SQL 映射。先写实体类再写 Mapper 接口最后写 XML。以商品查询为例// GoodsMapper.java public interface GoodsMapper { ListGoods selectByCategory(Param(categoryId) Integer categoryId, Param(keyword) String keyword); int insertGoods(Goods goods); Goods selectById(Param(id) Integer id); }!-- GoodsMapper.xml -- mapper namespacecom.campus.dao.GoodsMapper select idselectByCategory resultTypecom.campus.entity.Goods SELECT * FROM goods WHERE status 1 if testcategoryId ! null AND category_id #{categoryId} /if if testkeyword ! null and keyword ! AND title LIKE CONCAT(%, #{keyword}, %) /if ORDER BY create_time DESC /select insert idinsertGoods useGeneratedKeystrue keyPropertyid INSERT INTO goods (user_id, category_id, title, description, price, images) VALUES (#{userId}, #{categoryId}, #{title}, #{description}, #{price}, #{images}) /insert /mapperuseGeneratedKeystrue和keyPropertyid必须加否则插入后拿不到自增主键前端发布商品后跳转详情页会没有 ID。if标签做动态 SQLcategoryId 为空时查全部不为空时按分类过滤。LIKE 用 CONCAT 拼接不要用%${keyword}%那是 SQL 注入的入口。3.2 Controller 层与统一返回格式Controller 负责接收请求、调用 Service、返回 JSON。建议封装一个统一返回类避免每个接口返回结构不一致。// Result.java public class ResultT { private int code; private String msg; private T data; // getter/setter 省略 public static T ResultT success(T data) { ResultT r new Result(); r.code 200; 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; } }// GoodsController.java RestController RequestMapping(/api/goods) public class GoodsController { Autowired private GoodsService goodsService; GetMapping(/list) public ResultListGoods list(RequestParam(required false) Integer categoryId, RequestParam(required false) String keyword) { ListGoods list goodsService.findByCondition(categoryId, keyword); return Result.success(list); } PostMapping(/publish) public ResultInteger publish(RequestBody Goods goods) { if (goods.getTitle() null || goods.getTitle().trim().isEmpty()) { return Result.error(标题不能为空); } int id goodsService.publish(goods); return Result.success(id); } }RestController等于Controller ResponseBody返回对象自动转 JSON。RequestBody接收前端 JSON 数据对应小程序的Content-Type: application/json。如果前端用 form 表单提交这里要改成RequestParam逐个接收。3.3 跨域配置小程序请求为什么报 403小程序开发时本地调试的域名是localhost但微信开发者工具默认校验合法域名。解决办法是在开发者工具里勾选“不校验合法域名”。但后端也要配 CORS否则浏览器端测试会 403。// 在 spring-mvc.xml 里加 mvc:cors mvc:mapping path/api/** allowed-origins* allowed-methodsGET,POST,PUT,DELETE allowed-headers* allow-credentialstrue/ /mvc:corsallowed-origins*和allow-credentialstrue同时用会冲突浏览器会拒绝。如果不需要携带 cookie把allow-credentials设为 false。小程序请求不涉及浏览器同源策略但开发者工具里的网络请求走的是 Chromium 内核所以 CORS 还是要配。4. 小程序端开发请求封装、页面跳转与图片上传4.1 请求封装一次写好处处调用原生小程序的wx.request是回调风格每个页面都写一遍太啰嗦。封装成 Promise 后配合 async/await 会清爽很多。// utils/request.js const BASE_URL http://localhost:8080/api; function request(options) { return new Promise((resolve, reject) { wx.request({ url: BASE_URL options.url, method: options.method || GET, data: options.data || {}, header: { Content-Type: application/json, token: wx.getStorageSync(token) || }, success(res) { if (res.data.code 200) { resolve(res.data.data); } else { wx.showToast({ title: res.data.msg || 请求失败, icon: none }); reject(res.data); } }, fail(err) { wx.showToast({ title: 网络异常, icon: none }); reject(err); } }); }); } module.exports { get: (url, data) request({ url, method: GET, data }), post: (url, data) request({ url, method: POST, data }) };BASE_URL在开发阶段指向本地 Tomcat上线要换成备案域名。token从缓存取登录后写入。success里判断code 200才 resolve否则统一弹提示。这样页面里只需要const res await request.get(/goods/list, { categoryId: 1 })。4.2 图片上传wx.uploadFile 与后端 MultipartFile发布商品要传图小程序用wx.uploadFile后端用MultipartFile接收。// 选择图片并上传 wx.chooseImage({ count: 3, success(res) { const tempPaths res.tempFilePaths; tempPaths.forEach(path { wx.uploadFile({ url: BASE_URL /upload, filePath: path, name: file, success(upRes) { const data JSON.parse(upRes.data); if (data.code 200) { images.push(data.data); } } }); }); } });// UploadController.java PostMapping(/upload) public ResultString upload(RequestParam(file) MultipartFile file) { if (file.isEmpty()) { return Result.error(文件为空); } String fileName System.currentTimeMillis() _ file.getOriginalFilename(); String filePath /upload/ fileName; File dest new File(filePath); if (!dest.getParentFile().exists()) { dest.getParentFile().mkdirs(); } try { file.transferTo(dest); return Result.success(/static filePath); } catch (IOException e) { return Result.error(上传失败); } }name: file必须和后端RequestParam(file)一致不一致会报 400。上传后的路径要映射成静态资源访问在 spring-mvc.xml 里配mvc:resources mapping/static/** location/upload//。4.3 页面跳转与参数传递小程序页面跳转用wx.navigateTo参数拼在 URL 上。详情页接收参数在onLoad里。// 列表页跳详情 wx.navigateTo({ url: /pages/detail/detail?id item.id }); // 详情页 onLoad onLoad(options) { const id options.id; this.loadDetail(id); }options.id拿到的是字符串如果后端接口需要 int记得parseInt。这个细节不注意后端会报类型转换异常。5. 避坑与排查那些答辩前夜还在改的 bug5.1 中文乱码数据库、连接串、响应编码三处都要查现象商品标题存进去是问号或者返回给小程序变成\u4e2d\u6587。原因MySQL 表字符集不是 utf8mb4或者 JDBC 连接串没指定编码或者 SpringMVC 的 StringHttpMessageConverter 默认用 ISO-8859-1。解决三处同时改。数据库ALTER TABLE goods CONVERT TO CHARACTER SET utf8mb4;JDBC URL 加?useUnicodetruecharacterEncodingutf8spring-mvc.xml 里配mvc:annotation-drivenmvc:message-convertersbean classorg.springframework.http.converter.StringHttpMessageConverterproperty namedefaultCharset valueUTF-8//bean/mvc:message-converters/mvc:annotation-driven。5.2 小程序请求返回 404路径拼错了还是 Tomcat 没起现象开发者工具 Network 面板显示 404。原因BASE_URL 写的是http://localhost:8080/api但后端 Controller 的RequestMapping是/goods实际路径应该是/api/goods/list。或者 Tomcat 的 context path 不是/而是/ssm。解决先确认 Tomcat 启动日志里的 context path再核对 Controller 的完整路径。在浏览器直接访问http://localhost:8080/api/goods/list能返回 JSON 说明后端没问题问题在小程序端。5.3 MyBatis 查询返回 null字段名和属性名没对上现象selectById返回对象但某个字段是 null。原因数据库字段是create_time实体类属性是createTime但 MyBatis 默认不开启驼峰映射。解决在 mybatis-config.xml 里加setting namemapUnderscoreToCamelCase valuetrue/。或者手动在 XML 里写resultMap做映射。推荐开驼峰省事。5.4 图片上传后访问 404静态资源映射没配现象上传成功返回路径但小程序image src加载不出来。原因上传的文件存在服务器磁盘但 SpringMVC 没有把该目录暴露为静态资源。解决spring-mvc.xml 加mvc:resources mapping/static/** locationfile:/upload//。注意 location 用file:前缀表示文件系统路径不是 classpath。5.5 订单重复提交前端按钮没防抖后端没做幂等现象用户快速点两次“立即购买”生成两笔订单。原因前端按钮没有 loading 状态后端没有唯一约束。解决前端点击后立即wx.showLoading并禁用按钮后端 order_no 用userId timestamp生成加唯一索引插入冲突时捕获异常返回“请勿重复提交”。6. 论文写作与答辩演示的收尾技巧论文部分系统架构图不要画得太花。三层架构表现层、业务层、数据层加一个部署图就够了。数据库表用 ER 图展示字段说明用表格列清楚。核心代码不要贴全文挑请求封装、MyBatis 动态 SQL、图片上传这三段每段配一段文字说明“为什么这样写”。演示视频建议按这个顺序录打开小程序首页 → 切换分类 → 搜索商品 → 查看详情 → 发布商品含选图上传→ 个人中心查看我的发布 → 下单 → 订单列表。全程控制在 3 分钟内不要录调试过程。答辩时老师最常问的三个问题你的 token 怎么生成的图片存在哪里订单状态怎么流转提前准备好答案。token 可以用 UUID 存 Redis毕业设计用 session 也行图片存本地磁盘路径写进数据库订单状态用 tinyint1 待确认、2 已完成、3 已取消前端根据状态显示不同按钮。我自己的习惯是答辩前一晚把整个流程在本地跑三遍每遍都从清空数据库开始。这样能发现自增 ID 不连续、时间格式不对、图片路径带中文等问题。希望帮到你。本文还有配套的精品资源点击获取
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门