简介:这是一套面向高校计算机相关专业毕业生的Java毕业设计完整项目包,主题为基于SSM框架与微信小程序的中国剪纸文化展示系统,适合需要完成高分毕设、课程设计或自学SSM+小程序全栈开发的学生参考。资源共722个文件,压缩包约28.1MB,包含102个Java后端源码、101个Vue前端文件、22个wxss与21个wxml小程序页面文件,以及SQL数据库脚本、properties配置、yml配置等;同时附带PPT、开题报告、任务书、使用文档与4段mp4演示视频,另有svg、png等图片素材与字体文件支撑界面展示。该项目已通过导师指导与答辩评审,获得97分评价,在Windows 10/11环境下严格调试,下载即可运行,部署教程齐全。已有115人学习下载,读者可借此获得一套结构完整、可直接复用的毕设方案,涵盖后端接口、小程序端页面、数据库设计与答辩材料,便于快速理解项目架构并完成二次开发或课程设计任务。
1. 从一份 SSM + 微信小程序剪纸项目说起:它到底能帮你省下多少时间
如果你正在搜「Java毕业设计」,大概率已经翻过不少仓库,也见过那种只有几张截图、跑起来一堆报错的“半成品”。中国剪纸这个选题之所以被反复做,是因为它同时踩中了两个刚需:一是非遗文化类题目在答辩时天然有话说,二是 SSM + 微信小程序这套组合足够经典,导师一看就知道你确实写了后端和前端,不是纯糊弄。但真正让人头疼的从来不是选题,而是把 Spring + SpringMVC + MyBatis 的 XML 配置、小程序端的登录态、图片上传、订单或收藏逻辑串成一条能演示的链路。这份「基于 SSM + 微信小程序的中国剪纸」项目,本质上就是把这套链路提前跑通了一遍,附带数据库脚本、开题报告、任务书、PPT 和演示视频。它适合两类人:一类是时间紧、需要快速搭出可演示系统的同学;另一类是想借这个壳子把 SSM 分层和小程序请求封装真正搞明白的人。下面我不谈虚的,直接按“怎么跑起来、参数怎么改、哪里容易翻车”来讲。
2. 把 SSM 后端跑起来:从建库到第一个接口返回 JSON
2.1 环境版本与依赖对齐,别让 JDK 和 Tomcat 打架
SSM 项目最玄学的地方就是“代码没问题,环境不对”。我一般会先把版本钉死,避免后面排查时怀疑人生。这个项目常见做法是 JDK 1.8 + Maven 3.6 + MySQL 5.7/8.0 + Tomcat 8.5,Spring 用 4.x 或 5.x 都行,但 MyBatis 和 Spring 的版本要能对上。如果你用 JDK 11 以上,注意老版本 Spring 的反射和 CGLIB 可能报IllegalAccessError,这不是代码错,是版本不匹配。
先在 MySQL 里建库,字符集用utf8mb4,否则剪纸名称里的生僻字或 emoji 会变问号:
-- 建库,字符集必须 utf8mb4,否则中文和特殊符号会乱码 CREATE DATABASE jianzhi DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE jianzhi; -- 导入项目自带的 .sql 文件,注意先关掉外键检查再导,避免表顺序问题 SET FOREIGN_KEY_CHECKS = 0; -- source /你的路径/jianzhi.sql; SET FOREIGN_KEY_CHECKS = 1;导入完成后,用SHOW TABLES;确认用户表、剪纸作品表、分类表、收藏或订单表都在。参数上重点看两处:数据库连接 URL 要加useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai,否则小程序传上来的中文会乱码;连接池如果用 Druid,初始连接数给 5 就够,毕业设计并发很低,给太大反而拖慢启动。
2.2 用 Maven 编译并部署到 Tomcat,确认接口能通
依赖对齐后,编译和部署就是标准动作。我习惯先在命令行跑一遍,确认不是 IDE 的锅:
# 清理并打包,跳过测试,毕业设计阶段测试类经常缺依赖 mvn clean package -DskipTests # 打包成功后 target 下会有 war 包,复制到 Tomcat 的 webapps 目录 cp target/*.war $TOMCAT_HOME/webapps/jianzhi.war # 启动 Tomcat,前台运行方便看日志 $TOMCAT_HOME/bin/catalina.sh run启动日志里重点看三行:Spring 容器是否刷新成功、MyBatis 是否打印了 Mapper 绑定、Tomcat 是否在 8080 端口监听。如果报No qualifying bean,多半是applicationContext.xml里的包扫描路径没覆盖到你的 Service;如果报Invalid bound statement,就是 Mapper XML 的 namespace 或方法名对不上。接口验证别急着开小程序,先用浏览器或 Postman 访问一个列表接口,比如http://localhost:8080/jianzhi/paper/list,能返回 JSON 数组就说明后端这条链路通了。这一步是整个项目的地基,地基不稳,后面小程序调半天都是白费。
3. 微信小程序端怎么接:登录、请求封装与图片展示
3.1 小程序登录换 openid,别把 session_key 传到前端
微信小程序的登录流程是固定套路:前端调wx.login拿 code,后端拿 code + appid + secret 去换 openid 和 session_key。这里有个血泪经验:session_key 绝对不能返回给前端,它相当于用户数据的解密密钥,泄露了就能解出手机号等敏感信息。常见做法是后端生成一个自定义 token(比如 UUID 或 JWT),把 openid 和 token 的映射存到 Redis 或数据库,前端只拿 token。
// 小程序端登录,只拿 code,不碰 session_key wx.login({ success: (res) => { if (res.code) { wx.request({ url: 'http://localhost:8080/jianzhi/user/login', method: 'POST', data: { code: res.code }, success: (resp) => { // 后端只返回 token 和基础用户信息 wx.setStorageSync('token', resp.data.data.token); } }); } } });后端换 openid 的接口里,appid 和 secret 写在配置文件,不要硬编码在 Java 里。参数上注意grant_type=authorization_code是固定的,code 只能用一次,用完就失效。如果你在本地调试,微信开发者工具里要勾选“不校验合法域名”,否则localhost请求会被拦。
3.2 请求封装与图片上传,路径拼接是最容易翻车的地方
小程序里如果每个页面都写一遍wx.request,后期改域名会改到崩溃。我一般会封一个request.js,统一加 token、统一处理错误码。图片上传是剪纸项目的核心,因为作品展示全靠图。上传用wx.uploadFile,后端用MultipartFile接收,存到本地磁盘或对象存储,数据库只存相对路径。
// 统一请求封装,自动带 token const request = (url, method, data) => { return new Promise((resolve, reject) => { wx.request({ url: 'http://localhost:8080/jianzhi' + url, method: method, data: data, header: { 'token': wx.getStorageSync('token') || '' }, success: (res) => { // 后端约定 code=200 才是成功,其他统一提示 if (res.data.code === 200) resolve(res.data.data); else { wx.showToast({ title: res.data.msg, icon: 'none' }); reject(res.data); } }, fail: reject }); }); };图片展示时,数据库存的是/upload/xxx.jpg,前端要拼成http://localhost:8080/jianzhi/upload/xxx.jpg。这里最常见的坑是路径里多了或少了斜杠,导致 404。参数上建议后端返回完整的可访问 URL,前端直接绑定,省得每个页面拼一次。另外小程序对图片有大小限制,单张建议压到 200KB 以内,否则列表页加载会卡到怀疑人生。
4. 数据库与核心表设计:剪纸作品、分类和用户怎么关联
4.1 三张核心表的字段与索引,别等查询慢了才加
剪纸项目的表不用多,但字段类型和索引要合理。用户表存 openid、昵称、头像;分类表存分类名和排序;作品表存标题、图片路径、分类 id、作者 id、创建时间。作品表和分类表用category_id关联,和用户表用user_id关联。查询列表时按创建时间倒序,所以create_time要加索引。
| 表名 | 关键字段 | 类型 | 说明 |
|---|---|---|---|
| user | id, openid, nickname, avatar | bigint, varchar(64), varchar(50), varchar(255) | openid 加唯一索引 |
| category | id, name, sort | int, varchar(30), int | sort 控制前端显示顺序 |
| paper | id, title, image, category_id, user_id, create_time | bigint, varchar(100), varchar(255), int, bigint, datetime | category_id 和 create_time 加索引 |
建表时注意image字段长度给够,有些同学存完整 URL 结果 255 不够用。如果要做收藏功能,再加一张collect表,用user_id + paper_id做联合唯一索引,防止重复收藏。参数上,create_time用datetime而不是timestamp,避免 2038 年问题,虽然毕业设计用不到那么久,但习惯要好。
4.2 用 MyBatis 写关联查询,resultMap 别偷懒用自动映射
作品列表通常要显示分类名和作者昵称,这就需要关联查询。MyBatis 里可以用resultMap手动映射,也可以用嵌套查询。我一般推荐一次性的LEFT JOIN,性能更好,也避免 N+1 问题。
<!-- PaperMapper.xml 片段:关联分类和用户,一次查完 --> <select id="selectPaperList" resultMap="PaperVoMap"> SELECT p.id, p.title, p.image, p.create_time, c.name AS category_name, u.nickname AS author_name FROM paper p LEFT JOIN category c ON p.category_id = c.id LEFT JOIN user u ON p.user_id = u.id ORDER BY p.create_time DESC LIMIT #{offset}, #{limit} </select> <resultMap id="PaperVoMap" type="com.jianzhi.vo.PaperVo"> <id column="id" property="id"/> <result column="category_name" property="categoryName"/> <result column="author_name" property="authorName"/> </resultMap>参数说明:offset是分页偏移量,limit是每页条数,前端传page和pageSize,后端算一下就行。注意resultMap里字段名和属性名不一致时一定要写<result>,别指望自动映射能猜对category_name到categoryName。如果查询结果为空,先看 SQL 在数据库里能不能跑出数据,再检查 MyBatis 的namespace和接口方法名是否一致。
5. 避坑与排查:那些让答辩现场翻车的细节
5.1 跨域和 403:小程序请求后端被拦
现象:小程序开发者工具里请求一直失败,控制台报request:fail或 403。原因通常是后端没配跨域,或者 SpringMVC 的拦截器把请求拦了。解决:在web.xml或配置类里加 CORS 过滤器,允许localhost和微信开发者工具的域名。如果用了拦截器做登录校验,记得放行/user/login这个接口,否则连登录都进不去。
5.2 图片上传后访问 404:路径映射没配
现象:上传成功,数据库也有路径,但小程序里图片显示空白,浏览器直接访问图片 URL 报 404。原因是 Tomcat 没有把上传目录映射为静态资源。解决:在 SpringMVC 配置里加<mvc:resources mapping="/upload/**" location="file:/你的上传目录/"/>,或者用 Nginx 做静态资源代理。注意location后面的路径要以斜杠结尾,否则会拼错。
5.3 中文乱码:从数据库到前端一路问号
现象:剪纸标题在数据库里正常,小程序里显示问号。原因可能是数据库连接没加characterEncoding=utf8,或者 Tomcat 的server.xml里 Connector 没加URIEncoding="UTF-8"。解决:三处一起改——数据库连接 URL、Tomcat Connector、小程序请求头content-type: application/json。改完重启,别只改一处就以为好了。
5.4 登录态失效:token 存了但后端不认
现象:明明登录成功,后续请求却提示未登录。原因通常是前端把 token 放在header里,后端拦截器取的是request.getParameter,两边对不上。解决:统一约定 token 放在请求头token字段,后端拦截器用request.getHeader("token")取。另外注意 token 过期时间,毕业设计可以设长一点,比如 7 天,避免演示到一半掉线。
5.5 数据库时区差 8 小时
现象:作品创建时间比实际时间少 8 小时。原因是 MySQL 的时区是 UTC,Java 取的是东八区。解决:连接 URL 加serverTimezone=Asia/Shanghai,或者 MySQL 里执行SET time_zone = '+8:00';。这个坑不影响功能,但答辩时老师一看时间不对,就会追问,提前改掉省事。
6. 进阶技巧:用这套项目练手,而不是只交差
如果你只把这个项目当成一次性作业,那确实有点浪费。我一般会建议在它基础上做两件事:一是把 SSM 的 XML 配置逐步换成注解或 Java Config,体会一下 SpringBoot 为什么后来会流行;二是把小程序端的请求封装再抽一层,加上 loading 和错误重试,这套逻辑在你以后做任何小程序项目都能直接复用。验证方法很简单:把后端接口用 Postman 跑一遍,再把小程序每个页面点一遍,重点看登录、列表、详情、上传这四个链路。如果时间允许,把数据库脚本里的测试数据换成你自己找的剪纸图片,答辩时演示效果会真实很多。我自己的习惯是,每改一个配置就提交一次 Git,这样翻车了还能回滚,别问我是怎么养成这个习惯的。希望帮到你。
本文还有配套的精品资源,点击获取