ARTICLE DETAIL

资讯详情

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

垃圾分类管理系统实战:SpringBoot+Vue3前后端分离开发指南

垃圾分类管理系统实战:SpringBoot+Vue3前后端分离开发指南 1. 项目概述与整体设计1.1 这个系统到底解决什么问题垃圾分类这个话题喊了很多年真正落地到管理层面大家普遍会遇到几个尴尬场景小区里督导员拿着纸质表格登记居民分类情况效率低不说数据后续也没法统计街道办想查某个投放点的满溢状态得靠人工跑现场管理部门想做积分激励却连谁投了什么、投了多少都说不清楚。这套城市垃圾分类管理系统本质上是把前端投放设备、后端管理平台、居民数据档案串起来的一张网。用Java SpringBoot Vue3 MyBatis MySQL这套组合做出来的是一套典型的前后端分离Web应用。后端只负责提供RESTful API前端用Vue3写单页应用通过axios异步请求数据MySQL负责把业务数据落盘。系统涉及的核心业务范围覆盖了垃圾类别管理、投放点管理、居民积分体系、分类投放记录、统计报表等模块。说白了这就是一个带完整业务闭环的管理后台既能让管理员快速上手配置业务也能让前端页面的交互体验足够顺畅。这项目特别适合谁一种是正在做毕设的学生拿这套代码改改业务字段加上自己的创新点答辩足够体面另一种是刚入行想搞懂前后端分离到底怎么协作的开发者通过跑通全流程理解Vue3的响应式机制、SpringBoot的自动配置、MyBatis的Mapper绑定比啃那些零散的知识点快得多。1.2 为什么选择这套技术组合先说后端SpringBoot的江湖地位不需要多解释它最核心的价值在于自动配置。你引入spring-boot-starter-web内嵌Tomcat就给你配好了引入spring-boot-starter-jdbc数据源也自动给你处理了。这套机制省掉的XML配置是一大堆让开发者能从环境搭建的琐碎里解脱出来专注写业务逻辑。MyBatis这层选得也很务实。JPA虽然在国内也有不少拥趸但MyBatis半自动化的特性对复杂SQL更友好。垃圾分类这种业务动辄就是多表关联统计比如查某个街道的参与率、某个投放点的分类正确率写一手可控的SQL比让ORM帮你猜要靠谱得多。再加上它不会给实体类和表字段做隐式映射出了问题能更快定位到是哪句SQL写得不对。前端Vue3则代表了目前国内后台管理系统的主流方向。组合式APIComposition API把同一业务状态的代码聚拢在一起配合reactive和ref这两个响应式基础API写起来比Vue2的Options API清爽不少。跟Element Plus搭在一起表格、表单、弹窗这些后台系统最常见的组件都是现成的开发效率相当高。提示这套组合在Gitee和GitHub上属于最常见的开源项目搭配学习资料多、坑也有人踩过了拿来研究或者二次开发遇到问题不会孤立无援。2. 数据库设计与后端实现2.1 表结构设计先想清楚数据怎么流转后端做得好不好一半看表结构设计得合不合理。垃圾管理系统的核心数据模型我按业务域拆成四个部分用户体系、基础档案、业务流水、统计汇总。下面这几张表是这个系统的骨架我实际开发时也是按这个顺序创建的表名用途关键字段说明sys_user系统用户表id, username, password, role_id, nicknamegarbage_category垃圾类别表id, name, code, description, recycle_flagwaste_drop_point投放点表id, name, address, manager, longitude, latitudewaste_record分类投放记录表id, user_id, category_id, point_id, weight, score, create_timepoints_detail积分明细表id, user_id, change_type, change_value, remark, create_timecleaning_task清运任务表id, point_id, status, assignee, plan_time, finish_time这里重点说下waste_record表它是整个业务的数据核心。每条记录代表一次投放行为关联了投放人、垃圾类别、投放点、重量和积分。设计时我特意把score字段冗余在表里而不是每次查积分记录再去算原因很简单——列表页需要频繁展示单次投放获得的积分如果每次都用关联查询去points_detail表里聚合数据库压力会明显增加尤其数据量上来之后这种冗余能扛住更多并发查询场景。sys_user表这里需要多说一句虽然是管理系统但用户角色要区分开来。系统里至少要有管理员、督导员、居民三种角色。管理员管全局配置督导员负责现场登记投放记录居民在Web端或者后续接入的小程序端查看自己的积分和投放历史。角色字段不建议直接存中文名用role_id关联一张角色表更规范后续加权限控制比如Spring Security或Sa-Token的时候也方便按角色id做鉴权。MySQL的建表语句有几处细节值得留神。所有表主键用BIGINT自增避免分布式环境下UUID主键导致的B树页分裂create_time字段统一用datetime类型并设置DEFAULT CURRENT_TIMESTAMP逻辑删除标记del_flag用tinyint(1)查询时所有Mapper都要带上WHERE del_flag 0的条件。这些习惯早期就养成后面写业务代码会顺畅很多。2.2 SpringBoot后端分层架构后端代码的包结构我建议按照经典的Controller → Service → Mapper三层来组织不要一顿操作把五层六层都堆出来后维护的时候非常痛苦。我用一个简化版目录展示核心结构src/main/java/com/example/garbage/ ├── controller/ # 接口层只做参数接收和结果封装 ├── service/ # 业务层事务边界在这里控制 │ └── impl/ ├── mapper/ # MyBatis Mapper接口 ├── entity/ # 数据库实体类 ├── dto/ # 数据传输对象用于接口入参和出参 ├── common/ # 通用返回结构、异常处理、工具类 └── config/ # 配置类跨域、MyBatis、拦截器等代码规范上有一个很容易被忽略的点接口入参不要直接拿Entity类来接。我见过很多项目图省事前端传什么参数就直接封装成实体类导致后端接口把数据库字段全部暴露了出去。正确做法是定义对应的DTO比如WasteRecordAddDTO只包含需要的字段既安全又解耦。返回给前端的数据也建议统一用一个ResultT结构包装里面放code、message、data三个字段前端拿到的永远是格式统一的响应体处理起来不用写一堆if判断。事务这块也要聊一下。投放记录和积分变动是强关联的投一次垃圾就要加一次积分这两步操作必须要在同一个事务里执行。SpringBoot里直接在Service方法上标注Transactional(rollbackFor Exception.class)就能保证任何一个环节抛异常时数据库自动回滚不会出现加了投放记录但积分没到账这种问题。特别注意这个配置现在很多新手依然认为Transactional默认只会回滚RuntimeException对于受检异常需要显式指定rollbackFor才能触发回滚。2.3 MyBatis Mapper的编写技巧MyBatis的使用核心在Mapper接口和XML文件。这套系统的用户管理模块我会在Mapper接口里定义一个public interface WasteRecordMapper { // 分页查询投放记录支持按用户、按类别、按投放点筛选 ListWasteRecordVO selectRecordPage(Param(query) WasteRecordQueryDTO query); // 统计某投放点近30天的分类数量 ListStatisticVO selectStatisticByPoint(Param(pointId) Long pointId, Param(startTime) LocalDateTime startTime); }对应的XML文件里写SQL时有几个点要特别提醒。第一动态查询条件用where标签包起来它能自动去掉多余的AND或OR第二分页不要自己手写LIMIT做拼接引入PageHelper插件或者用MyBatis-Plus的分页插件都行但要注意插件版本和SpringBoot版本的适配问题第三统计类SQL宁可多写几行把中间结果查出来也别试图在一条SQL里写完所有逻辑可读性差且后续维护成本高。MyBatis的映射关系上也藏着一个坑实体类属性和数据库字段命名不一致时下划线和驼峰转换需要保证开启。在application.yml里配一行map-underscore-to-camel-case: true这样create_time就能自动映射到createTime不然查询出来的对象某些字段就一直是null而且很难排查。另外使用MapperScan注解扫描Mapper接口包时路径千万不要写错。建议在启动类上直接标注MapperScan(com.example.garbage.mapper)这样接口才能被Spring容器扫描并注入到Service里。与此相对的如果漏写这个注解启动时Spring容器里找不到对应的Mapper Bean项目直接启动失败报的错也容易让新手摸不着头脑。3. 前端Vue3工程化实现3.1 Vite创建项目与目录组织现在是2025年Vue3项目的构建工具就别用Vue CLI了Vite是绝对的主流选择。Vite基于原生ESModule开发服务器启动速度快到飞起热更新几乎是秒级的和Webpack那种每次改代码都要等半天的情况完全两个体验。创建命令很简单npm create vitelatest garbage-web -- --template vue cd garbage-web npm install项目创建完以后需要按实际功能补充依赖。Element Plus是UI组件库vue-router负责前端路由pinia管理全局状态axios发送HTTP请求。安装命令我放一起npm install element-plus vue-router4 pinia axios拿到依赖之后的src目录建议这么组织src/ ├── api/ # 接口请求封装按业务模块拆文件 ├── assets/ # 静态资源 ├── components/ # 公共组件例如垃圾分类图标、分页组件 ├── router/ # 路由配置 ├── stores/ # Pinia状态管理 ├── views/ # 页面组件 ├── utils/ # 工具函数request封装、格式化等 └── App.vue这个分层和大多数后台管理系统的惯例一致后续就算多人协作每个人负责自己的模块提交代码时也很少冲突。写的时候我建议优先把utils/request.js写好所有axios请求都走这一个封装统一带上token拦截器统一处理HTTP状态码错误。这一步做好后面写接口只用关注业务数据不用每个请求都写一遍错误处理。3.2 核心页面实现与组件通信这个系统的前端核心页面大概有这几个登录页、首页数据看板、垃圾类别管理页、投放点管理页、投放记录页、积分明细页、系统用户管理页。以垃圾类别管理页为例。页面是一个典型的表格 弹窗表单组合。表格加载数据时调用garbageCategoryApi.getPage(params)接口传入页码、页大小和查询条件。返回的数据用reactive对象接收然后在模板里用el-table渲染。类别是否可回收这个字段在表格里么可以用el-tag来做颜色区分比如可回收用绿色标签其他垃圾用灰色一眼看过去很直观。script setup import { reactive, onMounted } from vue import { getCategoryPage, addCategory, updateCategory } from /api/category const state reactive({ loading: false, list: [], total: 0, query: { pageNum: 1, pageSize: 10, name: } }) const loadData async () { state.loading true const res await getCategoryPage(state.query) state.list res.data.rows state.total res.data.total state.loading false } onMounted(loadData) /script弹窗表单的写法也提一下我用的是Element Plus的el-dialog加el-form组合。表单数据不要直接改state.list里的对象而是单独给一个form对象编辑的时候通过深拷贝把当前行数据复制进去取消弹窗时直接把form置空避免脏数据残留。这个习惯看起来不起眼实际开发能省掉一堆改了数据但界面没刷新的疑难杂症。至于组件间通信列表页和弹窗表单往往是父子组件关系。子组件提交成功之后用defineEmits派发一个refresh事件父组件监听到事件后重新loadData()。如果用Pinia管理全局用户信息和权限也行但要明确使用场景像当前登录用户是谁这种数据放Store合适某个表格当前页码这种局部UI状态放组件内就够了不要什么都丢到全局Store里不然代码反而更乱。3.3 axios封装与路由守卫接口请求这一层属于前端工程质量的关键。我习惯把所有接口请求单独放在src/api目录下而不是直接在页面组件里写全路径。比如用户模块新建一个user.js文件import request from /utils/request export function getUserPage(data) { return request({ url: /api/user/page, method: post, data }) } export function addUser(data) { return request({ url: /api/user/add, method: post, data }) }所有请求都从统一的request实例出去这个实例在utils/request.js里创建。axios拦截器里做两件事请求拦截器读取并携带token响应拦截器统一处理返回码。后端接口约定好登录过期返回401前端拦截器捕获到401就清理本地token并跳转到登录页。这套机制几乎是后台系统的标配写一次后面所有模块都能用。路由守卫是另一个必配项。router.beforeEach里做登录校验如果访问一个需要鉴权的页面但本地拿不到token直接next(/login)重定向到登录页。这个操作虽然逻辑简单但头几次体验时很容易漏掉导致登录后直接刷新页面就白屏了。实际的排查经验是页面白屏优先看路由守卫是否把跳转逻辑拦住了再去看控制台有没有接口报错。注意开发环境下前端通过Vite代理转发请求到后端生产环境则通过Nginx配置/api前缀的反向代理。这两个场景的配置不同但目标一致都是为了解决跨域问题。开发期的跨域Proxy配置在vite.config.js里生产期的跨域则需要配置Nginx的proxy_pass。4. 部署联调与常见问题排查4.1 本地启动完整流程一套系统拿到手第一步是在本地把它跑起来。后端和前端要分开启动但两个都要正确处理。后端启动前要确认三个配置MySQL服务正常运行并创建好对应的数据库application.yml里的数据源配置正确url、username、password确保本地的Redis如果项目用到了也开启服务。数据源配置大概长这样spring: datasource: url: jdbc:mysql://localhost:3306/garbage_db?useSSLfalseserverTimezoneAsia/ShanghaicharacterEncodingutf-8 username: root password: 你的密码 driver-class-name: com.mysql.cj.jdbc.Driver启动SpringBoot后访问Swagger地址如果集成了http://localhost:8080/swagger-ui/index.html可以看到后端接口文档。我强烈建议你在这个阶段把每个接口都先拿来测一遍不要急着写前端因为很多问题的根源在后端接口就埋下了等前端联调的时候才暴露排查链路会拉得很长。前端启动就更简单了npm run dev默认端口5173。如果你遇到Vite启动报错提示ESMODULE相关绝大多数情况是package.json里的依赖没装全先试试删除node_modules目录重新npm install。启动起来后访问http://localhost:5173就能看到登录页了。4.2 跨域问题的两种解法前后端分离项目开发期最常见的报错就是跨域。浏览器会拦截前端发出的跨域请求提示Access-Control-Allow-Origin错误。网上这块的资料汗牛充栋但真正核心的原因就一条浏览器的同源策略限制了你访问不同源的接口。开发期最省事的办法是配置Vite开发服务器代理。在vite.config.js里加入这段配置server: { proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } }这么配的意义在于前端页面里请求/api/user/page开发服务器会把这个请求转发到http://localhost:8080/api/user/page。浏览器认为请求是从5173端口发出的且请求路径同源就不会产生跨域拦截。但要注意这只解决开发环境。生产环境部署时前端打包成静态文件放在Nginx里后端单独跑一个服务这时就要在Nginx配置里做反向代理location /api/ { proxy_pass http://127.0.0.1:8080/; }两种方案都在实操中经常用到我建议读者把两种方式都亲手配置一遍这样遇到问题的时候至少能快速判断该检查哪个配置文件。4.3 MyBatis相关经典报错排查这一节整理了一些我实际踩过的坑。第一个是Invalid bound statement (not found)。这个报错基本可以锁定两处Mapper接口和XML文件的namespace不匹配或者XML文件没有被打包到target目录里检查target目录里是否存在对应的XML文件。治本的办法是在pom.xml里让resource包含mapper/*.xmlbuild resources resource directorysrc/main/java/directory includes include**/*.xml/include /includes /resource /resources /build第二个是Cause: java.sql.SQLException: Access denied for user rootlocalhost这个基本就是MySQL密码错误或数据库没创建。MySQL8默认用caching_sha2_password认证和旧版驱动存在兼容问题建议dataSource url里加上驱动类名配置同时确认MySQL版本和连接驱动版本对应。第三个是关于分页的坑。如果用PageHelper请确保拦截器配置在SpringBoot中生效版本冲突会导致分页不生效或影响全局SQL。如果项目引入的是MyBatis-Plus分页逻辑可以直接用其PaginationInnerInterceptor两者不要混着用。4.4 前端调试的几个小工具经验联调阶段前端调试能力的提升对排错速度影响很大。Chrome的Vue Devtools插件是必装的它可以直观看到组件树的props和state排查界面为什么没有更新这类问题基本打开插件看一眼数据就知道是哪一层出了问题。网络请求排查用Chrome的Network面板。重点看红色或非2xx状态码的请求配合响应体内容判断是后端报错还是前端参数传错。如果后端返回的是500建议在后端控制台看完整异常堆栈如果返回的是400则多半是前端传给接口的参数类型或格式不对。另外提一个很多人忽略的技巧Postman或Apifox这类接口测试工具能在前端真正对接之前先把后端接口验证完。一个接口在前端页面调不通的时候第一步拿同样的参数在Apifox里再调一次。如果Apifox通了问题大概率在前端代码比如参数名对不上、字段大小写问题如果Apifox也不通那就直接去后端排查。Locate问题的层级越靠前调试成本就越低。5. 系统扩展与二次开发建议5.1 从管理后台到移动端联动这套系统如果只是做个Web管理后台能力其实还没有完全释放。垃圾分类的另一个高频使用场景在居民端居民通过小程序查积分、预约上门回收、扫码查看垃圾类别。小程序端和后端对接不需要重新改后端架构只要把现有接口按需暴露给移动端加上对应的鉴权策略即可。如果要用uni-app开发小程序技术栈基本是Vue3的语法如果选Vue3模式和现有的Web端代码有不少可以复用的部分。当然要注意小程序和Web的API差异比如登录用uni.login替代OAuth跳转本地存储用uni.setStorage替代localStorage。这块因为属于业务扩展就不展开细讲了但方向上完全可行。5.2 引入智能硬件与数据上报系统再往前走一步就是对接智能分类回收箱。这类物联网硬件设备通过MQTT协议把设备状态上报到后端包括箱体满溢状态、居民刷卡识别结果、称重数据等。通过这些数据系统能自动生成清运任务、计算参与率管理颗粒度从人记账提升到设备自动化采集。后端接入MQTT可以用Spring Integration MQTT模块订阅相关topic并解析消息把解析结果写入业务表。数据到来后会自动触发一些事件比如某个投放点满溢了自动创建一个清运任务分配给最近的保洁员。这套方案加上去之后整个系统的价值会明显上一个台阶。但和所有对接硬件的项目一样要预留消息重试和异常数据兜底机制不能假设设备每次上报的数据都合法。我在实际开发里遇到过设备重复上报导致积分重复发放的情况最后加了幂等校验按设备ID时间戳去重才解决。这个经验值得所有做类似系统的读者留意。提示二次开发时建议先跑通主链路管理员创建类别 → 督导员登记投放 → 居民查看积分再逐步扩展辅助功能。不要一开始就铺大饼功能面铺太开会分散精力最后可能没有一个模块能稳定运行。6. 打包上线与性能优化实战6.1 前后端打包部署流程后端部署推荐直接用Maven打Jar包。在项目根目录执行mvn clean package -DskipTests打完包后在target目录得到garbage-server.jar。部署到服务器上时用nohup java -jar garbage-server.jar --spring.profiles.activeprod server.log 21 启动即可。日志输出单独重定向到文件方便后续排查问题。如果服务器内存吃紧JVM参数可以加上-Xms256m -Xmx512m限制堆内存避免系统资源被Java进程占满。这是经验之谈部分云服务器默认配置可能只有2G内存如果不做限制运行多个服务容易直接OOM。前端部署用npm run build打包产物在dist目录。把dist目录里的文件上传到服务器的Nginx静态文件目录即可。Nginx里还要配置error_page 404 /index.html这是SPA应用必需的一步。原因很简单前端路由跳转用的是history模式用户如果直接在浏览器地址栏输入一个子路由地址Nginx默认会去查找这个路径对应的文件结果当然是404。配置fallback到index.html之后再由Vue Router自己去匹配路由。6.2 数据库慢查询优化系统运行一段时间后投放记录表的数据量会快速增长这时查询性能就成了第一个瓶颈。垃圾管理系统的列表页最常见的查询是按类型统计数量、按投放点聚合重量。这种SQL在数据量小的时候毫秒级返回数据量过百万以后可能就得花好几秒。第一个手段是给常用查询字段建联合索引。比如waste_record表频繁按user_id create_time来查某个人某段时间的投放记录就建一个联合索引idx_user_time(user_id, create_time)。索引设计的原则是等值查询的字段放前面范围查询的字段放后面。如果反过来索引的利用率就会打折扣。第二个手段是分页查询优化。传统LIMIT 100000, 20这种深分页在数据量大时性能很差因为MySQL会扫描前100000条全部记录后丢弃。改成WHERE id 最大id ORDER BY id LIMIT 20的方式走主键索引就能快速定位。这种游标分页的方案在后台管理系统的数据导出场景特别实用。注意建索引不是越多越好。每次插入、更新操作都需要维护索引索引太多会拖慢写入性能。我的经验是单表索引控制在5个以内只给最核心的查询路径建索引。优化SQL之前先用EXPLAIN看执行计划确认确实是全表扫描了再加索引不要预防性建索引。6.3 热词补充Vue3和MyBatis面试常见追问这套项目如果作为面试展示项目那为什么选Vue3组合式API而不是选项式APIMyBatis一级缓存和二级缓存有什么区别这两个问题几乎必被问到。我提前把答案整理好供读者参考。Vue3的组合式API相比Vue2的选项式API最大的区别在于逻辑关注点可以按功能内聚而不是分散在data、methods、computed各个选项块里。一个列表页的加载状态、查询条件、接口函数在组合式API里可以全部放在同一段逻辑中代码可读性和可维护性都强很多。配合reactive()和ref()两个基础的响应式函数就能把普通JavaScript对象变成响应式的这也是Vue3响应式系统重构后的核心用法。MyBatis的一级缓存是SqlSession级别的默认开启同一个SqlSession内执行相同SQL会走缓存二级缓存是Mapper级别的跨SqlSession共享但因为是本地缓存多实例部署下会有数据一致性问题。实际项目中我对实时性要求高的数据从不让它走二级缓存普通配置数据的缓存也严格控制失效时间。能把这个取舍讲清楚面试官会认为你有真实项目经验而不是背八股文。7. 实操总结与项目经验补充分享7.1 代码之外的那些注意事项写这套系统时我最大的体会是一个项目能跑通不代表完成了真正意义上的完成是它符合业务场景、有清晰的工程结构、后续有人能接着维护。具体到垃圾分类管理系统上有几个点属于代码之外的经验沉淀。权限设计就是一个容易在早期被忽略、后期又很难补的部分。如果管理系统只有一张用户表不区分角色那任何登录用户都能访问所有接口这在真实场景里是不可接受的。建议早期就做两件事后端用拦截器或Spring Security做接口鉴权前端用路由守卫做页面级控制。至少在demo阶段把角色区分好后面换真正的权限框架时表结构不用大改。关于日志这属于那种不做没事、一出事就后悔没做的事。投放记录和积分变动属于核心业务操作每个写操作都要打印业务日志内容包括操作人、操作时间、请求参数、响应结果。排查线上问题时一份好的日志能比Debug快十倍。前端还有一个小习惯值得提接口返回的数据不要直接塞进Pinia的Store里长存只在组件内部使用就放组件自己的state。Store里存的东西越少维护成本越低也越不会出现两个页面状态不同步这种诡异问题。7.2 从源码项目到完整作品如果你是从开源仓库拉的项目建议拿到手以后先不要急着改代码按下面的顺序过一遍第一步把项目在本地完整启动起来把核心页面都点一遍第二步用Navicat把数据库表结构和初始数据看一遍理解字段的业务含义第三步才是改代码从最简单的字段调整开始逐步替换成自己的业务逻辑最后再做页面和权限上的定制。很多读者容易犯的一个毛病是拿到代码就动手大改结果改了几十个文件项目启动不起来了还说不清哪一步改坏了。源码项目学习价值最大的是稳定运行时的结构和有业务含义的数据设计这两样你没看明白就动手等于在没地图的情况下进入一个迷宫。另外项目部署上线之后建议做一次完整的备份。备份内容包括MySQL数据目录的定时转储文件、后端Jar包、前端dist目录。备份策略不用太复杂每天凌晨用crontab执行一次mysqldump就够了。真遇到服务器磁盘损坏或误操作你能在半小时内恢复一套可用环境这种安全感是在项目上踩过坑的人最明白的。7.3 后续功能还能往哪个方向延伸这套系统如果只是做一个展示作品已经合格了。但如果要真正落地有两个方向是大多数城市垃圾分类场景实际需要的。第一个方向是随手拍与整改工单。居民或督导员在投放点发现分类不规范的垃圾堆放拍张照片上传系统自动生成一个整改工单流程流转到对应的物业管理团队账号上整改完成后拍照回传系统自动复核销账。这部分从技术上讲就是多一张工单表和一套状态机流转逻辑借助前端表单上传组件能快速实现。第二个方向是大屏可视化。管理侧最关心的是整座城市或一个城区的参与率、分类正确率、积分发放总量。通过接入ECharts或者DataV这类可视化组件把统计数据变成地图热力图和折线图领导视角的效果会直观很多。后端只需要把统计接口按时间维度聚合好数据前端从Vue组件里把图表渲染出来即可。我自己在把垃圾分类管理系统往这两个方向延伸的过程中踩过的坑主要是两个一个是状态机的流转逻辑没有加超时自动催办导致整改工单躺在一个状态下没人管另一个是大屏数据接口没有做缓存每次刷新页面都实时聚合全量数据数据库负载压力不小。这两个问题都是在实际试运行了一段以后才暴露的。做成开源或者接真实需求耐心把这些边界场景处理干净系统才真的算维得住。
返回列表