从毕业设计选题到真正跑起来,Spring Boot个人记账系统一直是经久不衰的稳妥方案,尤其适合想做“轻量化”路线的同学。它功能边界清晰、技术栈通用、演示效果好,而且无论对你答辩还是后续扩展,都有足够的想象空间。这篇就完整拆解一下,面向个人用户或中小微企业的轻量化记账管理平台到底怎么做、为什么这么做、踩过哪些坑。1. 项目定位与整体设计思路1.1 为什么记账系统是毕业设计的“最优解”每年带毕设都会遇到大量同学问同一个问题:做什么题目比较好?我的答案里,记账系统出现频率极高。原因很简单,它天然具备一个合格毕设需要的三要素:业务复杂度适中、技术覆盖全面、演示效果直观。先说业务复杂度。记账这件事,单看很普通,无非是把收支记录下来。但如果你想做得正规一点,它就会自然延伸出用户体系、分类管理、账目流水、预算控制、数据统计这几个模块。每个模块单独拆出来都不难,放在一起却构成了一套完整的业务闭环,这就比单纯做个CRUD增删改查要有说服力得多。再说技术覆盖。Spring Boot后端项目里那些高频知识点,在这个系统里几乎都能用上:拦截器做登录校验、事务处理保证账单数据一致性、参数校验防止非法输入、定时任务做预算提醒、聚合查询做统计报表。这一套下来,面试和答辩时你能聊的东西就非常多了。最后说演示效果。记账系统天然带数据,登录、记一笔、看统计、月报展示,这套流程在答辩现场走一遍非常流畅。你不用费劲造场景,评委自己就会记账,他能很直观地感受到系统是否实用。1.2 轻量化到底轻在哪这个题目的关键词是“轻量化”,很多同学容易理解成“功能少”,这是不对的。轻量化的内核是:以最低的成本实现核心价值的闭环,同时保留可扩展性。放在记账场景里,就是满足个人或小微企业快速记录、直观分析、及时提醒这三件事,而不是一上来就堆全套ERP式功能。既然面向个人用户或中小微企业,那么用户量级就决定了技术方案的风格。不需要微服务、不需要分布式事务、不需要消息队列,一个Spring Boot单体应用加一个MySQL库,完全足够支撑几百上千个用户同时使用,而且部署也简单,随便一台机器就能跑。维护成本低、演示成本低,这才是“轻”。在功能设计上,我也会刻意做减法。比如不做复杂的权限分级,只保留普通用户和管理员两类;不做多账本体系,一个用户一个默认账本,因为核心诉求是“记清楚账”,不是“管好复杂的账”。这样做的结果是:每个功能模块都能讲清楚、做完整,而不是每个功能都浅尝辄止。1.3 技术方案选型的底层逻辑这个项目主流搭配是Spring Boot 2.x + MyBatis-Plus + MySQL 8.0,前端可以选Thymeleaf服务端渲染,也可以选Vue 3 + Element Plus前后端分离。我建议基础一般的同学选择服务端渲染方案,原因是少一层联调成本,路由、数据渲染都交给后端,你要操心的知识点少一个维度。如果学过Vue或者愿意投入时间,前后端分离会更有亮点,因为API接口设计本身也是加分项,但代价是跨域、Token管理、前端构建这些环节都会消耗精力。基础一般的同学,建议优先保“跑通”,再考虑“花哨”。MyBatis-Plus之所以比原生MyBatis更合适,是因为我们大量场景是单表操作。记账流水的增删改查、分类的维护,用MyBatis-Plus自带的方法直接完成,省掉写XML的重复劳动。而统计报表这类复杂查询,再手写SQL也不迟。2. 数据库设计与关键模块拆解2.1 表结构设计:少而精的5张核心表记账系统表不必多,但每张都要经得起追问。我最终保留了5张表:用户表保存账号密码和昵称等基本信息,这是所有业务数据归属的基础。核心思考是合理设置唯一索引和密码加密存储方案。分类表预置“餐饮、交通、购物、工资、奖金”等常用分类,允许用户自定义。账目流水表是系统的核心,字段包含金额、类型(收入/支出)、分类ID、备注、记账时间、用户ID,这类数据会持续增长,所以要建立查询索引。预算表记录每月每类别的预算上限,用于超支提醒。系统日志表可选,但加上它答辩时聊聊操作审计会显得思考更全面。2.2 金额与时间的处理细节金额字段是一个很容易写错的地方。如果用Float或Double来存金额,你会遇到经典的0.1加0.2不等于0.3问题,这在账目计算里是不可接受的。正确做法是使用DECIMAL(10,2),精确到分,Java侧对应BigDecimal,所有涉及金额的运算都用BigDecimal完成,这个原则我会在后续代码中反复强调。时间字段同样有讲究。记账时间由用户自己选择,而不是直接用当前时间戳,因为用户很可能要补录昨天的账单。所以表里专门设计了record_date和record_time两个字段,展示和查询都以业务时间为准。建表时给user_id和record_date加联合索引,可以显著加速按月查询账单的速度。2.3 核心模块划分从代码结构看,系统分成这几个层次:用户模块:注册、登录、个人信息维护账单模块:收入支出流水的新增、编辑、删除、分页查询分类模块:预置分类加自定义分类统计模块:按日/月/年汇总收支、分类占比、趋势图数据预算模块:月度预算设置、超支提醒分层遵循经典的三层架构,Controller层只做参数接收和响应封装,Service层写业务逻辑,Mapper层与数据库交互。这个分层习惯一定要养成,答辩时被问到“为什么这么分”,你就回答“为了降低耦合、方便测试、职责分离”,这本身就是得分点。3. 核心实现细节与实操要点3.1 登录鉴权:拦截器加Token登录模块我推荐用JWT,一是无状态,二是前后端分离友好,三是面试时也算一个亮点。但要注意,JWT的token一旦签发,在有效期内没办法主动失效,所以要么把有效期设短一点,要么配合Redis做黑名单,这就可以作为扩展点去讲。整个鉴权链路是这样的:用户提交账号密码,后端校验成功后生成一个包含用户ID和用户名的JWT,返回给前端。前端每次请求带上Authorization请求头。后端的拦截器拦截除登录、注册外的所有接口,从Header里取token并解析,解析成功就把用户信息放入ThreadLocal,供后续业务使用。实际项目中我推荐用HandlerInterceptor加一个自定义注解来标识哪些接口需要登录,这样白名单配置更灵活。有不少同学喜欢在Controller里逐个判断token是否存在,看起来省事,但代码里到处都是重复逻辑,答辩时被问到“为什么代码高重复”就尴尬了。3.2 记账流水:事务与防重复提交核心业务逻辑里有一个场景特别注意:用户提交记账请求时,同时要更新分类小计。比如你在“餐饮”分类下记了一笔50元支出,系统不仅要插入流水记录,还要把该分类当月的支出金额同步更新,或者更新总资产数字。这里就涉及事务,必须保证“插入流水”和“更新统计”同时成功或同时失败。在Spring Boot里,只需要在Service方法上加@Transactional注解,就交给Spring托管事务了。要注意,只有通过Spring代理调用的方法才会启动事务,同类内部调用会失效,这是一个在答辩时容易被追问的经典问题。防重复提交是另一个容易被忽略的点。用户在网页上连续点“保存”两次,就会产生两条一模一样的账单。项目里我用了一个简单方案:给表加一个biz_id字段,前端提交时生成一个UUID作为业务唯一标识,数据库对这个字段建唯一索引,第二次重复提交直接报错提示,后端代码里捕获唯一键冲突异常即可。3.3 统计查询:一条SQL解决月度汇总统计页面需要的数据有两类:一类是总收入、总支出、结余的汇总数字,另一类是分类占比的饼图数据。这些都可以在一个Service方法里实现。核心SQL是下面这个结构:SELECT DATE_FORMAT(record_date, '%Y-%m') AS month, type, SUM(amount) AS total_amount, COUNT(*) AS bill_count FROM account_record WHERE user_id = #{userId} AND record_date BETWEEN #{startDate} AND #{endDate} GROUP BY DATE_FORMAT(record_date, '%Y-%m'), type ORDER BY month DESC这里为什么要用DATE_FORMAT而不是直接用日期分组?因为用户可能只选了“2024年3月”,需要将日期格式化到月份级别再分组。统计查询是高频操作,务必在user_id和record_date上建联合索引,否则数据量上来之后页面会卡。分类占比则是按分类分组汇总支出金额后,在Java里算百分比。注意BigDecimal除法的精度设置,用divid(..., 2, RoundingMode.HALF_UP)指定保留两位小数,避免出现除不尽报错。3.4 预算提醒:不是定时任务,而是懒加载预算超支提醒如果做成每天定时扫描所有用户,初听合理,其实很浪费资源,因为绝大多数用户没有设置预算。项目里我改成“查询时检查”:用户查询某个分类当月报表时,后端顺带把该分类预算与实际支出对比,超过即返回一个提醒字段,前端展示黄色预警条。这个方案好处很明显,不用引入任务调度框架,触发时机贴合用户使用场景。系统里也有一个每日定时任务,夜里跑一次,给所有“开启了预算提醒”的用户发送站内信或邮件提醒。这里用Spring自带的@Scheduled即可,配合cron表达式就够用,不需要引入Quartz。整体看下来,这套设计逻辑清晰、没有复杂框架。如果你正准备定题或已经定题,可以顺着这个思路往下做。4. 环境搭建与实操落地全流程4.1 项目初始化:从零到能跑起来很多人卡在“代码写好了但起不来”,大都是环境问题。我按自己搭项目的习惯讲一遍。要先准备好JDK 1.8或11、Maven 3.6以上、MySQL 8.0、IDEA。创建项目的时候,用Spring Initializr选上Web、MySQL Driver、MyBatis-Plus、Lombok、Validation这几个依赖。这里有个细节,用Lombok需要检查IDE是否装了插件,否则会报找不到getter和setter方法,这个问题看起来莫名其妙,实际非常常见。数据库连接池我选的是HikariCP,Spring Boot 2.x默认自带,不需要额外引入。配置时注意一个参数:spring: datasource: url: jdbc:mysql://localhost:3306/account_db?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.DriverURL里必须带serverTimezone,否则高版本MySQL连接器会直接报时区错误,这也算经典坑了。4.2 开发环境与生产环境的配置分离生产部署和本地开发需要的数据库配置往往不一样。项目里用Spring Boot的多Profile机制,在application.yml里设置spring.profiles.active为dev,另外维护application-dev.yml和application-prod.yml。本地用dev连本地库,服务器上用prod连云数据库。这样切换环境不需要改动代码,启动时通过JVM参数指定Spring.profiles.active=prod即可。日志配置同样值得花十分钟处理。用Logback将日志文件按天滚动,保留30天,避免服务器磁盘被日志撑爆。这在毕设演示中看不出来,但如果你后续把系统部署到正式环境,这是必踩的坑。我见过一台小服务器跑半年日志直接占用十几个GB,排查问题时才发现日志文件早就该清。4.3 部署上线:JAR包到底怎么传项目打包用Maven的package命令。如果租一台云服务器,最简单的部署流程是:Maven打包出JAR文件,用scp或宝塔面板上传到服务器,然后写一个启动脚本。启动脚本核心就一行命令:nohup java -jar account-system.jar --spring.profiles.active=prod > app.log 2>&1 &这里nohup保证SSH断开后进程不退出,日志重定向到app.log,方便排查问题。首次部署时记得开放对应的安全组端口,并检查防火墙是否放行。很多同学部署完发现网页打不开,查半天发现是安全组没配端口,并不是程序问题。数据库初始化方面,项目里准备了一个schema.sql,里面包含建表语句和预置分类数据。部署时用source schema.sql导入,几秒完成,比手动在Navicat里建表要规范得多。5. 常见问题与答辩避坑指南5.1 高频报错与解决方案,直接抄作业我把开发过程中听到和遇到的典型问题整理成一张速查表,适合对照排查。现象原因解决方案启动报时区错误JDBC连接串缺少serverTimezone连接URL加上Asia/Shanghai金额算出来一堆小数使用了Float/Double改DECIMAL,Java侧用BigDecimalMyBatis-Plus分页没有效果缺少分页插件配置PaginationInnerInterceptor在MyBatisConfig中注入插件前端跨域请求失败前后端分离未配置跨域实现WebMvcConfigurer的addCorsMappings方法打包后配置文件不生效多环境配置未指定profile部署时指定 --spring.profiles.active=prodIDEA中Lombok报错未安装插件或开启注解处理安装Lombok插件并开启Annotation Processing5.2 答辩时容易被追问,但又能轻松回答的问题记账系统看着简单,但评委最喜欢追问一些极具针对性的细节问题。第一个高频问题:密码是如何存储的。如果答“明文存的”,基本凉了一半。正确的做法是用BCryptPasswordEncoder进行哈希加密,加盐存储在数据库里,验证时调用matches方法比对。要注意BCrypt每次加密的密文不同,但matches验证永远能通过,这是它的设计特性。第二个问题:删除账目是物理删除还是逻辑删除。如果答“物理删除”,可以但不够高级。我推荐逻辑删除,表里加一个deleted字段,默认0,删除时改为1,查询时MyBatis-Plus自动过滤。好处是数据不会真正丢失,后续可以做回收站和数据分析。MyBatis-Plus对逻辑删除内置支持,只需配置全局逻辑删除字段,非常方便。第三个问题:如果月数据量超过百万,你怎么优化。这时候你可以说分页优化,用游标分页或WHERE id > lastId LIMIT 20的方案替代传统LIMIT OFFSET,并配合联合索引。即使你的项目根本不会有百万条记录,但表达出这个认知层次,已经足够让评委认为你有思考能力。5.3 从毕设到真实落地,还有哪些扩展空间完成一个能跑的记账系统只是及格线。想做得更出彩,还有几个成本低但收益明显的扩展方向。一个是数据导出,用EasyExcel或POI把月度账单导出成Excel,这实际上是面向中小微企业非常核心的功能,财务人员天然习惯下载报表。一个是语音记账,前端集成语音识别,识别“早餐花了15元”转成结构化数据,这个功能做出来演示效果很强。还有一个方向是多端联动,小程序端做记录入口,Web端做统计分析,用同一个后端API服务两端的架构,谈起来也很有落地价值。我见过有同学用OCR扫描小票,自动识别金额和商家,效果惊艳但工作量也大,如果想挑战自己,可以把它作为加分项,但务必先把基础流程做稳。毕竟,一个所有功能都稳定的系统,永远比一个半成品加一个噱头更打动人。6. 文档编写和讲解演示的一些个人经验最后聊几句关于文档和讲解的东西,因为这其实是毕设中真正拉开差距的地方。很多同学把文档做成“项目说明书”,洋洋洒洒几十页,全是截图和代码粘贴,真正解释“为什么这么设计”的文字几乎没有。一份好的设计文档,应该做到让从没看过你代码的人,按文档描述就能复现这个系统。文档要包括系统需求分析、用例图、E-R图、数据库设计说明、接口列表、核心流程说明和部署文档这七块。讲解演示同样需要注意顺序。不要上来就点开代码,讲类和接口怎么写的,评委看不到。正确流程是先讲项目背景和解决什么问题,花一分钟讲清楚业务价值;再登录系统,走一遍“记一笔-查流水-看统计-设预算”完整操作链路,让评委对你的系统建立整体感知;最后展开技术亮点,例如统计SQL怎么优化、事务怎么处理、鉴权怎么设计的,控制在两分钟内。时间长短不是问题,逻辑顺畅才是关键。定制的意义在真实项目中往往被低估。所谓面向个人或中小微企业的轻量化记账,真正落地时几乎每个使用方都有自己的偏好,例如某个小店主要要记进销存而不是流水,某个自由职业者想按项目维度统计收入。作为一名参与过多个定制项目的开发者,我的经验是,在基础版本之上预留灵活的字段和接口,比一次次改表结构要高效得多。系统设计时如果能把“可定制”放进思考维度,你会发现它的应用范围比自己预想的要宽不少。这也是“轻量化”三字真正的价值所在——基础轻巧,但扩展空间不减。
从毕业设计选题到真正跑起来,Spring Boot个人记账系统一直是经久不衰的稳妥方案,尤其适合想做“轻量化”路线的同学。它功能边界清晰、技术栈通用、演示效果好,而且无论对你答辩还是后续扩展,都有足够的想象空间。这篇就完整拆解一下,面向个人用户或中小微企业的轻量化记账管理平台到底怎么做、为什么这么做、踩过哪些坑。1. 项目定位与整体设计思路1.1 为什么记账系统是毕业设计的“最优解”每年带毕设都会遇到大量同学问同一个问题:做什么题目比较好?我的答案里,记账系统出现频率极高。原因很简单,它天然具备一个合格毕设需要的三要素:业务复杂度适中、技术覆盖全面、演示效果直观。先说业务复杂度。记账这件事,单看很普通,无非是把收支记录下来。但如果你想做得正规一点,它就会自然延伸出用户体系、分类管理、账目流水、预算控制、数据统计这几个模块。每个模块单独拆出来都不难,放在一起却构成了一套完整的业务闭环,这就比单纯做个CRUD增删改查要有说服力得多。再说技术覆盖。Spring Boot后端项目里那些高频知识点,在这个系统里几乎都能用上:拦截器做登录校验、事务处理保证账单数据一致性、参数校验防止非法输入、定时任务做预算提醒、聚合查询做统计报表。这一套下来,面试和答辩时你能聊的东西就非常多了。最后说演示效果。记账系统天然带数据,登录、记一笔、看统计、月报展示,这套流程在答辩现场走一遍非常流畅。你不用费劲造场景,评委自己就会记账,他能很直观地感受到系统是否实用。1.2 轻量化到底轻在哪这个题目的关键词是“轻量化”,很多同学容易理解成“功能少”,这是不对的。轻量化的内核是:以最低的成本实现核心价值的闭环,同时保留可扩展性。放在记账场景里,就是满足个人或小微企业快速记录、直观分析、及时提醒这三件事,而不是一上来就堆全套ERP式功能。既然面向个人用户或中小微企业,那么用户量级就决定了技术方案的风格。不需要微服务、不需要分布式事务、不需要消息队列,一个Spring Boot单体应用加一个MySQL库,完全足够支撑几百上千个用户同时使用,而且部署也简单,随便一台机器就能跑。维护成本低、演示成本低,这才是“轻”。在功能设计上,我也会刻意做减法。比如不做复杂的权限分级,只保留普通用户和管理员两类;不做多账本体系,一个用户一个默认账本,因为核心诉求是“记清楚账”,不是“管好复杂的账”。这样做的结果是:每个功能模块都能讲清楚、做完整,而不是每个功能都浅尝辄止。1.3 技术方案选型的底层逻辑这个项目主流搭配是Spring Boot 2.x + MyBatis-Plus + MySQL 8.0,前端可以选Thymeleaf服务端渲染,也可以选Vue 3 + Element Plus前后端分离。我建议基础一般的同学选择服务端渲染方案,原因是少一层联调成本,路由、数据渲染都交给后端,你要操心的知识点少一个维度。如果学过Vue或者愿意投入时间,前后端分离会更有亮点,因为API接口设计本身也是加分项,但代价是跨域、Token管理、前端构建这些环节都会消耗精力。基础一般的同学,建议优先保“跑通”,再考虑“花哨”。MyBatis-Plus之所以比原生MyBatis更合适,是因为我们大量场景是单表操作。记账流水的增删改查、分类的维护,用MyBatis-Plus自带的方法直接完成,省掉写XML的重复劳动。而统计报表这类复杂查询,再手写SQL也不迟。2. 数据库设计与关键模块拆解2.1 表结构设计:少而精的5张核心表记账系统表不必多,但每张都要经得起追问。我最终保留了5张表:用户表保存账号密码和昵称等基本信息,这是所有业务数据归属的基础。核心思考是合理设置唯一索引和密码加密存储方案。分类表预置“餐饮、交通、购物、工资、奖金”等常用分类,允许用户自定义。账目流水表是系统的核心,字段包含金额、类型(收入/支出)、分类ID、备注、记账时间、用户ID,这类数据会持续增长,所以要建立查询索引。预算表记录每月每类别的预算上限,用于超支提醒。系统日志表可选,但加上它答辩时聊聊操作审计会显得思考更全面。2.2 金额与时间的处理细节金额字段是一个很容易写错的地方。如果用Float或Double来存金额,你会遇到经典的0.1加0.2不等于0.3问题,这在账目计算里是不可接受的。正确做法是使用DECIMAL(10,2),精确到分,Java侧对应BigDecimal,所有涉及金额的运算都用BigDecimal完成,这个原则我会在后续代码中反复强调。时间字段同样有讲究。记账时间由用户自己选择,而不是直接用当前时间戳,因为用户很可能要补录昨天的账单。所以表里专门设计了record_date和record_time两个字段,展示和查询都以业务时间为准。建表时给user_id和record_date加联合索引,可以显著加速按月查询账单的速度。2.3 核心模块划分从代码结构看,系统分成这几个层次:用户模块:注册、登录、个人信息维护账单模块:收入支出流水的新增、编辑、删除、分页查询分类模块:预置分类加自定义分类统计模块:按日/月/年汇总收支、分类占比、趋势图数据预算模块:月度预算设置、超支提醒分层遵循经典的三层架构,Controller层只做参数接收和响应封装,Service层写业务逻辑,Mapper层与数据库交互。这个分层习惯一定要养成,答辩时被问到“为什么这么分”,你就回答“为了降低耦合、方便测试、职责分离”,这本身就是得分点。3. 核心实现细节与实操要点3.1 登录鉴权:拦截器加Token登录模块我推荐用JWT,一是无状态,二是前后端分离友好,三是面试时也算一个亮点。但要注意,JWT的token一旦签发,在有效期内没办法主动失效,所以要么把有效期设短一点,要么配合Redis做黑名单,这就可以作为扩展点去讲。整个鉴权链路是这样的:用户提交账号密码,后端校验成功后生成一个包含用户ID和用户名的JWT,返回给前端。前端每次请求带上Authorization请求头。后端的拦截器拦截除登录、注册外的所有接口,从Header里取token并解析,解析成功就把用户信息放入ThreadLocal,供后续业务使用。实际项目中我推荐用HandlerInterceptor加一个自定义注解来标识哪些接口需要登录,这样白名单配置更灵活。有不少同学喜欢在Controller里逐个判断token是否存在,看起来省事,但代码里到处都是重复逻辑,答辩时被问到“为什么代码高重复”就尴尬了。3.2 记账流水:事务与防重复提交核心业务逻辑里有一个场景特别注意:用户提交记账请求时,同时要更新分类小计。比如你在“餐饮”分类下记了一笔50元支出,系统不仅要插入流水记录,还要把该分类当月的支出金额同步更新,或者更新总资产数字。这里就涉及事务,必须保证“插入流水”和“更新统计”同时成功或同时失败。在Spring Boot里,只需要在Service方法上加@Transactional注解,就交给Spring托管事务了。要注意,只有通过Spring代理调用的方法才会启动事务,同类内部调用会失效,这是一个在答辩时容易被追问的经典问题。防重复提交是另一个容易被忽略的点。用户在网页上连续点“保存”两次,就会产生两条一模一样的账单。项目里我用了一个简单方案:给表加一个biz_id字段,前端提交时生成一个UUID作为业务唯一标识,数据库对这个字段建唯一索引,第二次重复提交直接报错提示,后端代码里捕获唯一键冲突异常即可。3.3 统计查询:一条SQL解决月度汇总统计页面需要的数据有两类:一类是总收入、总支出、结余的汇总数字,另一类是分类占比的饼图数据。这些都可以在一个Service方法里实现。核心SQL是下面这个结构:SELECT DATE_FORMAT(record_date, '%Y-%m') AS month, type, SUM(amount) AS total_amount, COUNT(*) AS bill_count FROM account_record WHERE user_id = #{userId} AND record_date BETWEEN #{startDate} AND #{endDate} GROUP BY DATE_FORMAT(record_date, '%Y-%m'), type ORDER BY month DESC这里为什么要用DATE_FORMAT而不是直接用日期分组?因为用户可能只选了“2024年3月”,需要将日期格式化到月份级别再分组。统计查询是高频操作,务必在user_id和record_date上建联合索引,否则数据量上来之后页面会卡。分类占比则是按分类分组汇总支出金额后,在Java里算百分比。注意BigDecimal除法的精度设置,用divid(..., 2, RoundingMode.HALF_UP)指定保留两位小数,避免出现除不尽报错。3.4 预算提醒:不是定时任务,而是懒加载预算超支提醒如果做成每天定时扫描所有用户,初听合理,其实很浪费资源,因为绝大多数用户没有设置预算。项目里我改成“查询时检查”:用户查询某个分类当月报表时,后端顺带把该分类预算与实际支出对比,超过即返回一个提醒字段,前端展示黄色预警条。这个方案好处很明显,不用引入任务调度框架,触发时机贴合用户使用场景。系统里也有一个每日定时任务,夜里跑一次,给所有“开启了预算提醒”的用户发送站内信或邮件提醒。这里用Spring自带的@Scheduled即可,配合cron表达式就够用,不需要引入Quartz。整体看下来,这套设计逻辑清晰、没有复杂框架。如果你正准备定题或已经定题,可以顺着这个思路往下做。4. 环境搭建与实操落地全流程4.1 项目初始化:从零到能跑起来很多人卡在“代码写好了但起不来”,大都是环境问题。我按自己搭项目的习惯讲一遍。要先准备好JDK 1.8或11、Maven 3.6以上、MySQL 8.0、IDEA。创建项目的时候,用Spring Initializr选上Web、MySQL Driver、MyBatis-Plus、Lombok、Validation这几个依赖。这里有个细节,用Lombok需要检查IDE是否装了插件,否则会报找不到getter和setter方法,这个问题看起来莫名其妙,实际非常常见。数据库连接池我选的是HikariCP,Spring Boot 2.x默认自带,不需要额外引入。配置时注意一个参数:spring: datasource: url: jdbc:mysql://localhost:3306/account_db?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.DriverURL里必须带serverTimezone,否则高版本MySQL连接器会直接报时区错误,这也算经典坑了。4.2 开发环境与生产环境的配置分离生产部署和本地开发需要的数据库配置往往不一样。项目里用Spring Boot的多Profile机制,在application.yml里设置spring.profiles.active为dev,另外维护application-dev.yml和application-prod.yml。本地用dev连本地库,服务器上用prod连云数据库。这样切换环境不需要改动代码,启动时通过JVM参数指定Spring.profiles.active=prod即可。日志配置同样值得花十分钟处理。用Logback将日志文件按天滚动,保留30天,避免服务器磁盘被日志撑爆。这在毕设演示中看不出来,但如果你后续把系统部署到正式环境,这是必踩的坑。我见过一台小服务器跑半年日志直接占用十几个GB,排查问题时才发现日志文件早就该清。4.3 部署上线:JAR包到底怎么传项目打包用Maven的package命令。如果租一台云服务器,最简单的部署流程是:Maven打包出JAR文件,用scp或宝塔面板上传到服务器,然后写一个启动脚本。启动脚本核心就一行命令:nohup java -jar account-system.jar --spring.profiles.active=prod > app.log 2>&1 &这里nohup保证SSH断开后进程不退出,日志重定向到app.log,方便排查问题。首次部署时记得开放对应的安全组端口,并检查防火墙是否放行。很多同学部署完发现网页打不开,查半天发现是安全组没配端口,并不是程序问题。数据库初始化方面,项目里准备了一个schema.sql,里面包含建表语句和预置分类数据。部署时用source schema.sql导入,几秒完成,比手动在Navicat里建表要规范得多。5. 常见问题与答辩避坑指南5.1 高频报错与解决方案,直接抄作业我把开发过程中听到和遇到的典型问题整理成一张速查表,适合对照排查。现象原因解决方案启动报时区错误JDBC连接串缺少serverTimezone连接URL加上Asia/Shanghai金额算出来一堆小数使用了Float/Double改DECIMAL,Java侧用BigDecimalMyBatis-Plus分页没有效果缺少分页插件配置PaginationInnerInterceptor在MyBatisConfig中注入插件前端跨域请求失败前后端分离未配置跨域实现WebMvcConfigurer的addCorsMappings方法打包后配置文件不生效多环境配置未指定profile部署时指定 --spring.profiles.active=prodIDEA中Lombok报错未安装插件或开启注解处理安装Lombok插件并开启Annotation Processing5.2 答辩时容易被追问,但又能轻松回答的问题记账系统看着简单,但评委最喜欢追问一些极具针对性的细节问题。第一个高频问题:密码是如何存储的。如果答“明文存的”,基本凉了一半。正确的做法是用BCryptPasswordEncoder进行哈希加密,加盐存储在数据库里,验证时调用matches方法比对。要注意BCrypt每次加密的密文不同,但matches验证永远能通过,这是它的设计特性。第二个问题:删除账目是物理删除还是逻辑删除。如果答“物理删除”,可以但不够高级。我推荐逻辑删除,表里加一个deleted字段,默认0,删除时改为1,查询时MyBatis-Plus自动过滤。好处是数据不会真正丢失,后续可以做回收站和数据分析。MyBatis-Plus对逻辑删除内置支持,只需配置全局逻辑删除字段,非常方便。第三个问题:如果月数据量超过百万,你怎么优化。这时候你可以说分页优化,用游标分页或WHERE id > lastId LIMIT 20的方案替代传统LIMIT OFFSET,并配合联合索引。即使你的项目根本不会有百万条记录,但表达出这个认知层次,已经足够让评委认为你有思考能力。5.3 从毕设到真实落地,还有哪些扩展空间完成一个能跑的记账系统只是及格线。想做得更出彩,还有几个成本低但收益明显的扩展方向。一个是数据导出,用EasyExcel或POI把月度账单导出成Excel,这实际上是面向中小微企业非常核心的功能,财务人员天然习惯下载报表。一个是语音记账,前端集成语音识别,识别“早餐花了15元”转成结构化数据,这个功能做出来演示效果很强。还有一个方向是多端联动,小程序端做记录入口,Web端做统计分析,用同一个后端API服务两端的架构,谈起来也很有落地价值。我见过有同学用OCR扫描小票,自动识别金额和商家,效果惊艳但工作量也大,如果想挑战自己,可以把它作为加分项,但务必先把基础流程做稳。毕竟,一个所有功能都稳定的系统,永远比一个半成品加一个噱头更打动人。6. 文档编写和讲解演示的一些个人经验最后聊几句关于文档和讲解的东西,因为这其实是毕设中真正拉开差距的地方。很多同学把文档做成“项目说明书”,洋洋洒洒几十页,全是截图和代码粘贴,真正解释“为什么这么设计”的文字几乎没有。一份好的设计文档,应该做到让从没看过你代码的人,按文档描述就能复现这个系统。文档要包括系统需求分析、用例图、E-R图、数据库设计说明、接口列表、核心流程说明和部署文档这七块。讲解演示同样需要注意顺序。不要上来就点开代码,讲类和接口怎么写的,评委看不到。正确流程是先讲项目背景和解决什么问题,花一分钟讲清楚业务价值;再登录系统,走一遍“记一笔-查流水-看统计-设预算”完整操作链路,让评委对你的系统建立整体感知;最后展开技术亮点,例如统计SQL怎么优化、事务怎么处理、鉴权怎么设计的,控制在两分钟内。时间长短不是问题,逻辑顺畅才是关键。定制的意义在真实项目中往往被低估。所谓面向个人或中小微企业的轻量化记账,真正落地时几乎每个使用方都有自己的偏好,例如某个小店主要要记进销存而不是流水,某个自由职业者想按项目维度统计收入。作为一名参与过多个定制项目的开发者,我的经验是,在基础版本之上预留灵活的字段和接口,比一次次改表结构要高效得多。系统设计时如果能把“可定制”放进思考维度,你会发现它的应用范围比自己预想的要宽不少。这也是“轻量化”三字真正的价值所在——基础轻巧,但扩展空间不减。