
简介面向Java初学者及需要完成毕业设计的学生这份记账系统项目以Java技术栈完整展示了从需求建模、代码编写、数据库设计到服务器部署的全流程。压缩包含280个文件整体约71.94MB其中既有23个Java源码文件也有大量XML配置、SQL数据库脚本、CSS/JS前端样式与交互文件以及docx部署说明、mp4部署演示视频资料粒度覆盖编码、配置、运行与讲解等环节。已有187人学习下载适合直接用于课程设计或项目复现。通过源码可以深入理解MVC分层思想、Spring MVC、MyBatis等框架的整合方式以及用户、账目等数据的增删改查操作部署文档与视频则逐步说明开发环境准备、数据库连接、项目导入和打包发布等关键步骤帮助解决从开发到上线的常见问题。前端结合Layui等组件提供基础界面目录划分清楚按视频、源码、数据库、说明文档归档便于按需查阅。1. 基于 Java 的记账系统毕业设计解压到跑通这份资源里到底有什么很多人拿到这类「毕业设计资源」的第一反应是双击 IDEA 打开源码结果缺数据库、缺依赖、配置对不上半小时过去还卡在导入页面。这份「基于 Java 的记账系统毕业设计」资源我完整过了一遍它不是只有代码的残包而是把「01-视频、02-源码、03-数据库、04-说明文档」四件套配齐了——意味着你按顺序走是能真正跑起来的而不是看一堆无从下手的 Java 文件。适合三类人刚学完 Java 基础、想找一个完整 Web 项目练手复现的初学者正在做课程设计或毕业设计、需要参考 Code 组织方式和业务写法的同学以及想搞明白 Spring Boot MyBatis 从前端页面到数据库落库整条链路怎么串起来的从业者。这篇笔记把资源拆开讲清楚里面是什么、怎么跑、坑在哪、怎么改造成自己的东西。2. 项目结构与技术栈先看清四个文件夹和 Spring Boot MyBatis 的选型逻辑拿到压缩包后第一件事不是运行而是看目录。这套资源的目录组织是非常标准的「交付包」格式四件套各司其职视频是给你照着做的数据库是让你能连上的源码是给你改的说明文档是兜底的。2.1 目录结构与文件地图四个文件夹各承担什么角色我建议按这个顺序去解压和阅读目录内容在项目里的作用01-视频项目演示与部署录屏先看一遍了解系统长什么样、部署步骤大概几步02-源码完整 Java 工程含 Maven 配置与前端资源项目本体所有业务逻辑与页面都在这里03-数据库SQL 脚本或数据库文件建库建表 初始化数据是项目能跑起来的前提04-说明文档部署文档、环境要求、账号说明出问题时的第一排查依据优先级高于视频源码目录里能看到一批很有信息量的文件mvnw.cmd说明这个工程带了 Maven Wrapper即使本机没装全局 Maven也能用项目里锁定的版本来构建layui.css、layer.css、laydate.css表明前端基于 Layui 这套组件库layer是弹层组件laydate是日期选择器——记账流水按日、按月筛选全靠它dtree.css和dtreefont.css对应的是树形组件菜单或分类树会用到index.css是主页样式public.css是全局公共样式。这些文件组合起来说明一个事实这不是前后端分离项目而是后端渲染 前端组件库的经典单体结构对初学者更友好。提示解压后先别急着删任何目录。视频、文档、SQL 脚本在排错阶段都是「后悔药」尤其是 04-说明文档里写的数据库账号密码很可能和源码配置是一致的先通读一遍能省不少时间。2.2 技术栈与选型理由为什么是 Spring Boot MyBatis Layui这套资源覆盖的核心技术栈可以整理成一张对照表层次技术选型在项目里承担的角色后端基础Java SE业务逻辑、实体类、工具类Web 框架Spring Boot Spring MVC接收请求、路由分发、控制反转持久层MyBatis数据库增删改查SQL 写在 XML 里数据库MySQL存储用户、分类、账目流水前端Layui jQuery页面布局、表格渲染、弹窗交互构建Maven依赖管理、打包为什么这套组合是这类毕业设计的主流核心原因是「分工清晰、单人可维护」。Spring Boot 内置 Tomcat把过去配置 web.xml、装配 Spring 容器的繁琐步骤省掉了你在 IDEA 里直接运行 main 方法就能起来一个 Web 服务这对课设和毕设场景非常关键。Spring MVC 的 Controller-Service-Mapper 三层结构把「接收参数、处理业务、操作数据库」在代码层面物理隔离每一层都能单独测试。MyBatis 属于半自动 ORMSQL 由你自己写虽然比 JPA 多几行 XML但对记账系统这种以增删改查和统计报表为主的项目来说SQL 可控性远比自动生成重要——比如月度汇总这种带 CASE WHEN 的统计语句用手写 SQL 反而更直观。前端选 Layui 而不是 Vue/React 也很好理解这是一套「后端开发者友好」的组件库不需要 Node 环境不涉及打包构建引入 CSS 和 JS 就能用正好契合课程设计的工期。这套组合对学习 Java Web 的人还有一个隐性价值它把「请求怎么进来、数据怎么流转、结果怎么回去」这条主线完整串起来了。学完 Servlet 和 JSP 之后很多人最大的困惑是那些零散的知识点在一个真实系统里怎么配合——这个项目就是一份标准答案。2.3 数据库设计记账系统的核心表结构与字段边界记账系统最核心的两张业务表是「分类表」和「流水表」再加一张用户表。分类表负责把收入和支出归类流水表是每一笔账目的明细记录。这里给出流水表的建表 SQL你会发现它的字段设计思路非常有代表性CREATE TABLE biz_record ( id BIGINT NOT NULL AUTO_INCREMENT COMMENT 流水ID, user_id BIGINT NOT NULL COMMENT 所属用户ID, category_id BIGINT NOT NULL COMMENT 分类ID, type TINYINT NOT NULL COMMENT 类型1支出2收入, amount DECIMAL(10,2) NOT NULL COMMENT 金额单位元, record_date DATETIME NOT NULL COMMENT 记账日期, remark VARCHAR(255) DEFAULT NULL COMMENT 备注, create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, PRIMARY KEY (id), KEY idx_user_date (user_id, record_date) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT账目流水表;几个字段设计的细节值得展开。金额用DECIMAL(10,2)而不是FLOAT或DOUBLE是因为浮点类型在 MySQL 里做累加时会丢精度账目系统对精度要求高差一分钱都是问题type用TINYINT而不是字符串是为了节省存储空间也方便在 SQL 里用数字直接过滤record_date放进业务表而不是直接用create_time是因为用户记账时可能补录之前的账业务时间和系统写入时间是两个概念混在一起会导致统计错位。联合索引(user_id, record_date)直接服务于两类高频查询——按用户查全部流水、按时间范围做月度汇总这个索引是这套查询性能的关键支撑。如果你拿到资源后想改造成自己的项目最值得动刀的就是表结构比如在biz_category里加一个parent_id支持二级分类或者在biz_record里加一个book_id把「生活账」和「工作账」分开这些都是典型的「表结构修改」练习能顺手把数据库迁移脚本的写法也学会。3. 快速跑通从 MySQL 导库到 IDEA 启动环境与配置一次到位跑通这个项目不需要太多前置条件但环境版本必须对齐否则你会栽在各种莫名其妙的兼容性错误上。这一章按我自己的复现顺序来先对版本再导库最后启动。3.1 环境版本匹配JDK、Maven、MySQL 分别用什么版本这类毕业设计大概率是按 JDK 8 写的不要一上来就用 JDK 17 或 21。很多老项目用了只在 JDK 8 下正常工作的第三方库或语法特性换了高版本 JDK 之后要么编译失败要么运行时反射报错。Maven 建议 3.6 以上如果你不想单独装 Maven直接利用工程自带的mvnw.cmdWindows或mvnwLinux/macOS就行它会自动下载工程锁定的 Maven 版本。MySQL 用 5.7 或 8.0 都可以但两个版本的连接参数有差异后面会细说。环境项建议版本说明JDK1.8JDK 8与大多数毕业设计源码兼容性最好Maven3.6.x 以上或直接使用项目内 Maven WrapperMySQL5.7 或 8.08.0 需要额外配置时区参数IDEA2020.1 以上对 Maven 工程支持完整提示装好环境后先看一眼 04-说明文档里的「运行环境」一节如果文档写的是 JDK 1.8 MySQL 5.7那你的本地环境尽量对齐别用「最新版」挑战一个课程设计项目的兼容性。3.2 数据库导入先把 03-数据库 里的脚本跑起来数据库是这个项目能不能启动的前提。打开 03-数据库 目录里面通常是一个.sql文件比如bookkeeping.sql。推荐用命令行导入比 Navicat 可视化导入更可控出错了也更容易定位mysql -uroot -p -e CREATE DATABASE IF NOT EXISTS bookkeeping DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; mysql -uroot -p --default-character-setutf8mb4 bookkeeping bookkeeping.sql第一条命令的-e参数表示执行 SQL 后退出这里用于建库并指定 utf8mb4 字符集避免中文备注变成乱码第二条命令的--default-character-setutf8mb4告诉客户端导入的脚本按 utf8mb4 解析很多人在这一步翻车就是因为 SQL 文件里有中文注释而客户端默认用了 latin1。导入完成后用SHOW TABLES;看有没有把用户表、分类表、流水表建出来再用SELECT COUNT(*) FROM biz_record;确认初始化数据是否进去了——一张空表可能说明脚本执行不完整。如果 03-数据库 里给的是.frm或.ibd文件而不是 SQL 脚本那就需要用数据库管理工具整库导入这种情况更少见优先找 SQL 脚本。3.3 IntelliJ IDEA 导入与启动前配置打开 IDEA点击File - Open选中02-源码目录下的pom.xml文件IDEA 会识别为 Maven 工程并开始下载依赖。这一步等多久取决于网络和本地仓库缓存看到右侧 Maven 面板里没有红色报错就说明依赖解析完成。启动前要检查src/main/resources/application.yml或application.properties里的数据库连接server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/bookkeeping?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: 123456连接串里最关键的三个参数是useUnicodetrue、characterEncodingutf8和serverTimezoneAsia/Shanghai。前两个保证中文写入读出不乱码第三个是 MySQL 8.0 的强制要求——8.0 的驱动默认要求指定时区否则启动直接报The server time zone value异常。如果你用的是 MySQL 5.7时区参数可以留但最好也写上统一行为规范。启动方式有两种。第一种是直接在 IDEA 里右键运行主类类名通常是Application或ApplicationMain适合调试。第二种是模拟真实部署在终端执行cd 02-源码 ./mvnw clean package -DskipTests java -jar target/bookkeeping-1.0.0.jar-DskipTests表示跳过单元测试强烈建议加上——很多毕业设计里 JUnit 版本和 JDK 不匹配跑测试会把打包卡住。java -jar启动后看到Tomcat started on port(s): 8080日志就说明成功浏览器打开http://localhost:8080/login.html进入登录页。4. 代码链路实战从页面点「记一笔」到数据库落库看骨架怎么转起来跑通只是第一步真正值钱的是源码。这一章我用「新增一笔支出」这个最核心的操作把从前端按钮到数据库落库的完整调用链拆开讲。4.1 三层调用链Controller / Service / Mapper 各管什么Spring MVC MyBatis 项目的标准调用链是这样的浏览器页面发起 Ajax 请求 → Spring MVC 的DispatcherServlet根据 URL 匹配到Controller方法 → Controller 把请求参数封装成 DTO 对象调用Service接口 → Service 实现类里做业务校验和组装 → 调用Mapper接口 → MyBatis 根据 XML 中定义的 SQL 操作数据库 → 结果逐层返回最后通过ResponseBody以 JSON 格式响应给前端。记住一个判断标准Controller 里不该出现 SQLService 里不该出现HttpServletRequestMapper 里不该出现业务判断。职责越清晰后期改代码越安全。很多 Java 初学者写出来的「大泥球」类就是把请求处理、业务判断、JDBC 代码全堆在同一个方法里这个项目恰好是治这个毛病的参照样本。4.2 「新增一笔支出」的完整代码Controller、Service、Mapper 三件套先看 Controller 层。RestController RequestMapping(/api/record) public class RecordController { Resource private RecordService recordService; PostMapping(/add) public ResultVOString add(RequestBody RecordDTO dto) { if (dto.getAmount() null || dto.getAmount().compareTo(BigDecimal.ZERO) 0) { return ResultVO.fail(金额必须大于0); } recordService.addRecord(dto); return ResultVO.success(记账成功); } }RestController告诉 Spring 这个类里所有方法的返回值都会直接序列化成 JSON 响应不用再写ResponseBody。PostMapping(/add)把 POST 请求的/api/record/add路径映射到这个方法。RequestBody负责把前端传来的 JSON 字符串反序列化成RecordDTO对象。注意这里的金额校验compareTo(BigDecimal.ZERO) 0是对 BigDecimal 做比较的正确姿势千万不要用或直接比较——前者比较的是对象引用后者在部分版本里行为不一致。接下来是 Service 层。Service public class RecordServiceImpl implements RecordService { Resource private RecordMapper recordMapper; Transactional(rollbackFor Exception.class) public void addRecord(RecordDTO dto) { Record record new Record(); BeanUtils.copyProperties(dto, record); record.setUserId(SecurityContextHolder.getUserId()); int rows recordMapper.insert(record); if (rows ! 1) { throw new BizException(数据插入失败请重试); } } }Service把这个类注册为 Spring 容器里的业务 Bean。Transactional(rollbackFor Exception.class)声明事务边界——如果insert之后的代码抛了异常数据库会自动回滚不会出现流水表多了一条半截数据的情况。BeanUtils.copyProperties是 Spring 提供的属性拷贝工具把 DTO 里的同名字段复制到Record实体上。这里补一个细节userId不是从前端传的而是从SecurityContextHolder里拿当前登录用户这样做能防止用户伪造别人的 ID 写数据是记账系统里必须养成的安全意识。最后是 Mapper 接口和对应的 XML。insert idinsert parameterTyperecord useGeneratedKeystrue keyPropertyid INSERT INTO biz_record (user_id, category_id, type, amount, record_date, remark) VALUES (#{userId}, #{categoryId}, #{type}, #{amount}, #{recordDate}, #{remark}) /insertuseGeneratedKeystrue配合keyPropertyid的作用是让 MySQL 自增主键在插入完成后回填到Record.id字段这样后续如果需要拿到新纪录的 ID 做关联操作比如记录完成后继续插入一张附件表不需要再查一次数据库。#{}是 MyBatis 的预编译占位符对应PreparedStatement的?可以防止 SQL 注入如果你看到${}拼接方式除非是动态表名否则都要警惕注入风险。注意type字段传的是数字在Record实体里要么用Integer接收要么用枚举加EnumValue注解处理。4.3 报表统计与时间处理月度收入支出的 SQL 写法记账系统除了记流水另一个核心功能就是统计。月度汇总的 SQL 是这套资源里含金量最高的部分它演示了「按时间分组 条件聚合」两种常用手法的组合SELECT DATE_FORMAT(record_date, %Y-%m) AS month, SUM(CASE WHEN type 1 THEN amount ELSE 0 END) AS total_expense, SUM(CASE WHEN type 2 THEN amount ELSE 0 END) AS total_income FROM biz_record WHERE user_id #{userId} GROUP BY DATE_FORMAT(record_date, %Y-%m) ORDER BY month DESC;DATE_FORMAT(record_date, %Y-%m)把完整的日期时间截断成年月格式这是按月份分组最稳的写法不要用YEAR()和MONTH()拆成两列再分组多一层嵌套不说排序还会乱。SUM(CASE WHEN type 1 THEN amount ELSE 0 END)是典型的行转列写法——把同一行数据里不同type的金额拆到不同的统计列里这样一次查询就能同时拿到支出和收入。ORDER BY month DESC是按月份倒序展示前端用 Layui 表格渲染时可以直接用返回的month字段当排序字段不需要在 JavaScript 里再写一遍排序逻辑。如果遇到需要在内存里按金额排名的场景比如「本月支出最大的一笔」可以查出来之后用 Java 的Stream配合Comparator实现但这类分页数据尽量在 SQL 里解决内存排序只适合小数据量。5. 部署避坑与常见问题从导入数据库到上服务器的五个翻车现场这部分是我自己跑类似项目时的血泪经验。每个问题都按「现象 → 原因 → 解决」的排查思路来写你在复现时遇到同样情况可以少走半小时弯路。5.1 MySQL 8.0 导入 SQL 脚本报 1064 语法错误或中文乱码现象用 Navicat 运行03-数据库里的 SQL 文件执行到一半报You have an error in your SQL syntax或者导入完成后表里中文全部变成???。原因SQL 文件的字符集声明和 MySQL 客户端默认字符集不一致。很多毕设脚本头部写的是SET NAMES utf8但表结构用的是utf8mb4当脚本里存在 emoji 类字符或生僻字时utf8 直接报错。另一个常见原因是 Navicat 以latin1编码读取脚本文件把多字节中文字符截断了。解决改用命令行导入并显式指定字符集mysql -uroot -p --default-character-setutf8mb4 bookkeeping bookkeeping.sql导入完成后用SHOW CREATE TABLE biz_record;确认表的DEFAULT CHARSET是utf8mb4再用SELECT * FROM biz_category LIMIT 5;抽查中文数据是否正常。如果数据还是乱的删库重新导一次导入前先执行SET NAMES utf8mb4;让会话字符集先行对齐。5.2 页面能打开但 CSS/JS 全部 404Layui 样式完全失效现象http://localhost:8080/login.html能正常返回 HTML但页面没有任何样式F12 控制台里全是.css和.js的 404 请求。原因模板页面里引用的 Layui 静态资源路径不对或者 Spring MVC 的静态资源映射把/layui/开头的请求拦截了。常见的错误是页面里写的引用路径是/layui/css/layui.css但实际资源放在/static/layui/css/layui.css而项目没有配置额外的资源映射。解决先打开 IDEA 左侧的src/main/resources目录确认layui文件夹在static还是public下然后对照页面源码里的引用路径如果页面引用写的是layui/css/layui.css相对路径页面在子目录时解析就会错位推荐在application.yml里显式配置静态资源映射spring: mvc: static-path-pattern: /** web: resources: static-locations: classpath:/static/,classpath:/public/,classpath:/resources/static-path-pattern: /**表示所有静态资源请求都交给资源解析器处理static-locations列出资源实际存放的目录。改完配置后重启项目F12 刷新看资源是否加载成功——这一步是排查资源和请求映射冲突的标准动作。5.3 接口报 Table bookkeeping.biz_record doesnt exist现象项目能启动登录页也能打开但输入账号密码点登录后提示Table bookkeeping.biz_record doesnt exist。原因有三种可能。第一种是 SQL 脚本导入到了错误的库比如脚本里没有CREATE DATABASE语句你把表建到了information_schema。第二种是 Linux 服务器上 MySQL 的表名大小写敏感而 Mapper XML 里写的表名大小写和实际建表不一致。第三种是数据库连错实例了本地有多个 MySQL 服务。解决先执行SHOW DATABASES;确认bookkeeping库存在且表在里面。如果表在但接口还是报错多半是大小写问题在my.cnf的[mysqld]段加一行配置后重启lower_case_table_names1这个参数让 MySQL 把所有表名转成小写比较但注意它只对新建的表生效改完配置后需要重新导入一次数据库。如果加了配置还是报错那优先检查application.yml里的url是否带库名拼写错误——这类问题越基础越容易被忽略。5.4 记账日期在前端显示成一串数字或英文格式现象流水列表里recordDate显示为1736020800000这样的一长串数字或者显示成2025-01-05T00:00:00的 ISO 格式和页面其他地方的日期样式不一致。原因数据库DATETIME字段经过 MyBatis 取出后是java.util.DateSpring Boot 默认使用 Jackson 序列化Date 会被转成时间戳毫秒数或被序列化成带T的 ISO 字符串而不是你预期的yyyy-MM-dd HH:mm:ss。解决在日期字段上直接加格式化注解这是最快的方案JsonFormat(pattern yyyy-MM-dd HH:mm:ss, timezone GMT8) private Date recordDate;pattern指定输出的日期格式timezoneGMT8确保东八区时间不被转成 UTC。如果项目里日期字段很多更省事的做法是在application.yml里配置全局日期格式spring: jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT8注意如果实体里已经有JsonFormat注解全局配置会被字段级注解覆盖排查时先看有没有双重标准。5.5 按部署视频操作却连不上数据库现象跟着01-视频里的步骤把工程打包成 war 放进 Tomcat 的webapps启动 Tomcat 后报Cannot create PoolableConnectionFactory或Access denied for user rootlocalhost。原因视频是录制时的环境里边的数据库账号密码、端口号、甚至数据库名可能和当前03-数据库里的脚本不一致。最常见的是视频用的密码是123456但你要么改了本地 MySQL 密码要么application.yml里写的密码是另外一套。解决以04-说明文档为基准把配置逐一核对用一条命令先测连接是否能通mysql -uroot -p -h 127.0.0.1 -P 3306 bookkeeping -e SELECT 1;能执行成功说明账号密码和网络都没问题再回去检查application.yml里的url是否写成了服务器 IP 而不是localhost。这里的原则是文档优先于视频源码优先于记忆。我踩过最狠的一次坑是视频里用的数据库名是bookkeeping但实际源码里的连接串写的是books两边不一致导致我排查了将近一小时。6. 进阶技巧把 IDEA 里跑通的工程打包成可运行 JAR 并快速部署6.1 用 spring-boot-maven-plugin 打一个干净的 JAR要在服务器上运行最省心的方式是打可执行 JAR而不是 war 包。确保02-源码的pom.xml里配置了打包插件build plugins plugin groupIdorg.springframework.boot/groupId artifactIdspring-boot-maven-plugin/artifactId version2.7.18/version /plugin /plugins /build版本选2.7.18是因为它和 JDK 8 完全兼容Spring Boot 3.x 强制要求 JDK 17和这类毕业设计源码大概率不匹配。然后执行一条命令./mvnw clean package -DskipTestsclean清掉上次构建的产物package把当前工程打成 JAR-DskipTests跳过测试。打包完成后在target目录下能看到bookkeeping-1.0.0.jar这个文件就是包含了 Tomcat 运行时、所有依赖和静态资源的完整产物拷到服务器上就能跑。6.2 不改代码覆盖配置用启动参数指定端口和数据库地址在真实环境里服务器 IP、数据库密码往往和本地不一致不用回本地改代码重新打包直接在启动命令里覆盖即可java -jar bookkeeping-1.0.0.jar \ --server.port8082 \ --spring.datasource.urljdbc:mysql://192.168.1.100:3306/bookkeeping?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai \ --spring.datasource.password你的新密码命令行参数的优先级高于application.yml里的配置这是 Spring Boot 配置体系的默认规则。--server.port8082把端口从默认的 8080 挪到 8082避免和其他服务冲突--spring.datasource.url指定远程数据库地址。注意密码如果包含或空格整个值要用双引号包住否则 shell 会截断参数。6.3 部署后的三连验证接口、日志、数据落库我一个项目部署完会强制自己走一遍验证流程不验证不算完成。第一步看接口curl -I http://localhost:8082/login.html返回200说明服务活着第二步看日志启动日志里必须有Tomcat started on port(s): 8082和Started Application in X.XX seconds只看到前一行但没看到后一行说明可能有 Bean 初始化失败被吞了第三步验数据用系统录入一笔测试账目然后登进 MySQL 执行SELECT id, amount, type, record_date, create_time FROM biz_record ORDER BY id DESC LIMIT 5;看到刚录入的那笔记录存在且时间正确才说明数据库连接、字符集、日期时区全部正常。从那以后我每次拿到这类毕业设计资源都会先花十分钟把03-数据库和04-说明文档从头到尾核对一遍再跑代码这个习惯帮我躲过了不少坑。希望这篇笔记能让你少走点弯路把资源里的代码真正变成自己的东西——先去下载页把整套资源拖下来跑通一遍再按你自己的记账需求去改表和接口比从零写一个省力得多。希望帮到你。本文还有配套的精品资源点击获取