ARTICLE DETAIL

资讯详情

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

SpringBoot财务管理系统毕业设计:从建表到凭证复式记账的完整实现

SpringBoot财务管理系统毕业设计:从建表到凭证复式记账的完整实现 简介面向计算机相关专业毕业设计场景的Java财务管理系统完整项目基于Spring Boot框架开发包含前后端源码、毕业论文与答辩PPT适合需要快速搭建财务系统课题或学习企业级分层开发的毕业生与开发者。资源包共452个文件93.17MB核心文件涵盖Java后端逻辑、Vue前端页面、SQL初始化脚本、XML配置及Maven工程文件同时附带演示视频可清晰了解功能运行效果。系统支持管理员与员工双端功能模块涵盖系统管理、账务处理等常见业务并附有数据库设计、系统测试等论文章节内容环境要求明确JDK1.8、MySQL5.7、Tomcat7等便于本地部署和二次开发。已有179人学习下载适合用于课题参考、代码复用与设计文档撰写。1. 一个 springboot 财务管理系统为什么值得你动手做先看清这份毕业设计的真实分量又到毕业设计季每年这时候总有人拿着“Java毕业设计-基于springboot开发的财务管理系统-毕业论文PPT附源代码演示视频”这类标题来找我。说实话财务管理系统是 springboot 毕业设计里最适合复现也最容易翻车的题目——说适合是因为账务流程天然结构化需求明确教材和开源参考一大堆照着做能出完整效果说容易翻车是因为很多人把数据库设计做成了“流水账”复式记账、科目体系、试算平衡一个都没踩准演示视频里一录凭证录入就露馅。这篇笔记不假装有源码包只把这个方向从选型、建表、编码、排错到答辩准备完整捋一遍。你照着走完能跑通、能演示、敢讲原理也就知道这份源代码该往哪个方向做、自己怎么组织它。适合正在选题或已经开做的 Java 学生也适合想快速上手 springboot 管理类项目的新手。2. 搭建 springboot 项目骨架依赖、配置与目录结构一次跑通2.1 为什么是 springboot mybatis-plus mysql毕业设计的选型逻辑做财务管理系统技术栈不用花哨。springboot 负责把 SSH 时代那一堆 XML 配置收掉内置 Tomcat一个 jar 包能跑MyBatis-Plus 在 MyBatis 基础上把单表 CRUD 和分页封装好写财务模块时能省下大量样板代码MySQL 存数据InnoDB 引擎支持事务恰好满足凭证录入这类写操作的原子性要求。前端怎么选标题里没限定但日常见到的毕业设计有两种主流做法一种是 springboot 直接套 Thymeleaf 模板 Bootstrap jQuery适合一个人开发后端渲染页面调试简单另一种是前后端分离Vue 打包后放进 springboot 的 static 目录用 Nginx 都不用装直接打成 jar 跑。如果你的任务是“应付答辩 演示流畅”我建议选前者省掉跨域和接口联调的环节如果你论文里想写“前后端分离架构”增加篇幅再走 Vue 打包路线注意把前端 build 产物统一丢到 src/main/resources/static 下springboot 会把它当静态资源自动映射这就是热词里“vue打包放进springboot中”的实际含义。2.2 pom.xml 与 application.yml先让项目跑起来新建一个 springboot 项目时我一般从 Spring Initializr 生成基础骨架然后手动调整 pom.xml。财务管理系统所需的依赖不长核心是 web、mybatis-plus、mysql 驱动、lombok再加一个 validation 用于参数校验。下面是一个能直接跑的最小 pom 关键片段parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version2.7.18/version relativePath/ /parent dependencies !-- Web 启动器内嵌 Tomcat提供 MVC 能力 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- MyBatis-Plus 的 springboot 适配 -- dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.3/version /dependency dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId scoperuntime/scope /dependency dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency /dependencies这段配置里最容易出问题的是版本组合springboot 2.7.18 配 mybatis-plus 3.5.3 是稳定搭配如果换成 springboot 3.x就必须配套 mybatis-plus 3.5.5 以上版本并使用 jakarta 命名空间否则启动时直接报 ClassNotFoundError。这是很多人一上来就“翻车”的地方后面第 5 章会单列一条排查。MySQL 驱动版本跟着 springboot parent 走就行不用显式写版本号。接着是 application.yml。财务管理系统里必须配好数据源、MyBatis-Plus 的日志与驼峰映射以及时区参数server: port: 8080 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/finance_db?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: 123456 jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: Asia/Shanghai mybatis-plus: configuration: map-underscore-to-camel-case: true log-impl: org.apache.ibatis.logging.stdout.StdOutImpl global-config: db-config: id-type: auto logic-delete-field: deleted logic-delete-value: 1 logic-not-delete-value: 0url 里的 serverTimezoneAsia/Shanghai 和 jackson 的 time-zone 是配套的少了任何一个日期字段都会出现“8 小时错觉”。map-underscore-to-camel-case 负责把数据库的 create_time 自动映射成 Java 实体的 createTime这能省掉一大半 XML 手写映射。logic-delete 配置是给财务数据留后悔药——凭证录错了做逻辑删除而不是物理删除这在财务系统里是刚需后面建表时你会看到 deleted 字段。2.3 目录结构怎么摆controller/service/mapper 分层与包命名springboot 项目结构没有强制标准但财务管理系统建议按“按角色分包 按技术分层”结合的方式组织方便论文里画架构图。我常用的目录如下src/main/java/com/example/finance/ ├── FinanceApplication.java ├── common/ │ ├── Result.java // 统一返回体 │ ├── PageResult.java // 分页返回体 │ └── BizException.java // 自定义异常 ├── config/ │ ├── MybatisPlusConfig.java // 分页插件 │ └── WebConfig.java // 拦截器注册 ├── controller/ │ ├── AuthController.java │ ├── SubjectController.java │ ├── VoucherController.java │ └── ReportController.java ├── service/ │ ├── SubjectService.java │ ├── VoucherService.java │ └── impl/ │ ├── SubjectServiceImpl.java │ └── VoucherServiceImpl.java ├── mapper/ │ ├── SubjectMapper.java │ └── VoucherMapper.java ├── entity/ │ ├── Subject.java │ ├── Voucher.java │ └── VoucherEntry.java └── dto/ ├── VoucherAddDTO.java └── LoginDTO.java这个结构好在哪里controller 只做参数接收和结果封装service 写业务规则mapper 只碰数据库。财务系统里业务规则密——借贷必须平衡、科目不能删下级、凭证号不能断号这些全部收敛在 service 层答辩时讲“我把业务规则放在 service 层而不是 controller”本身就是个得分点。如果论文里想写“项目结构清晰、职责单一”这个分包能直接截图标出来讲。还要注意一点如果项目里有登录功能建议用拦截器统一校验 session而不是在每个 controller 里重复写判断。WebConfig 里注册一个 HandlerInterceptor 实现类放行登录接口和静态资源其他接口全部校验。这套逻辑第 4 章给完整代码。3. 核心账务流程落地科目、凭证与复式记账的实现要点3.1 财务系统的数据基座科目表与凭证表如何设计财务管理系统区别于普通 CRUD 项目的核心是数据模型设计。先看两张最核心的表科目表和凭证表。科目表是财务系统的“骨架”资产、负债、权益、成本、损益五大类编号规则要符合会计习惯——1001 库存现金、1002 银行存款、1122 应收账款这类编码在教材里是现成的。凭证表是“血肉”每一笔业务最终都落在凭证上。建表 SQL 是财务系统的地基设计时至少要考虑字段完整性、逻辑删除、时间戳和唯一索引。我用下面的 SQL 建科目表和凭证表CREATE TABLE subject ( id BIGINT NOT NULL AUTO_INCREMENT, subject_code VARCHAR(20) NOT NULL COMMENT 科目编码, subject_name VARCHAR(50) NOT NULL COMMENT 科目名称, category CHAR(1) NOT NULL COMMENT 类别1资产 2负债 3权益 4成本 5损益, parent_id BIGINT DEFAULT NULL COMMENT 父科目ID一级科目为NULL, status TINYINT DEFAULT 1 COMMENT 状态1启用 0停用, deleted TINYINT DEFAULT 0 COMMENT 逻辑删除标记, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY idx_code (subject_code) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT会计科目表; CREATE TABLE voucher ( id BIGINT NOT NULL AUTO_INCREMENT, voucher_no VARCHAR(20) NOT NULL COMMENT 凭证编号如记-2024-0001, voucher_date DATE NOT NULL COMMENT 凭证日期, total_debit DECIMAL(12,2) NOT NULL COMMENT 借方总额, total_credit DECIMAL(12,2) NOT NULL COMMENT 贷方总额, status TINYINT DEFAULT 1 COMMENT 状态1已审核 0草稿, remark VARCHAR(255) DEFAULT NULL COMMENT 摘要, created_by BIGINT DEFAULT NULL COMMENT 制单人ID, deleted TINYINT DEFAULT 0, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uk_voucher_no (voucher_no) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT记账凭证表; CREATE TABLE voucher_entry ( id BIGINT NOT NULL AUTO_INCREMENT, voucher_id BIGINT NOT NULL COMMENT 所属凭证ID, subject_id BIGINT NOT NULL COMMENT 科目ID, direction CHAR(1) NOT NULL COMMENT 方向D借 C贷, amount DECIMAL(12,2) NOT NULL COMMENT 金额, summary VARCHAR(255) DEFAULT NULL COMMENT 分录摘要, PRIMARY KEY (id), KEY idx_voucher_id (voucher_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT凭证分录表;这三张表构成了账务系统的最小闭环。voucher 表存凭证头——编号、日期、总额voucher_entry 存凭证体——科目、方向、金额。之所以要拆成两张表是因为一张凭证有多条分录一对多关系如果不拆表数据就会出现大量冗余和更新异常。金额类型用 DECIMAL(12,2) 而不用 DOUBLE这是财务系统的基本常识DOUBLE 的二进制浮点误差会在月底对账时让你差出几分钱这在后面避坑章节会专门展开。voucher_no 上的唯一索引保证了凭证编号不重配合服务端生成器可以实现并发安全。3.2 复式记账的核心约束借贷平衡与金额类型复式记账是财务系统的灵魂。每笔业务至少涉及两个科目有借必有贷借贷必相等。这段约束要写进业务校验逻辑而不是指望录单人自觉。在 VoucherServiceImpl 里保存凭证前必须做三件事校验借贷总额相等、校验科目存在且启用、校验分录不为空。下面这段保存凭证的代码是财务系统最关键的一段public void saveVoucher(VoucherAddDTO dto) { ListVoucherEntryAddDTO entries dto.getEntries(); if (entries null || entries.size() 2) { throw new BizException(凭证至少包含两条分录); } BigDecimal totalDebit entries.stream() .filter(e - D.equals(e.getDirection())) .map(VoucherEntryAddDTO::getAmount) .reduce(BigDecimal.ZERO, BigDecimal::add); BigDecimal totalCredit entries.stream() .filter(e - C.equals(e.getDirection())) .map(VoucherEntryAddDTO::getAmount) .reduce(BigDecimal.ZERO, BigDecimal::add); if (totalDebit.compareTo(totalCredit) ! 0) { throw new BizException(借贷不平衡借方 totalDebit 贷方 totalCredit); } // 校验科目是否有效 for (VoucherEntryAddDTO e : entries) { Subject subject subjectMapper.selectById(e.getSubjectId()); if (subject null || subject.getStatus() ! 1) { throw new BizException(科目不存在或已停用 e.getSubjectId()); } } Voucher voucher new Voucher(); voucher.setVoucherNo(generateVoucherNo(dto.getVoucherDate())); voucher.setVoucherDate(dto.getVoucherDate()); voucher.setTotalDebit(totalDebit); voucher.setTotalCredit(totalCredit); voucher.setStatus(1); voucher.setRemark(dto.getRemark()); voucherMapper.insert(voucher); for (VoucherEntryAddDTO e : entries) { VoucherEntry entry new VoucherEntry(); entry.setVoucherId(voucher.getId()); entry.setSubjectId(e.getSubjectId()); entry.setDirection(e.getDirection()); entry.setAmount(e.getAmount()); entry.setSummary(e.getSummary()); voucherEntryMapper.insert(entry); } }这段代码里的关键约束有两个。第一个是金额累加用 BigDecimal.compareTo 而不是 equals原因是 BigDecimal 的 equals 方法会比较精度1.0 和 1.00 在 equals 下不相等但 compareTo 认为它们数值相等用 equals 会误杀合法凭证第二个是“先插凭证头再插分录”的顺序不能反因为 voucher_entry 表有 voucher_id 外键依赖必须先拿到凭证头的主键才能插入分录。你在论文里可以强调这个顺序是“保证数据完整性”的手段。事务问题也要考虑。上面这段方法现在还缺 Transactional 注解一旦某条分录插入失败前面插入的凭证头就会变成孤儿数据。把 Transactional(rollbackFor Exception.class) 加在方法上Spring 才能在 RuntimeException 抛出时回滚整个操作。这个注解是财务模块最容易漏的一环漏了以后系统里全是只有凭证头没有分录的脏数据。3.3 凭证的查询与分页列表、详情与条件检索凭证查询是财务管理系统日常使用频率最高的功能也是演示视频里必须展示的画面——用户要能按日期范围、凭证字号、科目筛选凭证列表点击某一条能看完整分录。分页可以用 MyBatis-Plus 自带的分页插件只需在配置类里注册 PaginationInnerInterceptorConfiguration public class MybatisPlusConfig { Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor new MybatisPlusInterceptor(); PaginationInnerInterceptor pagination new PaginationInnerInterceptor(DbType.MYSQL); pagination.setMaxLimit(100L); interceptor.addInnerInterceptor(pagination); return interceptor; } }分页参数 maxLimit 限制了单页最大条数防止有人把 pageSize 调到 10000 把数据库拖垮这是管理系统里常用的保护性设置。分页对象直接用 MyBatis-Plus 的 Page controller 里接收 pageNum 和 pageSize 两个参数传给 serviceservice 返回 Page 前端用 Vue 的 el-pagination 或 jQuery 的分页组件接住就行。凭证详情是个典型的一对多查询场景。常见做法是查 Voucher 主记录后再按 voucherId 查 voucher_entry 列表组装成 VoucherDetailVO 返回。也可以一次性查全部再在内存里分组但凭证量上去以后内存分组会带来不必要的开销。这里不追求极端性能两次查询的思路更好理解答辩时也容易讲清楚。4. 报表、权限与凭证编号答辩加分项里的三个细节4.1 报表怎么聚合用 SQL 把科目余额变成利润表财务系统的最终输出是报表答辩时能不能拿出像样的“利润表”“资产负债表”直接决定评委对项目深度的判断。报表实现不复杂核心是把凭证分录按科目方向汇总。利润表里最关键的是“主营业务收入”“主营业务成本”“管理费用”“财务费用”这些损益类科目的发生额聚合查询写出来是这样的SELECT s.id AS subject_id, s.subject_name, SUM(CASE WHEN e.direction D THEN e.amount ELSE 0 END) AS total_debit, SUM(CASE WHEN e.direction C THEN e.amount ELSE 0 END) AS total_credit FROM subject s LEFT JOIN voucher_entry e ON s.id e.subject_id LEFT JOIN voucher v ON v.id e.voucher_id WHERE s.category 5 AND v.voucher_date BETWEEN #{startDate} AND #{endDate} AND v.status 1 AND v.deleted 0 AND s.deleted 0 GROUP BY s.id, s.subject_name科目余额表是资产负债表的来源它的逻辑稍微复杂一点资产类科目借方表示增加权益和负债类科目贷方表示增加所以期末余额的计算公式要按类别区分。常见做法是用一个 SQL 把每个科目的期初余额和本期发生额汇总出来然后在 Java 层按“资产类 期初余额 借方发生额 - 贷方发生额负债权益类 期初余额 贷方发生额 - 借方发生额”的规则计算期末余额。这样虽然牺牲了一点 SQL 的复杂度但把计算逻辑放到 service 层后可以更好地在答辩时讲业务分析过程而不是只会念 SQL。4.2 权限控制怎么做拦截器实现角色访问财务系统的权限和普通管理系统不一样的地方在于“数据敏感”——凭证、报表只能让特定角色看不能让所有人都能点到。毕业设计不需要做细到按钮级别的 RBAC通常做到角色拦截就足够管理员能看所有菜单财务人员能录凭证和查账普通用户只能看基础信息。用 Spring 的 HandlerInterceptor 实现public class AuthInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HttpSession session request.getSession(); Object user session.getAttribute(loginUser); if (user null) { response.setContentType(application/json;charsetUTF-8); response.getWriter().write({\code\:401,\msg\:\未登录\}); return false; } return true; } }再在 WebConfig 里注册拦截器并设置放行规则Configuration public class WebConfig implements WebMvcConfigurer { Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new AuthInterceptor()) .addPathPatterns(/**) .excludePathPatterns(/api/auth/login, /api/auth/logout, /error); } }这种“一个拦截器 黑名单放行”的模式对毕业设计是最省力的选择。如果你需要角色区分可以在拦截器里校验用户角色字段或者给不同角色返回不同的菜单列表——常见的做法是登录时把菜单树一次性查出来放进 session前端根据 session 数据渲染侧边栏。这里注意前端的菜单隐藏只是体验层面的真正的权限控制一定要有后端校验兜底不能把“显示/隐藏菜单”当作权限实现。权限这块还涉及密码存储的细节财务系统的密码不要明文存。Spring Security 不在毕业设计推荐范围用 Shiro 或自写 MD5/SHA-256 加盐即可。建议至少做 SHA-256 加盐处理让论文里有“加密存储”这个关键词。没有做加密的财务系统答辩时如果被追问“密码怎么存的”现场会很难看。4.3 凭证编号生成高并发下不重号的设计凭证编号看似是小功能做不好会在演示时当场出丑。最常见的错误是查数据库里的最大号加 1String maxNo voucherMapper.selectMaxVoucherNo(); int seq Integer.parseInt(maxNo.substring(maxNo.length() - 4)) 1;两个用户同时操作时这个逻辑必然产生重复编号voucher_no 的唯一索引会直接抛 DuplicateKeyException。更稳妥的做法是用数据库的原子自增或者 Redis 的 INCR但毕业设计里引入 Redis 会增加部署复杂度一个简单可靠的办法是用“日期 当天序号”设计配合数据库唯一索引做兜底序号生成用 synchronized 或者数据库的 UPDATE 自增语句。下面是常见的实现public String generateVoucherNo(LocalDate date) { String dateStr date.format(DateTimeFormatter.ofPattern(yyyyMMdd)); String prefix 记- dateStr -; int seq 1; // 使用数据库原子更新来获取当天最大序号避免并发重复 Long maxSeq voucherMapper.selectMaxSeqByDate(date); if (maxSeq ! null) { seq maxSeq.intValue() 1; } return prefix String.format(%04d, seq); }这里 selectMaxSeqByDate 查询当天最大序号即使出现并发voucher_no 的唯一索引也会拦截重复插入让用户重新提交一次保证不会出现两条相同编号的凭证。如果你想做得更优雅可以把“查最大号 插入”放到同一个事务里配合悲观锁 SELECT ... FOR UPDATE这也是企业财务软件常用的思路。毕业设计里我建议用“唯一索引兜底”这个方案代码简单答辩时也能讲清楚“数据库约束是最后的防线”这个理念。凭证编号还要注意“作废凭证”场景凭证作废后它的编号不能拿给新凭证再用否则会造成账务追溯混乱这是财务软件和普通 CRUD 项目的显著区别。实现上作废凭证时把它的状态置为作废编号保留新凭证继续用递增序号保证凭证号的严肃性。5. 从环境到部署的常见坑毕业设计翻车现场排查记录5.1 springboot 版本太高mybatis-plus 启动直接报错现象项目一启动就抛java.lang.ClassNotFoundException: javax.servlet.Filter或者mybatis-plus相关类找不到控制台一片红色。原因springboot 3.x 用了 Jakarta EE 规范把 javax.servlet 包改名成 jakarta.servlet旧版 mybatis-plus 3.5.1 及以下还是按 javax 编译的两者不兼容。解决不要挑战最新版。springboot 2.7.x mybatis-plus 3.5.x 是当前最稳的搭配网上参考资料和源码也几乎都是这套组合。如果你确实要用 springboot 3.x把 mybatis-plus 升到 3.5.5 以上并且把所有 javax 开头的 import 改成 jakarta 开头。另外springboot 2.7 对应 JDK 8 或 11springboot 3 要求 JDK 17 才能跑起来环境版本不一致也会让人误判是代码问题。5.2 java 环境变量没配好全家桶都在黑匣子里现象命令行敲 java -version 能出来版本但启动 springboot 提示找不到主类或者 IDEA 里能跑、双击 jar 包就闪退。原因IDEA 自带 JDK 或会自动检测 JAVA_HOME但命令行启动 jar 走的是系统 JAVA_HOME。JAVA_HOME 没配或只配到 jre 路径jar 包启动时就找不到完整 JRE 环境。解决按 java 环境变量配置标准来JAVA_HOME 指向 JDK 安装目录不是 bin 目录Path 里加 %JAVA_HOME%\binCLASSPATH 配 .;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar。然后重启命令行再验证 java -version。这个坑几乎每年都有人踩一般发生在换电脑或换 JDK 版本之后属于环境问题里最磨人的一种。5.3 金额用 double 存储月底对账差了 8 分钱现象凭证录入时 0.1 0.2 显示 0.30000000000000004三张凭证汇总后对不上账月底试算平衡怎么都平不了。原因double 是二进制浮点数0.1 在二进制里是无限循环小数存储精度有限累加误差会逐渐放大。财务系统对金额的精度要求是“分”不允许这种误差存在。解决数据库字段统一用 DECIMAL(12,2)Java 实体统一用 BigDecimal禁止在代码里用 double 或 float 定义金额变量。BigDecimal 的构造建议用字符串构造器new BigDecimal(0.1)不要用new BigDecimal(0.1)否则误差在构造时就留下来了。给 Excel 导出做金额格式化时也一定要用 BigDecimal不要先把值转成字符串再格式化。5.4 日期时区问题mysql serverTimezone 引发的 8 小时错觉现象本地时间 12:00 录入的凭证查询出来变成了 04:00日期参数在控制台打印正确但存进数据库就少了 8 小时。原因MySQL 连接串里的 serverTimezone 没有配置或配置成 UTC数据库会话时区跟本地时区东八区不一致JDBC 驱动做时间转换时按 UTC 处理。解决jdbc url 里显式指定 serverTimezoneAsia/Shanghai同时注意 MySQL 8.0 以上驱动推荐用 com.mysql.cj.jdbc.Driver老驱动类名已废弃。Java 侧再给 Jackson 配 time-zone: Asia/Shanghai前后端日期格式化保持一致。这个排查套路值得记下来先看数据库连接串再看驱动类名最后看 Jackson 配置三层对齐才能避免“8 小时错觉”。5.5 中文乱码字符集不统一入库就变“???”现象页面填中文摘要保存后数据库里变成三个问号或者 Excel 导出时中文全部乱码。原因数据库连接串没配 characterEncodingutf8表结构默认字符集不是 utf8mb4或者前端页面没有声明 charset。解决数据库连接串加 characterEncodingutf8建表语句统一指定 DEFAULT CHARSETutf8mb4页面 meta 标签声明 utf-8。另外如果用了 MySQL 8.0 以上数据库本身默认字符集基本没问题但老库迁移时经常出现库、表、字段三级字符集不一致排查顺序是先看表结构 SHOW CREATE TABLE再看连接串最后看前端页面声明。乱码问题看着小但演示时满屏问号观感比功能 bug 还致命。6. 论文、PPT 与演示视频答辩前夜最该做的一次整体验证论文、PPT 和演示视频是毕业设计的交付物但很多人把它们当作“写代码之后的事”最后一周才赶工。我见过太多代码能跑但论文写得像说明书、视频里录到一半报错的同学。因为在代码阶段就该把论文骨架搭起来。论文大纲按“选题背景 → 技术选型 → 系统设计 → 系统实现 → 系统测试”展开每个章节对应一个代码模块系统设计对应数据库表结构系统实现对应 controller/service 的方法说明。这样写论文每句话都有代码支撑不需要编造数据。交付前建议按这份清单走一遍视频录制前先把数据库备份一次录完演示再恢复现场避免因为演示中的误操作污染数据“录视频时故意演示一个错误输入比如不平衡凭证展示系统的报错拦截效果这比全程一帆风顺更有说服力”这样的思路往往不被人注意但恰恰是答辩加分项演示时的环境尽量精简关闭不必要的软件避免弹窗打断节奏。我自己的教训是第一次做财务系统时把科目表和凭证表混成一张表结果试算平衡的逻辑写了一周也没彻底对平后来重新拆表两小时解决了问题。这个项目的价值不在写完的那一行行代码在于让你把“数据建模 → 业务规则 → 技术实现”这条链路完整走一遍。希望这份经验能让你少走我走过的弯按期完成并顺利通过答辩。希望帮到你。本文还有配套的精品资源点击获取
返回列表