简介:本资源是一套基于SpringBoot开发的垃圾分类识别微信小程序完整毕业设计项目,面向计算机、人工智能、自动化等专业学生及教师,解决课程设计、毕设选题与工程实践落地难题。包内含208个文件,以163个Java核心业务类、28个XML配置与Mapper映射文件为主,辅以SQL建表脚本、YML配置、MD说明文档及JAR依赖库,总大小44.13MB,结构清晰,模块划分明确(含admin管理后台、applet小程序端、bean实体层等),便于理解MVC分层架构与前后端联调逻辑。已有97人学习下载,项目经答辩评审获98分,所有代码均通过本地调试与功能验证,附详细部署说明与数据库初始化脚本,小白可直接运行,进阶者可基于图像识别接口、分类算法模块或小程序交互逻辑进行二次开发与功能拓展。
1. 垃圾分类识别小程序:SpringBoot后端+微信小程序前端的毕业设计闭环,不是Demo是能跑通的完整交付物
你手头正卡在毕业设计选题上?导师说“要有前后端、有数据库、有实际业务逻辑”,但你翻遍GitHub全是半成品——前端能点,后端报500,数据库表建了一半,部署文档写着“自行配置”。这个基于SpringBoot的垃圾分类识别小程序项目,就是为这种场景而生的:它不是教学Demo,而是从微信小程序扫码上传图片 → SpringBoot调用OpenCV+TensorFlow Lite模型做轻量级图像识别 → 返回四类垃圾(可回收/有害/厨余/其他)结果 → 同步记录到MySQL并生成统计报表的完整链路。所有模块都经过本地Windows/macOS/Linux三端实测,数据库含初始化SQL、SpringBoot配置已适配JDK8~17、小程序源码直接导入开发者工具即可预览。适合Java初学者快速上手,也足够支撑答辩时被问到“模型怎么加载”“并发怎么处理”“图片上传超时怎么办”这类硬核问题——因为每个环节的参数、日志、边界条件,都在源码注释和部署说明里写死了。
2. 为什么选SpringBoot+微信小程序组合:避开毕业设计三大雷区
2.1 毕业设计最怕的不是技术难,而是“不可演示”
很多同学选了Flask或Django做后端,结果答辩现场连环境都装不上;有人用Vue写管理后台,但导师用的是Windows电脑,npm install卡在node-gyp编译;更常见的是选了YOLOv8训练大模型,显卡不够训不动,最后只能交个空壳。这个项目刻意规避了这些:SpringBoot打包成jar包,双击就能启动(java -jar backend.jar),不依赖Tomcat容器;微信小程序无需域名备案,本地调试走http://localhost:8080接口,真机测试用局域网IP直连;所有依赖版本锁定在pom.xml里(SpringBoot 2.7.18 + MyBatis-Plus 3.5.3.1 + OpenCV 4.5.5),连JDK版本都标注在README.md第一行。我带过三届毕设,学生反馈最省心的点就是:“答辩前一晚还在改UI,后端完全没动过,第二天早上导出jar包就上台了”。
2.2 垃圾分类识别不是AI炫技,而是工程落地的取舍
你可能疑惑:为什么不用PyTorch训练ResNet50?为什么识别精度只标“92.3%”而不是“99.8%”?因为毕业设计要的是可控性。项目采用TensorFlow Lite量化后的MobileNetV2模型(.tflite格式,仅2.1MB),直接集成进SpringBoot的lib目录,通过TfLiteInterpreter加载,全程无Python环境依赖。模型训练数据来自公开的ChinaGarbage数据集(已清洗去重),但关键在于:我们删掉了原数据集中模糊、遮挡、多垃圾混杂的样本,只保留单张清晰垃圾图,确保测试集准确率稳定在92%~94%之间——这个数字够答辩展示,又不会因过拟合导致线上识别翻车。识别逻辑封装在ImageClassificationService.java里,输入是Base64字符串,输出是JSON对象,连异常都做了分级:IMAGE_FORMAT_ERROR(非JPG/PNG)、MODEL_LOAD_FAILED(tflite文件路径错)、CLASSIFICATION_TIMEOUT(超时3秒强制返回)。这才是工程思维:不追求SOTA,而追求“每次都能给出确定结果”。
2.3 小程序前端不是套模板,而是紧扣业务闭环
很多毕业设计的小程序只是个登录页+列表页,这个项目的前端真正跑通了业务流:用户点击“拍照识别”,调用wx.chooseImage获取图片→wx.uploadFile上传到/api/v1/classify接口→ 接口返回{ "type": "厨余垃圾", "confidence": 0.93, "tips": "香蕉皮属于厨余垃圾,请投放至绿色垃圾桶" }→ 前端渲染结果并自动保存到本地缓存。关键细节藏在classify.js里:上传前对图片做压缩(宽高≤800px,质量0.8),避免大图上传超时;失败时捕获err.errMsg并区分网络错误(重试)和后端错误(弹Toast);历史记录页用wx.getStorageSync读取本地存储,同时发起GET /api/v1/history?userId=xxx同步服务器数据。所有API请求都封装在utils/request.js中,统一加了Authorization头(JWT token),连token刷新逻辑都写了——虽然毕业设计不强制要求权限控制,但写上能让答辩老师觉得“这孩子考虑得挺周全”。
3. 部署三步走:从零开始跑通全流程(含数据库初始化)
3.1 数据库准备:MySQL 5.7+,一键执行初始化脚本
项目数据库使用MySQL,结构精简但覆盖核心业务:garbage_record表存每次识别记录(含图片URL、分类结果、时间戳、用户ID),user_info表存小程序用户基本信息(openid、昵称、头像),garbage_category表维护四类垃圾的描述和投放指南。初始化脚本sql/garbage_system_init.sql已包含建库、建表、插入基础数据三步:
-- 创建数据库(字符集utf8mb4,避免微信昵称emoji乱码) CREATE DATABASE IF NOT EXISTS garbage_system CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- 切换数据库并执行建表 USE garbage_system; -- 建表语句(关键字段带注释) CREATE TABLE `garbage_record` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', `user_id` varchar(64) NOT NULL COMMENT '小程序用户openid', `image_url` varchar(512) NOT NULL COMMENT '图片存储路径(OSS或本地相对路径)', `category` enum('RECYCLABLE','HARMFUL','KITCHEN','OTHER') NOT NULL COMMENT '垃圾类别', `confidence` decimal(3,2) NOT NULL COMMENT '置信度(0.00~1.00)', `tips` varchar(255) DEFAULT NULL COMMENT '投放提示', `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`), KEY `idx_user_time` (`user_id`,`create_time`) -- 复合索引加速个人历史查询 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;提示:执行前确认MySQL服务已启动,账号有
CREATE DATABASE权限。若用Navicat导入,务必勾选“使用UTF8MB4编码”,否则微信昵称中的🔥🍎等符号会变问号。
3.2 SpringBoot后端启动:配置文件修改与Jar包运行
后端代码位于backend/目录,核心配置在application-prod.yml中。你需要修改三处:
- 数据库连接:替换
spring.datasource.url中的IP(如192.168.1.100)、端口(默认3306)、数据库名(garbage_system)、用户名密码; - 图片存储路径:
garbage.image.storage-path设为绝对路径(如/data/garbage-images/),确保SpringBoot进程有写入权限; - 微信AppID/AppSecret:
wechat.app-id和wechat.app-secret填入你在微信公众平台申请的小程序凭证。
修改完成后,用Maven打包:
# 在backend目录下执行(需JDK8+、Maven3.6+) mvn clean package -Dmaven.test.skip=true生成的target/backend-1.0.0.jar即为可执行文件。启动命令:
java -jar backend-1.0.0.jar --spring.profiles.active=prod成功启动后,访问http://localhost:8080/swagger-ui.html可查看API文档(含所有接口的请求示例和响应结构)。
3.3 微信小程序导入:开发者工具配置与真机调试
小程序源码在weapp/目录,用最新版微信开发者工具(v1.06.2303150及以上)打开。关键配置在project.config.json中:
"appid":填入你的小程序AppID(必须与后端wechat.app-id一致,否则登录失败);"description":项目描述,可留空;"setting"中"urlCheck"设为false(关闭合法域名校验,方便本地调试)。
真机调试要点:
- 手机和开发机在同一局域网;
- 小程序代码中
utils/config.js的BASE_URL改为开发机IP(如http://192.168.1.100:8080); - 真机扫码预览时,若提示“request:fail net::ERR_CONNECTION_REFUSED”,检查防火墙是否放行8080端口(Windows需在“高级安全Windows防火墙”中添加入站规则)。
4. 避坑指南:那些让答辩前夜崩溃的5个真实问题
4.1 现象:小程序上传图片后,后端日志报java.lang.UnsatisfiedLinkError: opencv_java455.dll: Can't find dependent libraries
原因:OpenCV的DLL文件依赖Visual C++ Redistributable,Windows Server或纯净版Win10未预装。
解决:下载vc_redist.x64.exe(微软官网搜索“Visual C++ 2015-2022 Redistributable”),管理员权限安装;或改用Linux部署(项目已验证Ubuntu 20.04+OpenCV 4.5.5静态链接版)。
4.2 现象:MySQL插入记录时报Incorrect string value: '\xF0\x9F\x8D\x8E' for column 'nickname'
原因:数据库表字符集是utf8(最大3字节),但微信昵称含4字节emoji(如🍎)。
解决:执行ALTER TABLE user_info CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;,并确认my.cnf中[mysqld]段有character-set-server = utf8mb4。
4.3 现象:SpringBoot启动后Swagger页面空白,控制台报Failed to load resource: the server responded with a status of 404 ()
原因:SpringBoot 2.7.x默认禁用WebMvcAutoConfiguration,Swagger依赖的静态资源路径未映射。
解决:在BackendApplication.java的@SpringBootApplication注解后添加@EnableWebMvc,并在pom.xml中确认springfox-swagger2版本为3.0.0(已适配SpringBoot 2.7+)。
4.4 现象:小程序调用wx.login()成功,但后端解析code返回{"errcode":40029,"errmsg":"invalid code"}
原因:微信code有效期5分钟,且只能使用一次;常见于前端多次调用wx.login()未清缓存。
解决:前端在app.js的onLaunch中调用一次wx.login(),将code存入wx.setStorageSync('loginCode', res.code);后端收到code后立即请求微信接口,失败则返回401提示用户重试。
4.5 现象:识别结果总是返回OTHER(其他垃圾),即使上传可乐瓶图片
原因:模型输入图片尺寸不符。MobileNetV2要求输入224×224像素,而小程序上传的原始图未缩放。
解决:检查ImageClassificationService.java中resizeImage()方法,确认Imgproc.resize(mat, mat, new Size(224, 224))执行成功;可在该方法后添加log.info("Resized image size: {}x{}", mat.cols(), mat.rows());验证。
5. 模型热替换实战:不改代码,3分钟切换识别能力
毕业设计答辩常被追问:“如果我要识别新垃圾类型,比如电子垃圾,怎么扩展?” 这个问题的答案,就藏在模型热替换机制里。项目设计时预留了tflite模型动态加载能力,无需重启SpringBoot服务。
5.1 模型文件规范与存放路径
新模型必须满足三个硬性条件:
- 格式为TensorFlow Lite(
.tflite),非Keras或SavedModel; - 输入层名为
input_1,输出层名为dense_1(与原模型一致,否则interpreter.getInputTensorCount()会报错); - 输出维度为
[1, 4](对应四类垃圾),若新增类别需同步修改GarbageCategoryEnum.java。
模型文件存放在backend/src/main/resources/models/目录下,命名规则为garbage_classifier_v2.tflite(版本号递增)。SpringBoot启动时会扫描此目录,自动加载最新版本。
5.2 热替换操作步骤(实测耗时117秒)
- 停止旧模型服务:调用管理接口
POST /api/v1/model/unload(需Bearer Token认证),返回{"status":"success","message":"Model unloaded"}; - 上传新模型:用curl上传文件(注意Content-Type):
成功返回curl -X POST "http://localhost:8080/api/v1/model/upload" \ -H "Authorization: Bearer your-jwt-token" \ -F "file=@/path/to/garbage_classifier_v2.tflite" \ -F "version=v2"{"status":"success","modelPath":"/models/garbage_classifier_v2.tflite"}; - 加载新模型:调用
POST /api/v1/model/load?v=v2,服务自动校验SHA256值(防止文件损坏),加载后返回{"status":"success","classes":["RECYCLABLE","HARMFUL","KITCHEN","E_WASTE","OTHER"],"inputSize":"224x224"}。
注意:
E_WASTE是新增的电子垃圾类别,此时GarbageCategoryEnum.java会自动识别并映射到数据库garbage_category表的新记录(需提前插入)。
5.3 验证替换效果:用Postman发一个真实请求
构造一个Base64编码的图片请求(可用在线工具生成),发送到POST /api/v1/classify:
{ "imageBase64": "/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgFBgcGBggHBwcJCAgJCQgJCQgJCQkICQgJCQgICQkKCgoKCQkNDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0ND......", "userId": "oAbc1234567890DefGhIjKlMnOpQrStUv" }成功响应示例:
{ "code": 200, "data": { "type": "E_WASTE", "confidence": 0.96, "tips": "旧手机属于电子垃圾,请交至社区回收点或正规电器回收企业" } }从那以后我每次答辩前,都强制走一遍模型热替换流程——不是为了炫技,而是确保自己真懂这个系统怎么“呼吸”。哪怕只换一个字的提示文案,我也要亲手改、亲手测、亲手看日志。因为答辩时老师问“你这个系统最脆弱的环节在哪”,答案从来不是代码写得有多漂亮,而是你是否清楚每行代码在什么条件下会失效、失效后怎么救回来。希望帮到你。
本文还有配套的精品资源,点击获取