基于Spring Boot的汽车4S店管理系统设计与实现
1. 项目概述与整体设计思路1.1 为什么选Spring Boot做汽车4S店管理系统每年毕业设计季总有不少同学来问我选什么题目。汽车服务管理系统、4S店销售管理系统这类题目出现频率一直不低原因很实在业务场景清晰、模块划分自然、前后端交互典型用它能把SpringBoot的核心知识点全部串起来——Spring MVC、MyBatis/JPA、事务管理、权限控制、文件上传、接口设计一样都没落下。比简单的“图书管理系统”更有区分度又不至于像电商系统那样复杂到难以收尾。我常年帮同学们看这类项目一个直观感受是很多同学拿到这类题目第一反应是“功能越多越好”把车队管理、金融贷款、保险理赔全塞进来结果数据库十几张表关联关系绕成迷宫最后答辩的时候自己都讲不清楚。这是选题阶段最容易踩的一个坑。正确的做法是紧扣一个真实4S店的核心业务闭环来做。汽车4S店销售、售后服务、配件供应、信息反馈四位一体最核心的业务流程无非是——车辆入库、客户到店看车、销售订单生成、客户提车、后续进店做维修保养、配件出库。围绕这个链条去设计系统天然就有逻辑答辩的时候讲业务流比背概念强得多。这套系统的定位就是覆盖一个4S店从车辆入库、销售出库到售后维修保养、客户回访的完整闭环。技术栈选SpringBoot 2.x MyBatis Plus MySQL前端用Layui或Vue都可以重点在业务逻辑和数据处理上。1.2 核心业务闭环拆解很多人一上来就写代码我建议先画业务流程图不用画的很高大上一张A4纸能讲清楚就行。4S店的核心角色有四类销售员、售后技师、仓库管理员、店长/经理。四类人对应四类操作诉求销售员要能看车、录订单、做客户登记、车辆分配提车售后技师要能接维修工单、记录维修项、申请配件仓库管理员要管车辆库存和配件库存做入库出库店长要能看到销售报表、维修报表、库存预警。权限划分清楚后系统的骨架就出来了。我见过不少同学的代码Service层写着写着就变成“万能接口”谁都能查所有数据这在毕业设计答辩时是会被评委追问的。哪怕不做SpringSecurity那么复杂的权限框架至少要用拦截器校验登录状态再用角色字段做操作级别的区分。另一个容易出问题的点是“状态流转”。一辆车从“在库”到“已预订”再到“已售出”一个维修工单从“待接单”到“施工中”到“待验收”最后“已结算”这些状态之间必须是有序流转的不能出现“已售出的车还能被修改库存”这种逻辑漏洞。我建议在数据库设计阶段就把状态枚举值和流转规则定清楚写在一块文档里哪怕只是注释都行。1.3 技术选型背后的选型理由SpringBoot到现在已经是Java后端开发的事实标准选它不单纯因为它火而是它确实适合这个场景自动配置省掉了一大批XML配置项目结构清爽适合展示代码层次内置Tomcat打包成Jar就能跑部署文档好写演示环境不容易翻车生态成熟校园网环境下随便搜都是资料报错往上贴就能查到解决方案与Vue/Layui等前端通过Restful接口交互适合体现前后端分离思想。持久层我推荐MyBatis Plus而非原生MyBatis原因是单表CRUD代码量少一半条件构造器写查询非常直观分页插件一条配置就行。有人担心“用MP会不会显得不够懂SQL”答辩的时候主动解释一句“复杂多表查询仍然手写了SQLMP负责单表基操”反而显得你有判断力。数据库用MySQL 8.0字符集utf8mb4这是最稳妥的组合。连接的数据库账号密码我习惯统一写在application.yml里但提交代码的时候把密码改成弱口令并备注说明避免不必要的麻烦。前端方面如果以前端分离为亮点用Vue2 ElementUI接口规范按RESTful风格来。如果不打算费这个劲直接用Thymeleaf模板渲染也行工作量小很多但“前后端分离”在答辩时是一个加分项所以我个人建议有条件的话还是分开写。2. 数据库设计与核心表结构解析2.1 表结构设计的原则和踩坑记录这套系统在我的项目里总共设计了9张核心表。第一版做的时候我脑子一热设计了14张表把活动营销、试乘试驾、意见反馈都拆成了独立表。结果开发到中期发现大量表之间只有外键关系业务代码里根本用不到反而因为关联查询嵌套多、SQL写得痛苦最后砍掉了5张表。所以这里特别想强调毕业设计不是企业级全量系统表数量在合理范围内、能表达完整业务闭环即可。9张表覆盖用户、角色、车辆、客户、销售订单、维修工单、配件库存、配件出入库记录、操作日志——已经足够把业务讲圆了。还有一个常见错误不在建表语句里设置外键约束。很多教程说“逻辑外键更好”但毕业设计场景下数据库里有一两个真正的FOREIGN KEY答辩时聊到“数据一致性”更有底气。我的做法是核心业务表之间加物理外键辅助记录表不加既严谨又高效。2.2 每张表的设计思路说明用户表sys_user主键id、用户名、密码BCrypt加密存储、真实姓名、角色id、手机号、创建时间。用户名加唯一索引这是登录查询的高频字段不加索引会导致连表登录接口响应慢。角色表sys_role主键id、角色名、角色编码。角色就四种ADMIN、SALER、TECHNICIAN、WAR EHOUSE仓库员编码写到代码里作为常量不要用魔法字符串散落各处。车辆信息表car_info车架号VIN唯一、品牌、车型、颜色、排量、厂商指导价、成交价、库存状态在库/已预订/已售出、入库时间、所属仓库。关于VIN码真实业务里它是车辆的身份证17位我在这里设置成唯一索引防止重复录入。这是很多同学会漏掉的细节。客户信息表customer姓名、电话、身份证号脱敏显示、地址、客户等级意向客户/成交客户/流失客户、意向车型、备注。电话必须加唯一约束因为客户可能重复到店没约束的话数据会乱掉。销售订单表sale_order订单号手动生成规则是“SO”yyyyMMdd四位流水、车辆id、客户id、销售员id、成交价、定金、订单状态待付款/已付款/已提车/已取消、创建时间。订单号不用数据库自增id因为它要给人看自增id会暴露销量而且格式不专业。这个细节答辩的时候提出来是很加分的。维修工单表maintain_order工单号MO日期流水、车辆id、客户id、接待技师id、故障描述、维修项说明、配件费用、工时费、总金额、状态待接单/施工中/待验收/已结算、创建时间、完成时间。工时费和配件费分开存为了方便后续算技师提成和配件消耗这个设计很关键。配件库存表parts_inventory配件编码、配件名称、适配车型、库存数量、预警阈值、单价、供应商。预警阈值这个字段是实现“库存不足自动预警”功能的数据基础很多同学不做这个其实就是一个字段的事。配件出入库记录表parts_record配件id、变更类型入库/出库、变更数量、关联单号销售订单号或维修工单号、操作人、操作时间。这张表专门用于追踪配件流向满足答辩时“数据可追溯”这一考核点需要。操作日志表sys_log操作用户id、操作类型、操作描述、操作时间、IP地址。系统里加一个全局AOP切面去记录写操作花不了多少代码量但是“系统安全性”的亮点就有了。建表SQL的细节上有三个地方要特别留意所有金额字段用DECIMAL(10,2)不要用FLOAT/DOUBLE否则会出精度问题时间字段统一用DATETIME不要混用TIMESTAMP和DATE每张表都要有create_timeupdate_time建议也加上排序和排查问题时非常方便。2.3 索引设计里容易被忽略的细节拿销售订单表举例常用的查询条件是“按时间范围查销售记录”“按销售员查业绩”“按状态查订单”。所以至少三个复合索引(create_time)、(saler_id, status)、(car_id)。维修工单表同理(technician_id, status)、(customer_id)、(create_time)。我见过不少同学把索引加到每一个字段上最后查询反而变慢这个点答辩时很容易被问到。其实索引不是越多越好每张表的索引数控制在3到5个是一线开发中比较健康的范围。3. 后端核心功能模块实现详解3.1 登录认证与权限控制的实现方案登录模块我采用的是JWT 拦截器的方案不引入SpringSecurity。原因有两个一是SpringSecurity的配置复杂度对于毕设来说属于“杀鸡用牛刀”很多同学配了半个月还是各种重定向问题二是手写拦截器加JWT中间件只有几十行代码自己写的逻辑自己能讲透答辩的时候不会被问住。流程是用户提交用户名密码后端用BCrypt校验密码校验通过后生成一个JWT里面放userId、用户名、角色编码有效期设为12小时。前端把Token存在本地每次请求在Header里带上Authorization: Bearer xxx。后端写一个AuthInterceptor在preHandle里解析Token放入ThreadLocal里的UserContext后续代码直接用UserContext.getUserId()取当前登录人。这套方案的演示效果很好前端强制刷新页面仍然保持登录态接口鉴权可以随时配置“白名单路径”给评审老师展示完之后还能现场在配置里去掉某一个路径演示拦截器生效。这种“能现场演示”的点比任何口头讲解都加分。除了登录拦截操作权限要做到按钮级。比如销售员订单列表上的“删除”按钮在后端接口上也必须校验角色编码。我是用自定义注解RequireRole(ADMIN)挂在Controller方法上拦截器里读取注解信息判断角色代码看起来简洁也展示了元注解和反射的知识点。3.2 销售订单流程的状态机实现销售订单的状态机是实现里最容易写出bug的部分。我的状态定义如下0待付款下单成功等待客户交定金或全款1已付款款项已到账2已提车车辆已交付给客户3已取消订单取消状态流转规则待付款 → 已付款财务确认待付款 → 已取消销售员或管理员取消已付款 → 已提车车辆出库交付已付款/已提车 → 已取消不允许这四条规则我用一个OrderStatusFlow类来做集中控制提供canTransit(from, to)方法所有接口在变更状态前都调用它校验。这样设计后订单被随意跳状态这个逻辑漏洞就从根上堵死了后续所有业务逻辑都在这个约束下运行。车辆库存的扣减要和订单状态联动。下单时锁车、付款时确认车辆已占用、取消时释放车辆、提车时扣减在库数量。用事务注解Transactional保证“订单状态变更”和“车辆状态变更”同成功同失败这一步千万不能漏漏了就会出现“订单已付款车还在库里”的错乱数据。3.3 维修保养工单与配件库存的联动维修工单的实现我觉得是这套系统里最有业务含金量的部分。场景是这样的客户车辆进店技师创建维修工单填写故障描述和维修项如果某个配件不够系统提醒仓库补货维修完成后技师填写工时费系统自动算出总费用并扣减配件库存。实现上我分了三个核心接口createMaintainOrder创建工单初始状态为待接单startMaintain技师接单状态变为施工中同时根据维修项计算需要的配件调用库存扣减接口预占配件completeMaintain填写工时费计算总价状态变为待验收settleMaintain客户确认付款状态变为已结算。配件扣减这里有一个很关键的细节先检查库存是否充足再扣减并且整个过程要和工单状态变更放在同一个事务里。我第一版的时候就踩过坑检查库存和扣减库存写了两个方法中间隔了几行代码结果演示的时候前台的同事同时点了两次“接单”库存扣成了负数现场就很尴尬。后来改成在Service层加synchronized关键字外加数据库层面的乐观锁版本号字段双保险之后才算彻底稳定。另外每次扣减配件库存都要在parts_record表里插入一条记录字段里写清楚关联的工单号。这个设计在答辩时被老师问“如何验证你系统记录的真实性”时可以直接从数据库里查流水给他看说服力很强。3.4 报表统计销售业绩与库存预警报表功能是4S店管理系统的加分项但要控制好实现复杂度。我的方案是不引入额外的报表引擎也不用第三方图表库的前端复杂集成直接用接口聚合数据返回给前端一个固定格式的对象前端用简单的柱状图/饼图组件展示。三个核心报表接口getSaleReport按月统计销售额、订单数、单车均价。SQL用DATE_FORMAT(create_time, %Y-%m)做分组再用GROUP BY汇总。这里需要注意如果某个月没有订单分组查询不会返回0那行所以接口里要先查一个月份列表再补齐零数据。getStockWarning排查所有库存数量低于预警阈值的配件。一个WHERE stock warning_threshold就搞定但要顺手把维修工单里待接单且需要这个配件的工单数也查出来形成“配件库存预警关联工单提示”的组合信息。getMaintainReport按技师统计月均接单数和工时费收入用于支撑绩效考核场景。这里为什么建议用GROUP BY而不是查全表后在Java里计算因为MySQL 8.0对分组聚合的优化已经很好数据量大的时候接口响应时间差一个数量级。答辩时可以提一句“面向集合的思想”瞬间拉开差距。3.5 大文件上传与图片管理车辆图片、客户证件、维修照片这些在4S店管理中都是高频操作。我用的是SpringBoot自带的上传能力加上一个简单的本地文件存储方案。配置一个目录路径upload.dir上传逻辑用MultipartFile.transferTo()保存文件文件名用UUID重命名防止中文名乱码和重名覆盖。然后把文件的相对路径存进数据库记录前端获取时拼接一个映射路径或通过静态资源映射接口读取。这里要提醒文件存储路径必须是绝对路径不能写相对路径否则打包运行和本地运行会目录不一致。还有一个细节上传文件要限制大小和类型我设置的是图片最大5MB仅允许jpg/png/webp超出则抛业务异常给友好提示。这个“限制大小”的操作在演示时如果有人恶意上传一个超大文件系统能平稳处理不会被“测穿”。4. 前端页面与交互设计要点4.1 页面架构与路由组织方式如果选择前后端分离方案Vue2 ElementUI是当前最稳妥的组合资料多、组件全、踩坑博客满大街都是。页面结构分成四个区域登录页、管理主页带侧边栏和顶部导航、业务页面销售/售后/库存/报表、个人中心。路由用Vue Router配上“前置守卫”——判断本地有没有Token没有就跳登录页有就放行。这个机制和前面后端JWT是配套的算是一条完整的链路。侧边栏菜单从这个系统的角色维度去设计管理员全部菜单销售员我的客户、车辆销售、销售订单、销售报表技师维修工单、配件申请、我的接单仓管员车辆入库、配件库存、出入库记录。注意这里前端菜单和后端权限必须保持一致前端是“显示控制”后端是“真实验证”。前端菜单隐藏了某个按钮不等于接口也不让调所以后端鉴权才是安全的关键。能主动把这个区分讲清楚也说明你理解了权限的本质。4.2 几个交互细节与后端联调的坑日期范围选择器ElementUI的el-date-picker默认返回的是数组对象格式如果不做格式化直接传给后端SpringMVC会直接报类型转换错误。正确做法是前端用value-formatyyyy-MM-dd HH:mm:ss确保提交的是字符串后端接收用RequestParam加字符串拼接成SQL查询区间。这个坑几乎每个项目都会遇到提前处理能省半天调试时间。状态字段回显订单状态、工单状态在数据库里存的是数字0/1/2前端不能直接显示数字要做一个枚举映射工具类把“0”转成“待付款”再用标签组件渲染成不同颜色。我建议在前端定义一个全局filter统一处理状态翻译比每个页面各自写判断强得多。搜索表单的防抖处理客户列表页有一个“按手机号搜索”的输入框如果不做防抖用户每敲一个字就发一次请求数据库压力大接口日志也会刷得很乱。用lodash的debounce300ms防抖即可。这个小优化在技术答辩时提出来评委很认可觉得你基本概念扎实。4.3 打印功能与导出Excel销售订单的打印是刚需。我用的方案是前端把订单详情数据按打印模板渲染然后调window.print()打印。注意要加一个media print的CSS样式把侧边栏、导航栏隐藏掉只保留订单内容区域。否则打印出来的纸张里混着菜单栏观感很差。数据导出功能我采用的方案是后端生成Excel。用Apache POI把某一个报表查询结果写入Workbook设置ContentType为application/vnd.ms-excel前端用window.open直接触发下载。POI的版本选择用4.x兼容性好不会出现3.x和JDK8的冲突问题。这里有个小坑导出时文件名如果是中文浏览器可能乱码所以文件名统一用URL编码URLEncoder.encode前端下载时解码展示。5. 项目部署、演示要点与答辩技巧5.1 本地环境搭建的最小稳定组合我在帮同学们排查这类项目时发现大多数运行不起来的问题都出在“环境不统一”严格来说不是代码问题。推荐一套验证过无数次的稳定组合JDK 8不要装17或21SpringBoot 2.x在老版本JDK上最稳Maven 3.6或3.83.9和更高版本在校园网环境下经常拉不到旧依赖还容易遇到源失效MySQL 8.05.7也可以但8.0对utf8mb4和JSON支持更好Node 14Vue2项目的不二选择Node16以上容易出现node-sass编译报错开发工具用IntelliJ IDEA Community版即可不涉及版权问题整个项目克隆下来后执行顺序是这样的先建库建表执行SQL脚本然后改application.yml里的数据库账号密码启动后端再启动前端npm install然后npm run serve浏览器访问前端地址。提示如果npm install报node-gyp或node-sass的错误先检查Node版本是不是太高切换为14或16再试。这一条能解决我见到过的70%以上前端启动失败案例。5.2 编写README和部署文档的技巧毕业设计通常要求交一份部署文档但很多同学随便网上抄一段跑不通的例子比比皆是。我写这套系统的文档时坚持一个原则照着自己的文档能一步步复现运行。为此我专门用了一台纯净的Windows机器按文档从零跑了一遍踩到的每个细节都补进文档里。部署文档的大纲如下环境要求JDK/MySQL/Node版本标明最低版本数据库初始化建库SQL的位置和执行方式一些界面截图后端启动步骤IDEA导入Maven项目、修改配置、启动类位置前端启动步骤npm install、npm run serve测试账号说明列出管理员/销售员/技师/仓管员的测试账号密码常见问题端口占用、依赖拉取失败、数据库连接失败这是我认为这套系统交付材料中最值得花时间打磨的部分。项目做出来只是第一步能让别人快速跑起来才代表你真的理解了整个环境的运转逻辑也是毕业设计评分里的“工程素养”得分点。5.3 答辩现场演示的台词与节奏答辩演示环节最忌讳“打开系统疯狂点鼠标一句话不说”。好的演示其实是一场有节奏的讲解我通常会这样设计节奏第一步2分钟讲业务背景这家4S店有哪些角色他们日常有什么痛点系统如何覆盖核心业务闭环。投影仪上先展示数据库表关系图让评委对全貌有概念。第二步4分钟演示两三个核心流程登录→创建销售订单→把订单状态推到底→去库存看车辆状态变化再开一个技师账号创建一个维修工单→接单→扣配件→结算→看库存流水。全过程不要频繁切换页面按业务时间线走评委看起来不晕。第三步2分钟展示报表页和库存预警页强调“这些数字不是写死的是实时从业务数据聚合出来的”。第四步1分钟展示部署文档和代码结构说明“拿到代码后怎么把它跑起来”。演示时一定要准备少量“翻车预案”比如数据库没连上怎么快速定位浏览器缓存导致的页面异常怎么清理缓存刷新。我有一次演示就被“前端请求跨域”打了个措手不及后来在项目里封了一个统一的请求工具类把跨域配置也写在文档里才算放心。5.4 这段代码在答辩时如何把技术亮点讲透同样一套系统有人拿70分有人拿90分差距主要体现在能不能把“做了什么”提升为“为什么这么做、凭什么这么设计”。我建议每个人梳理出至少5个“技术叙事点”为什么用JWT而不是Session因为前后端分离架构下Session的会话保持要处理跨域Cookie问题JWT天然适合无状态接口为什么用MyBatis Plus还是保留手写SQL单表操作追求开发效率多表报表查询注重SQL优化空间两种模式分层使用互不冲突为什么状态流转单独抽一层因为状态机的变化规则是业务核心约束集中管理可以防止到处散落if/else造成状态跳跃为什么订单号不直接用ID因为订单号要对外展示、要排序、要防猜测ID自增会把业务量泄露出去为什么库存扣减要加事务和锁因为并发场景下两个技师同时接单可能把最后一个配件重复扣减数据库层面的行锁是保证准确性的底线。这些叙事点不需要在答辩时一口气说完整穿插在流程演示中讲即可。准备这样一个“技术认知清单”远比背那些概念定义有说服力。6. 常见问题与排查技巧实录6.1 启动阶段的高频报错处理现象一后端启动报Failed to configure a DataSource这是没连上数据库但报错信息很长直接搜“Failed to configure”就能定位。排查思路排优先级检查MySQL服务有没有起来Windows服务管理器或net start确认检查application.yml里的url/username/password是否匹配检查jar包是否下载完整Maven仓库里mysql-connector-java对应的版本是否存在。有些同学改配置文件时用到localhost连不上改成127.0.0.1就好了通常是MySQL的host解析问题。现象二前端npm run serve报端口被占用Vue的devServer默认8080如果开着其他项目就会冲突。改vue.config.js的port为8081或别的就行。注意改端口后后端的CORS配置里如果写死了允许的源地址也要同步改。现象三接口请求报401或403401是Token没传或Token过期先在前端请求工具里检查拦截器有没有把Token塞进Header403是权限不足检查该账号角色是否匹配当前接口的RequireRole注解。这里有个我在开发时踩过的小坑JWT的密钥如果太短某些版本会报错建议直接用io.jsonwebtoken的官方示例密钥长度至少256位。6.2 运行阶段的逻辑Bug排查实录问题一库存扣成负数排查思路先在parts_record表查出对应编码的所有流水看是哪次操作扣多了。然后检查Service层是否有并发控制。如果只查不加锁就要在对账时发现负数。我给这个系统加的方案是“乐观锁库存下限检查”在parts_inventory表加一个version字段更新时带上WHERE version ?更新成功后version1。这个做法和秒杀系统的超卖问题是一样的解决思路讲出来评委听得很舒服。问题二销售业绩报表出现重复数据排查思路先检查sale_order表里数据的真实重复情况再用SELECT order_no, count(*) FROM sale_order GROUP BY order_no HAVING count(*) 1查一下。出现重复的常见来源是接口被重复请求比如前端按钮没做loading置灰用户双击提交了两次。后端解决方式很简单在提交订单的接口上做“幂等性处理”——用订单号做唯一约束或前置查询数据库层面再加唯一索引双保险。问题三前端中文内容显示乱码排查思路前端页面乱码查HTMLmeta charsetutf-8接口返回乱码查SpringBoot的server.servlet.encoding.forcetrue数据库表乱码查show variables like character%建表语句里统一DEFAULT CHARSETutf8mb4。绝大多数乱码问题逃不过这三个方向。问题四缓存导致页面状态不刷新排查思路前端改动上传后浏览器缓存旧JS文件页面还是旧样式。解决方式有几种开发场景我习惯在index.html加一个版本号注释或者用Webpack打包时给文件名加hash。后端数据不刷新则要确认是不是接口返回了浏览器缓存的响应给返回头加Cache-Control: no-cache。6.3 数据恢复与备份的常规操作这一部分属于运维意识很多同学完全不考虑但一旦演示前误删了数据就会非常慌。我很推荐在项目里写一个数据库备份脚本利用MySQL的mysqldump每天凌晨自动备份一次核心表保留最近7天。脚本本身十几行就能写清楚把它放在/docs/backup.shWindows下就是backup.bat答辩时展示“备份策略”同样是很超出预期的亮点。6.4 遇到查不到的问题时这招最实用做毕设项目没有人能从零一次跑通别人能帮你排查的也就几个固定的坑真正解决那些奇怪报错还得靠自己。我自己的习惯是把报错信息的关键词英文部分完整复制到浏览器搜索先看5篇左右的高质量中文博客如果没解决再精确增加关键词比如加上SpringBoot 2.6、Vue2、Windows。这比直接问人高效得多因为提问的成本和表达的成本都不低而搜索引擎能帮你看到更多的案例。如果搜索引擎翻了几页还没有头绪还有一个办法用二分定位法。先检查后端有没有启动报错、日志里最后一行是什么、前端控制台有没有红色报错、Network面板里请求是4xx还是5xx、数据库连接有没有成功一个项目就五个环节一个个做排除90%的问题半小时内都能定位。7. 项目扩展方向与个人建议7.1 三个低成本高收益的扩展点如果做完核心功能后还有富余时间我很推荐做三个扩展点它们不会让你新增太多工作量但对系统完整度和答辩观感提升明显。第一个是操作日志的可视化。前面已经建了sys_log表加一个“日志管理”页面即可管理员能按用户、操作类型、时间段筛选查看。这个功能能证明系统有审计能力看上去像企业级实践成本却很低。第二个是一键部署脚本。除了前端后端分开启动还可以提供一个根目录下的start.bat里写命令行启动的脚本或者用Dockerfile把后端和MySQL都容器化。哪怕是提供一份“自动初始化数据库”的脚本也比要手动建库更令人觉得工程化。第三个是消息提醒。当库存预警触发时给仓管员发送一条通知技术上用WebSocket或者后端定时任务都可以不需要做到实时推送那么复杂。但一定要克制不要因为引入新框架而增加运维负担如果工期紧张留到结题时当“future work”提一句其实更见水平。7.2 基于这套系统的真实经验分享做这个项目过程中踩过最大的坑是我在企业里给某公司的4S店门店做过一套内部管理工具的demo里面有一个“客户回访提醒”功能。第一版我用定时任务去扫全表每隔5分钟跑一次SELECT * FROM customer WHERE last_visit_time NOW() - INTERVAL 30 DAY数据量一上来就拖慢主表查询。后来改成只扫“最近24小时新增或更新的客户”再结合索引性能就正常了。后来做毕业设计版时我就把这个经验直接带进来报表接口同样遵循“先缩小范围再聚合”的原则效果一直很稳。但也要提醒毕设项目的复杂度是有限的不要指望一次把所有功能都堆上。我见过一个同学把“预约试驾”“客户画像分析”“消息推送”全做了然后答辩现场系统直接卡在启动界面只能干瞪眼让评委看控制台日志。做精做透三个核心流程比做糙十个半成品在打分上强得多。另外关于代码质量的自我检查有一个我长期坚持的做法写完一个模块后过两天再读一遍自己写的代码用一种“导师审阅”的心态找问题。比如方法命名是否体现业务语义、事务边界是否清晰、异常是否被捕获包裹这些小处打磨并不会多花很多时间但对交付物观感提升非常明显也养成了一个一线程序员该有的好习惯。7.3 给即将做这类题目的朋友最后几条建议第一数据库中所有金额字段必须用DECIMAL这是底线用浮点数做钱的运算早晚会出事第二登录密码的加解密一定要用带盐的加密不要存明文哪怕只是毕设也要有安全意识第三代码里不要出现中文注释里的“TODO”而不落实特别是答辩前要把所有TODO清理干净第四打包成Jar之前的application.yml里数据库账号密码不要写成本机的真实密码改成弱口令并备注说明防止文档外传隐患。我现在回忆起第一次把整套系统跑通时的感觉其实是“原来也不过如此”。框架给你解决了很多基础设施问题你自己要去解决的是真正的业务逻辑和边界情况。汽车服务管理这个领域看起来简单但把每一笔订单、每一项库存、每一个工单都串联成闭环细节到位之后那套系统才真正有了生命力。你对业务的理解会在那些细节里表现出来这也是这类题目值得认真做的原因。