ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

垃圾分类管理系统设计与实现:Spring Boot+Vue全栈开发实战

垃圾分类管理系统设计与实现:Spring Boot+Vue全栈开发实战 1. 这个毕设项目到底在解决什么问题先说说我对这类题目的整体感受。垃圾分类管理系统在毕设题目里出现的频率非常高几乎每个学校的选题库都有它原因很简单业务概念清楚、功能边界明确、前后端都能展开、又有一定的社会应用价值非常适合用来证明你掌握了一整套Web开发技能。但正因为做的人多真正能在答辩时把项目讲清楚、讲出亮点的却不多。大部分同学拿到源码之后只是启动跑通问到为什么这样设计数据怎么流转就卡住了。这个项目本质上做的是一件事把城市里垃圾分类从居民投放—分类收集—运输处理—积分激励这条链路搬到线上管理。传统模式下社区垃圾分类靠的是纸质登记和人工肉眼判断台账混乱、称重数据靠手写、积分奖励算不清楚而且管理人员没法知道哪个小区、哪类垃圾回收得最多。用系统管理之后每一笔投递都有记录每一次积分变动都有流水管理员还能从后台看到各分类垃圾的回收趋势决策就有数据支撑了。另外我想强调一个容易被忽视的点这类管理系统是典型的多角色权限项目。它不像单用户工具而是天然存在管理员、居民用户、收运人员三种身份各自看到不同的界面、操作不同的功能。这是面试官和答辩老师最爱问的地方也是项目含金量的一个重要来源。这篇文章我会把项目的技术选型、数据库设计、核心功能拆解、开发时真正会踩的坑以及源码拿到手之后怎么快速跑起来、怎么在答辩时讲出深度全部过一遍。不管是打算拿这个题目开题还是已经拿到源码准备消化都应该能从中找到对应你阶段的东西。顺带说一句网上这类毕设源码质量参差不齐有的给的是Spring Boot 2.3时代的古董代码有的把前端Vue依赖推得特别高新手一跑就是一堆版本报错。所以源码能不能跑通、代码结构是不是清晰、涉及的版本是不是合理本身就是我写这篇内容时想重点帮你把关的。2. 技术选型的每一步都是权衡之后的决定技术栈直接决定了你后面写代码、查资料、过答辩的顺利程度。我见过太多人一上来就选最新版本结果Spring Boot 3.x加JDK 17跟网上的教程、公司里的老代码全对不上卡在环境问题上好几天。选型这件事稳妥比新颖重要。2.1 Spring Boot版本别盲目追新Spring Boot目前主流是2.7.x和3.x两个大版本线。3.x要求JDK 17起步很多第三方整合组件还在适配期网上的报错解决方案也少。而2.7.x搭配JDK 8是过去几年JavaWeb项目里最成熟的组合教程多、坑基本都被踩平了毕设这个场景完全够用。实际开发里我建议直接锁 Spring Boot 2.7.6 JDK 8 Maven 3.8.x 这套组合。理由很简单你想用的MyBatis-Plus、Shiro、EasyExcel这些库对2.7的兼容性早就稳定了一旦遇到问题搜索引擎随便搜都是现成答案。答辩时如果老师问为什么不用Spring Boot 3你可以理直气壮回答为了保证生态兼容稳定把更多精力留在业务实现上。这本身就是工程上合理的取舍。2.2 持久层框架MyBatis-Plus比JPA更适合毕设持久层框架有这个几个选择原生MyBatis、MyBatis-Plus、Spring Data JPA。这个项目我强烈建议用MyBatis-Plus。原因有三第一代码量小。单表CRUD几乎不用写SQLBaseMapper直接给你提供了insert、selectPage这些现成方法你只需要在Service层写业务逻辑就行。对于毕设这种时间紧、功能多的项目效率差距非常明显。第二分页查询极其方便。管理后台几乎每个列表都要分页MyBatis-Plus的Page对象加上selectPage方法两三行代码就拿下一页数据和总条数。你自己手写MyBatis的分页SQL和PageHelper配置费劲不说还容易出bug。第三代码生成器可以大幅提速。MyBatis-Plus官方提供一个代码生成器工具连上数据库之后能自动生成实体类、Mapper接口、Service以及实现类一分钟就能把一张表的增删改查骨架搭好。我在开发这个项目时6张核心表就是靠它先铺出底子然后专心改业务逻辑。顺带说个很多人忽略的细节MyBatis-Plus的逻辑删除注解TableLogic很实用。比如用户注销或者收运记录作废这种场景你并不想真删数据只想在逻辑上隐藏。加上这个注解删除操作就自动变成update一个deleted字段数据历史全部保留对后续做统计报表非常友好。2.3 前端部分Vue全家桶还是模板引擎这个项目的前端有两条路线。一条是传统的Thymeleaf服务端渲染另一条是前后端分离的Vue。我看到的多数毕设源码都是前后端分离的方式后端负责提供JSON接口前端用Vue 2加Element-UI搭界面通过Axios调接口。我支持前后端分离但也要提醒你这种方式意味着你要同时维护两个项目部署时也要考虑跨域问题。如果你的前端基础偏弱建议直接使用现成的Vue后台管理模板比如vue-element-admin的简化版把精力集中在后端接口逻辑上。毕设答辩主要看的是你能否讲清楚整个系统的数据流前端界面不要求你从零手写每一个组件。2.4 数据库与缓存MySQL加Redis的组合逻辑数据库选MySQL 5.7或8.0都行Windows下装一个就行。缓存这里就有讲究了有人会问毕设这么小规模的项目真的需要Redis吗我的看法是可以不用Redis做高并发缓存但可以用它做两件很有答辩价值的事一是存登录Token让分布式会话看起来更现代二是存垃圾分类标准的字典数据减少数据库频繁查询。这两点在答辩时都很容易展开讲而且代码也不复杂。如果你怕引入Redis增加部署复杂度有个折中方案登录态用JWT自己解决字典数据直接放在系统内存里。但既然选了Spring Boot这个生态整合Redis本身就是一项加分技能我还是建议加上。3. 三种角色、五条业务线功能模块是这样拆开的垃圾分类管理系统最容易被做成一团浆糊就是因为它角色多、功能杂。拿到需求之后第一件事不是写代码而是把用户分出类别把每类用户要做的事情列成清单。3.1 管理员端手机号背后的权限体系管理员是这个系统里权限最大的人所有基础数据和核心业务都要从这里走。我把管理员端的功能拆成这么几块基础数据管理管的是垃圾分类标准。比如可回收物包括哪些、有害垃圾包括哪些这些标准不是固定的不同城市可能略有差异所以必须做成可维护的配置。管理员可以在后台新增、编辑、停用某个分类标准前端用户投递时就可以实时看到这些配置。用户管理和收运人员管理本质上是用户状态管理。管理员可以查看所有注册用户、审核收运人员的入驻申请、重置密码、封禁异常账号。技术上就是用户表和角色表做关联查询配合前面说的逻辑删除让删除操作可追溯。业务审核是管理端最容易忽略但最体现系统严谨性的地方。真实的垃圾收运流程里收运人员上报的称重数据不一定可信比如报了重量但没拍照或者分类纯度不合格。这个项目里可以设计一个收运记录审核功能管理员逐条核验记录审核通过后数据才进入统计报表积分也才会到账。这一步能让整个项目的闭环感一下子强起来。最后是统计分析。管理员要能看到每天的垃圾回收总量、分类占比、热门小区排名。我会用ECharts在管理端画柱状图和饼图后端提供一个聚合查询的接口SQL里用group by加日期函数按天或按月统计。这块做完了项目在信息化管理上的说服力就立住了。3.2 居民用户端预约投放和积分这套闭环用户端是这个系统里交互最多的部分我把它拆成四条线垃圾分类查询是用户打开系统最常用的功能。输入垃圾名称系统返回它属于哪一类以及投放建议。这里有一个很关键的产品细节垃圾名称可能千奇百怪奶茶杯旧电池过期药品词的形态也不一样。我建议在数据库里做一个别名表——分类标准表里存类别别名表里存奶茶杯 - 可回收物这种映射。用户查询时先匹配别名表匹配不到再给一个模糊查询兜底。这样做的好处是答辩时你可以说我考虑了用户输入的表达多样性这是加分项。在线预约是整个项目的核心业务流。用户在系统里选择小区地址预约上门回收时间填写垃圾类别和预估重量。预约提交后状态流转是待接单 - 已接单 - 已完成 - 已取消每一步都有时间记录。后端用一个状态字段表示前端根据状态显示不同的按钮。积分系统是让项目有趣起来的关键。用户每次成功投递都能拿到积分我把积分规则设计成可配置的可回收物每公斤10分有害垃圾每次投放固定20分具体参数由管理员在后台维护。积分到账之后用户可以在积分商城兑换小礼品比如垃圾袋、香皂之类这也是常见的社区激励做法。积分流水表必须单独建每次变动都要记账这既是业务需要也是答辩时可以展示的数据一致性设计。个人中心就是最常规的资料维护、积分余额查看、预约记录列表。这块基本是CRUD但要注意关联查询比如预约记录要连表查出小区的名字而不是直接显示一个小区ID这种细节做好了系统才显得完整。3.3 收运人员端移动场景下的任务闭环收运人员更多是在户外作业界面设计要偏简洁。登录后看到的是一个待预约列表按预约时间排序点击接单就把任务绑定到自己名下。上门完成回收后填写实际重量、拍摄现场照片提交给管理员审核。如果遇到用户爽约或者分类严重不合格还可以上报异常。这里涉及一个上传图片的问题后面第四部分会详细讲。收运人员端的核心是任务状态机要清清楚楚接单了就不能再被别人抢到提交了审核就不能再改审核通过了数据就锁定。状态机用一张表加一个状态字段就能实现但设计时一定要想清楚每一步允许从哪个状态跳到哪个状态否则用户一通乱点数据就全乱了。4. 数据库设计六张核心表是怎么串起来的数据库设计是答辩时老师最喜欢深挖的部分。表设计得好不好直接反映你有没有真正想清楚业务。我见过不少毕设源码表倒是建了一堆但外键关系混乱查询时全靠代码里硬拼SQL。下面我把我认为合理的一套表结构梳理出来你可以对照片思路去读源码。4.1 用户体系一张表还是三张表用户角色涉及普通用户、收运人员、管理员有三种主流设计。第一种是用户角色分离一张user表存公共信息一张role表存角色中间夹一张user_role关联表这是标准RBAC模型的写法也是最推荐的。第二种是一张用户表里加个role字段区分省事但扩展性差。第三种是三种角色各建一张表数据冗余少但登录逻辑要分别查三张表代码写起来很别扭。我在这个项目里用的是第一套user表为主role表预置居民、收运人员、管理员三个角色user_role表做关联。注册时默认是居民角色申请成为收运人员后由管理员审核再变更角色。这样做最大的好处是后面想加一个巡检员角色不用改表结构只需要在role表里加一条数据。这句话在答辩时非常有分量。4.2 垃圾分类字典的设计垃圾分类标准表我建议分成两张category分类主表和category_alias类别别名表。category表很简单就四个字段id、name比如可回收物、description描述、enabled是否启用。category_alias表记录垃圾名称和类别ID的对应关系表结构是id、alias_name比如旧报纸、category_id。这样设计的好处是很实在的居民端查询时走别名表命中率高管理员维护时改了主表名称所有别名自动跟着新分类走不需要逐条改。你在答辩时可以举一个具体例子比如用户搜索可乐瓶系统匹配到别名映射返回可回收物能立刻让老师get到你的设计意图。4.3 预约与收运的主线流程预约主表appointment是整条业务链路的核心。字段大概有这些id、user_id发起预约的用户、address_id预约时选择的地址快照、category_id预约的垃圾类别、estimated_weight预估重量、status待接单、已接单、已完成、已取消、create_time、update_time。这里有个容易忽略的技术点为什么不直接关联用户地址表而要设计成address_id存快照因为如果用户在预约之后修改了地址历史订单里显示的地址不应该跟着变。快照的思维方式在订单类系统里非常重要体现在毕设里就是一个字段的特殊设计但说出来的效果完全不一样。收运记录表collection_record紧跟着预约流程字段包括appointment_id、collector_id收运人员ID、actual_weight实际重量、photo_url现场照片、audit_status待审核、通过、驳回、audit_remark审核备注。它和预约表是一对一关系预约完成后生成一条收运记录进入审核流程审核状态从待审核到通过或驳回。4.4 积分流水数据一致性在这里体现积分系统的核心不只是用户表上那个balance字段而是points_record流水表。每条流水记录包括id、user_id、change_value变动值正数加积分负数扣积分、balance_after变动后的余额、related_type关联业务类型比如投递、兑换、管理员调整、related_id关联业务ID、create_time。为什么要存balance_after因为一旦出现积分对不上账的情况可以直接从流水反推每条记录的余额等于上一条余额加本次变动值。如果计算结果对不上说明系统里有逻辑bug。这种流水余额双写的思路在财务、积分、钱包系统里是基本素养放在毕设里作为亮点讲非常合适。另外注意积分变动时的数据库操作要保证原子性最好用事务包住更新余额插入流水两步避免中间崩溃导致只写了一半。5. 开发过程中真正让人头疼的几个坑源码拿到手跑通只是第一步改起来才是真正的考验。以下这几个问题是我实际开发这类系统时踩过并解决的网上基本不会有现成答案建议你提前避开。5.1 跨域配置与前端Cookie丢失前后端分离项目第一个拦路虎就是跨域。你前端跑在localhost:8080后端跑在localhost:9090前端发起的请求会被浏览器拦截。解决方案是在后端加一个跨域配置类实现WebMvcConfigurer重写addCorsMappings方法允许前端的来源、请求头和方法。这里有一个容易忽略的点如果你用Cookie传递登录态跨域配置里还必须加上allowCredentials(true)并且allowedOrigins不能写成*必须写具体的前端地址。否则前端明明调通了接口但登录状态死活拿不到这种问题排查起来非常隐蔽。5.2 文件上传路径的两类典型错误收运人员上传现场照片用的是MultipartFile上传。这里有两个高频坑。第一个是路径写死。有些源码里会把上传路径写成D:/upload换一台电脑运行就报找不到目录。正确做法是在application.yml里配置一个upload.path变量代码里用Value取出来部署时改配置就行。第二个是文件大小限制。Spring Boot默认单文件上传上限是1MB现场照片一张可能就有2-3MB用户一传就报错。需要在配置里手动调大spring.servlet.multipart.max-file-size: 10MB同时max-request-size也要相应调大。另外文件名要做随机化处理防止用户上传了两个同名文件后互相覆盖我习惯用UUID加原文件扩展名拼接成新文件名。5.3 定时统计报表的时间边界统计报表需要按天汇总数据常见做法是用定时任务每天凌晨跑一次。这里面藏着一个经典bug用LocalDateTime.now()获取时间是带有时分秒的但数据库里的create_time也是精确到秒的直接和当天零点、次日零点做比较边界很容易漏掉或重复计算。我建议统一按今天零点到明天零点这个左闭右开区间来查SQL里的写法是create_time #{start} AND create_time #{end}。写成就可能把第二天零点整的数据多算进去。这个坑在答辩时讲出来也是一个体现经验深度的细节。5.4 积分并发扣减问题如果说普通功能是CRUD积分扣减就是考验并发意识的题目。用户下单兑换商品时如果同一用户快速点了两次而代码是先查余额再更新就可能出现两个请求都读取到相同余额导致超扣。处理方式有两种在毕设里可行的方案。第一种用乐观锁在用户积分表加一个version字段更新时SET balance balance - #{deduct} WHERE version #{oldVersion}更新影响行数为0就提示操作太频繁。第二种用数据库行锁更新时SELECT ... FOR UPDATE把该行锁住但使用时要小心事务范围不要锁太久。我在项目里用的就是乐观锁方案代码量小、解释起来清晰老师一听就懂。5.5 定时任务别忘了处理异常情况定时统计的任务里如果某天系统升级或者数据库暂时不可用凌晨的统计任务可能执行失败。如果没有任何兜底措施那天的数据就永远缺失了。建议在任务方法里捕获异常并记录日志同时在后台提供一个手动触发统计的功能这样即便定时任务挂了管理员也能手动补跑。这个设计在真实业务里非常常见做进毕设里能明显提升系统的完整度。6. 源码拿到手之后目录结构怎么看、答辩怎么讲很多同学拿到毕设源码第一反应是打开IDEA直接运行看到登录页就以为大功告成。但实际上评委老师从头到尾最关心的只有三个问题这个系统是不是你写的、你清不清楚它的逻辑、你做的过程中有没有遇到并解决问题。所以读源码和做答辩准备其实同等重要。6.1 后端代码怎么快速看明白拿到源码后我建议按这个顺序梳理后端结构。第一看application.yml确认数据库连接、端口、文件上传路径配置这是所有功能能跑起来的地基。第二看entity目录也就是实体类对照数据库表结构把每个表对应哪些字段过一遍。第三看controller里的接口列表从接口URL反推出前端每个页面调用了什么。第四看service层实现重点理解几个核心方法比如预约后状态是怎么流转的积分到账是在哪一步触发的。这里面有一个很实用的小技巧如果源码里集成了Swagger或Knife4j启动后端后直接访问接口文档页面能看到所有接口的请求参数和响应结构比逐行读代码快得多。没有的话就用Postman手动调几个接口观察响应JSON的结构。6.2 答辩时值得突出的五个设计点第一个是角色权限。能讲清楚RBAC模型、三种角色的权限控制是怎么落地的就证明你不是只写了登录注册。第二个是积分流水与数据一致性。余额和流水双写的设计配合事务处理体现出你对账目不能丢、不能错的业务敏感度。第三个是状态机设计。预约从待接单到已接单到已完成每一步都有对应的校验不会出现用户跳过中间步骤直接完成的情况。这种边界思考在真实项目中很重要。第四个是分类别名匹配。你能指出用户输入不一定规范所以设计了别名映射表这就是在做产品层面的考虑而不只是写代码。第五个是统计报表设计。按天聚合的SQL、定时任务的边界处理、异常兜底能让老师看到你对系统实际运行有意识。6.3 拿到源码后别急着删改先备份基线版本最后给个非常实际的建议拿到源码第一件事运行起来之后立刻用Git初始化一个仓库提交一次初始版本作为基线。之后无论你怎么修改、删除、重构都能随时退回这个稳定状态。很多同学改完代码回不去了越改越乱最后连原本能跑的功能都废了就是这么来的。提交完初始版本再开始改心态会完全不一样。
返回列表