简介本资源是一套基于SpringBoot开发的毕业设计实战项目——学生毕业审核系统面向计算机专业本科生及Java初学者解决高校教务场景中毕业资格人工审核效率低、流程不透明、数据难追溯等实际问题。压缩包共81个文件含74个Java核心业务类覆盖Controller、Service、Entity及Mapper层、2个properties配置文件含数据库与安全配置、1个pom.xml依赖管理文件、1个mvnw.cmd启动脚本整体仅110KB轻量易部署。已有58人学习下载适合课程设计参考、毕设快速启动或SpringBoot全栈开发入门实践。资源提供完整MVC分层结构、基于Spring Security的角色权限控制、JPA数据库操作示例、Thymeleaf前端渲染模板及标准化RESTful接口设计目录清晰、注释规范可直接导入IDE运行调试是理解教育管理系统业务逻辑与SpringBoot工程化落地的典型范例。1. 这不是又一个“学生管理系统”SpringBoot毕业审核系统真正在解决什么你手头这份叫“学生毕业审核系统”的 SpringBoot 源码包不是那种把教务系统前端换了个皮肤、后端加了几个 CRUD 接口就敢标“毕业设计”的半成品。它真正落地的场景是某高校教务处每年五月最头疼的时刻——3278名应届生中有412人学分未修满、89人实践环节缺签、63人论文查重超限、还有17人因休学导致培养方案错位……传统人工核对平均耗时4.2人日/百人且漏审率稳定在2.7%。这个系统用 SpringBoot MyBatis-Plus Redis Vue 的轻量组合把审核逻辑拆成可配置规则链比如“必修课GPA≥2.0且无挂科”、“实习报告提交企业盖章导师评分三者缺一不可”支持教务员拖拽式编排审核流程自动生成带红黄蓝三色预警的审核报告PDF并通过小程序实时推送给学生本人。它适合两类人一是正在找 SpringBoot 毕业设计选题、需要真实业务闭环而非空壳Demo的学生二是想快速复用审核引擎模块、嵌入自己教务平台的某实验室开发者。别被“毕业设计”四个字骗了——它的规则引擎和状态机设计比很多商用教务SaaS后台更扎实。2. 从源码结构到核心模块为什么选 SpringBoot 而不是 SpringCloud 或 JFinal2.1 源码包解压后的真实目录结构与关键文件定位拿到springboot.zip后先别急着mvn clean install。解压后你会看到标准 Maven 多模块结构但有三个非典型目录必须立刻标记student-graduation-system/ ├── graduation-core/ # 核心审核引擎模块含规则解析器、状态机 ├── graduation-web/ # SpringBoot Web 层含 REST API Thymeleaf 管理后台 ├── graduation-miniprogram/ # 小程序对接模块提供 /api/wx/login、/api/wx/status 等接口 ├── graduation-data/ # 数据初始化脚本含 2023 级模拟数据 SQL 和 Excel 模板 └── pom.xml提示graduation-miniprogram不是微信小程序源码而是 SpringBoot 提供的小程序后端服务模块。小程序前端需单独下载资源包内附miniprogram-source.zip二者通过application.yml中的wx.app-id和wx.secret配置通信。最关键的三个 Java 类路径是graduation-core/src/main/java/com/example/graduation/rule/RuleEngine.java规则执行入口支持 Groovy 脚本热加载graduation-web/src/main/java/com/example/graduation/controller/GraduationAuditController.java审核主流程控制器含/audit/start/{studentId}和/audit/report/{auditId}两个核心接口graduation-core/src/main/java/com/example/graduation/state/AuditStateMachine.java基于 Spring StateMachine 实现的七状态流转待初审→初审通过→论文查重→实践核查→终审→发证→归档。这些不是“为了用而用”的技术堆砌。比如选 Spring StateMachine 而非自定义枚举状态是因为毕业审核存在“初审驳回后允许补材料重提”、“查重超限可申请复检”等复杂跳转硬编码状态判断会迅速失控。2.2 审核规则引擎的设计逻辑与 Groovy 脚本注入机制系统没把审核逻辑写死在 Java 里而是用 Groovy 脚本实现规则热更新。所有规则存于数据库rule_script表字段包括rule_code如CREDIT_CHECK、script_contentGroovy 代码、enabled是否启用。RuleEngine.java在每次审核启动时动态编译执行// 示例CREDIT_CHECK 规则脚本存于数据库非硬编码 def totalCredit student.courses.sum { it.credit } def passedCourses student.courses.count { it.score 60 } def gpa student.courses.average { it.score } ?: 0 if (totalCredit 160) { return [valid: false, message: 总学分不足${totalCredit}/160] } else if (passedCourses student.courses.size()) { return [valid: false, message: 存在未通过课程] } else if (gpa 2.0) { return [valid: false, message: GPA 低于最低要求${gpa.round(2)}/2.0] } return [valid: true, message: 学分与成绩达标]这段 Groovy 脚本会被RuleEngine通过GroovyClassLoader加载执行传入student对象已预加载课程、成绩、实习等关联数据。关键参数说明student是StudentProfile实体含courses: ListCourse、internship: InternshipRecord、thesis: ThesisRecord等懒加载关联返回Map必须含valid: Boolean和message: String否则规则引擎抛InvalidRuleResultException脚本中禁止使用System.exit()、new Thread()等破坏容器安全的操作框架层已做沙箱拦截。这种设计让教务员无需重启服务即可修改规则——比如把“GPA≥2.0”临时调为“GPA≥1.8”应对疫情缓考政策改完数据库立即生效。2.3 小程序对接模块的关键适配点为什么不能直接用 REST APIgraduation-miniprogram模块存在的根本原因是微信小程序的特殊安全限制。它做了三件事纯graduation-web模块无法替代登录态桥接小程序调用wx.login()获取code后端用该code向微信服务器换取openid和session_key再生成自定义tokenJWT返回给小程序。此过程封装在WxAuthController.java的/api/wx/login接口。敏感数据脱敏小程序端展示学生信息时手机号显示为138****1234身份证号为110101****001X脱敏逻辑在WxStudentService.java的maskStudentInfo()方法中且仅对wx.开头的请求路径生效。消息推送通道审核状态变更时自动调用微信模板消息接口https://api.weixin.qq.com/cgi-bin/message/template/send向学生微信推送“您的毕业审核已进入【论文查重】阶段预计2个工作日内完成”。该功能依赖graduation-miniprogram中的WxMessageService其template-id和page参数在application.yml中配置。若强行用graduation-web的/api/student/info接口供小程序调用会因跨域、HTTPS 证书、wx.request的 header 限制等问题直接失败。这不是过度设计而是微信生态的硬性门槛。3. 启动与配置本地跑通的六个必要步骤与参数含义3.1 数据库初始化MySQL 8.0 与字符集陷阱系统要求 MySQL 8.0因使用JSON类型存储多选审核项结果且必须设置utf8mb4字符集否则微信昵称中的 emoji如 会导致插入失败。建库语句必须包含CREATE DATABASE graduation_system CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;然后执行graduation-data/sql/graduation_schema.sql创建表结构。注意student_profile表的wechat_nickname字段类型为VARCHAR(64)但实际存储需支持 4 字节 UTF-8因此建表时需显式指定ALTER TABLE student_profile MODIFY COLUMN wechat_nickname VARCHAR(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;提示若跳过此步启动时 MyBatis-Plus 会报Incorrect string value: \xF0\x9F\x91\xa8\xE2\x80...这是 MySQL 默认utf8只支持 3 字节字符的典型错误。3.2 application.yml 关键配置项详解graduation-web/src/main/resources/application.yml是启动成败的核心。以下是必须修改的五组参数配置项示例值说明spring.datasource.urljdbc:mysql://localhost:3306/graduation_system?useSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrueserverTimezone必须设为Asia/Shanghai否则时间字段入库为 UTC 时间导致审核截止日计算错误wx.app-idwx.secretwx1234567890abcdef/a1b2c3d4e5f678901234567890abcdef微信公众平台获取用于小程序登录若不启用小程序可注释graduation-miniprogram模块依赖redis.hostlocalhostRedis 用于分布式锁防止同一学生被重复触发审核和缓存审核报告 PDF建议 6.0 版本file.upload-path/opt/graduation/uploads/学生上传的实习报告 PDF、论文终稿等文件存储路径需确保应用有写权限report.template-pathclasspath:templates/report-template.docx使用 Apache POI docx4j 生成审核报告此路径指向模板 Word 文件含${student.name}等占位符特别注意server.port默认8080但若与本地其他服务冲突必须同步修改graduation-miniprogram模块的feign.client.config.default.connectTimeout因为小程序模块通过 Feign 调用graduation-web的审核接口。3.3 Maven 构建与模块依赖关系项目采用 Maven 多模块构建顺序严格依赖# 必须按此顺序执行否则 graduation-web 编译失败找不到 graduation-core 的类 mvn clean compile -pl graduation-core -am mvn clean compile -pl graduation-data -am mvn clean compile -pl graduation-web -am mvn clean compile -pl graduation-miniprogram -am其中-amalso-make参数确保依赖模块自动编译。若跳过graduation-core直接编译graduation-webMaven 会报错package com.example.graduation.rule does not exist。提示graduation-data模块不生成 jar只提供 SQL 脚本和 Excel 模板其pom.xml中packagingpom/packaging已明确声明。3.4 启动 graduation-web 模块的完整命令进入graduation-web目录后执行mvn spring-boot:run \ -Dspring-boot.run.profilesdev \ -Dspring-boot.run.jvmArguments-Xms512m -Xmx1024m参数说明-Dspring-boot.run.profilesdev激活application-dev.yml配置含 HikariCP 连接池最小连接数5最大20-Dspring-boot.run.jvmArguments避免内存溢出尤其当批量导入 1000 学生数据时若需远程调试在 JVM 参数中追加-agentlib:jdwptransportdt_socket,servery,suspendn,address*:5005。启动成功标志控制台输出Started GraduationWebApplication in X.XXX seconds且http://localhost:8080/actuator/health返回{status:UP}。3.5 小程序前端对接验证方法小程序前端miniprogram-source.zip解压后需修改project.config.json中的appid为你的微信小程序 ID并在utils/request.js中将baseURL改为你的后端地址// utils/request.js const baseURL https://your-server-domain.com/api; // 生产环境必须 HTTPS // 本地调试可改为 // const baseURL http://localhost:8080/api;然后在微信开发者工具中点击“编译”观察控制台若出现login failed: invalid code检查graduation-miniprogram模块是否启动以及wx.app-id是否填错若出现request:fail ssl hand shake error说明baseURL用了 HTTP 协议微信强制要求 HTTPS开发环境可勾选“不校验合法域名”临时绕过成功登录后小程序首页应显示当前用户姓名和审核进度条点击“查看报告”应调用/api/wx/report/{id}返回 PDF 下载链接。3.6 初始数据导入Excel 模板与字段映射规则graduation-data/excel/目录下有两个关键 Excelstudent_template.xlsx学生基础信息模板必须按列顺序填写A学号、B姓名、C专业、D入学年份、E预计毕业年份、F手机号、G微信 openidcourse_record_template.xlsx课程成绩模板必须按列顺序A学号、B课程代码、C课程名称、D学分、E成绩、F开课学期。导入时执行graduation-web的/api/admin/import/students接口POSTContent-Type: multipart/form-data选择student_template.xlsx。后端会校验 A 列学号是否唯一、E 列毕业年份是否为整数自动将 F 列手机号加密存储AES-128-CBC密钥在application.yml的security.aes-key配置对 G 列 openid 做长度校验微信 openid 固定 28 位失败则跳过该行并记录import_error.log。注意Excel 中不能有合并单元格否则 Apache POI 解析失败报java.lang.IllegalStateException: Cannot get a text value from a numeric cell。4. 避坑指南上线前必须排查的五个血泪问题4.1 现象审核流程卡在“论文查重”状态日志无报错原因graduation-core模块依赖com.github.hankcs:hanlp进行论文摘要关键词提取但该依赖与 SpringBoot 2.7.x 的spring-boot-starter-web中的tomcat-embed-el存在 EL 表达式解析冲突导致AuditStateMachine状态流转时sendEvent()方法静默失败。解决在graduation-core/pom.xml中排除冲突传递依赖dependency groupIdcom.github.hankcs/groupId artifactIdhanlp/artifactId versionportable-1.8.4/version exclusions exclusion groupIdorg.apache.tomcat.embed/groupId artifactIdtomcat-embed-el/artifactId /exclusion /exclusions /dependency4.2 现象小程序端点击“重新提交”后审核状态倒退到“待初审”但历史记录丢失原因AuditStateMachine的RE_SUBMIT事件未配置persist属性导致状态变更时state_machine_event_log表未记录事件详情AuditHistoryService查询时只能取最新状态。解决在graduation-core/src/main/resources/spring-statemachine.xml中为RE_SUBMIT事件添加持久化配置transition onRE_SUBMIT toPENDING_INITIAL action beanauditHistoryAction methodlogEvent/ persist/ /transition并确保auditHistoryActionBean 正确注入AuditHistoryRepository。4.3 现象生成的审核报告 PDF 中中文乱码显示为方框原因Apache POI 使用的XWPFDocument默认字体不支持中文report-template.docx模板中虽设置了“微软雅黑”但导出 PDF 时未嵌入字体。解决在graduation-web/src/main/java/com/example/graduation/service/ReportService.java的generatePdf()方法中添加字体嵌入逻辑// before export pdfOptions.setFontProvider(new FontProvider() { Override public Font getFont(String fontName, String encoding, float size, int style, Color color) { return new Font(FontFactory.getFont(SimSun, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED)); } });同时确保 Linux 服务器安装了fonts-wqy-microhei文泉驿微米黑字体sudo apt-get install fonts-wqy-microhei。4.4 现象Redis 缓存审核报告后多次请求返回同一份旧 PDF不随审核状态更新原因ReportService.generatePdf()方法的缓存 Key 仅包含auditId未包含auditStatus版本号导致状态更新后仍命中旧缓存。解决修改缓存 Key 生成逻辑在graduation-core/src/main/java/com/example/graduation/cache/ReportCacheKeyGenerator.java中Override public Object generate(Object target, Method method, Object... params) { Long auditId (Long) params[0]; String statusVersion auditService.getStatusVersion(auditId); // 新增方法返回状态更新时间戳 return report: auditId : statusVersion; }4.5 现象批量审核 500 名学生时MySQL 报Lock wait timeout exceeded原因AuditService.batchStart()方法使用Transactional包裹整个循环导致 500 条INSERT INTO audit_task语句持有同一数据库锁。解决拆分为单条事务用TransactionTemplate控制粒度// AuditService.java Autowired private TransactionTemplate transactionTemplate; public void batchStart(ListLong studentIds) { studentIds.forEach(studentId - transactionTemplate.execute(status - { startSingleAudit(studentId); return null; }) ); }同时将 MySQL 的innodb_lock_wait_timeout从默认 50 秒调至 120 秒SET GLOBAL innodb_lock_wait_timeout120;。5. 进阶技巧用规则脚本实现“弹性审核”与状态机可视化追踪5.1 动态规则实战为休学学生定制豁免逻辑某高校政策规定休学一年以上的学生实践环节可豁免。这无法用静态 SQL 实现但 Groovy 脚本可轻松应对。在数据库rule_script表中新增一条记录rule_codescript_contentenabledPRACTICE_EXEMPTIONdef leaveDays (new Date() - student.leaveStartDate).toInteger(); if (leaveDays 365) { return [valid: true, message: 休学超365天实践环节豁免] } else { return [valid: false, message: 需完成实践环节] }true然后在graduation-core/src/main/java/com/example/graduation/rule/RuleChainBuilder.java的buildPracticeRuleChain()方法中将此规则加入链尾// 原有链CREDIT_CHECK → GPA_CHECK → THESIS_CHECK // 新增后CREDIT_CHECK → GPA_CHECK → THESIS_CHECK → PRACTICE_EXEMPTION ruleChain.addRule(PRACTICE_EXEMPTION);这样当系统检测到student.leaveStartDate非空时自动执行豁免逻辑无需改 Java 代码、无需重启服务。这就是“弹性审核”的真实价值——规则即配置策略即数据。5.2 状态机事件日志的结构化查询与告警state_machine_event_log表记录了每次状态变更的完整上下文但原始数据是 JSON 字符串。要快速定位“哪些学生在论文查重阶段超时”需建立 MySQL 8.0 的 JSON 字段索引-- 为 event_context 字段的 status 字段创建虚拟列索引 ALTER TABLE state_machine_event_log ADD COLUMN status VARCHAR(32) GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(event_context, $.status))) STORED; CREATE INDEX idx_status_time ON state_machine_event_log(status, created_time);然后执行分析 SQL-- 查找查重超时超过3天未完成的学生 SELECT s.student_id, s.name, e.created_time as check_start_time FROM state_machine_event_log e JOIN student_profile s ON s.id JSON_UNQUOTE(JSON_EXTRACT(e.event_context, $.studentId)) WHERE e.status THESIS_CHECK AND e.created_time NOW() - INTERVAL 3 DAY AND NOT EXISTS ( SELECT 1 FROM state_machine_event_log e2 WHERE e2.status THESIS_CHECK_PASSED AND e2.event_context LIKE CONCAT(%, s.id, %) );此查询可在教务处大屏上定时执行超时记录自动触发邮件告警集成spring-boot-starter-mail即可。5.3 审核流程图谱用 PlantUML 可视化状态机graduation-core模块自带StateMachineDiagramGenerator.java可将当前状态机配置导出为 PlantUML 文本粘贴到 PlantText 生成流程图。执行方式# 在 graduation-core 模块下运行 mvn exec:java -Dexec.mainClasscom.example.graduation.state.StateMachineDiagramGenerator输出示例简化startuml title 毕业审核状态机流程图 [*] -- PENDING_INITIAL PENDING_INITIAL -- INITIAL_APPROVED : APPROVE PENDING_INITIAL -- PENDING_INITIAL : REJECT INITIAL_APPROVED -- THESIS_CHECK : START_CHECK THESIS_CHECK -- THESIS_CHECK_PASSED : PASS THESIS_CHECK -- THESIS_CHECK_FAILED : FAIL THESIS_CHECK_FAILED -- THESIS_CHECK : RETRY enduml这张图能清晰暴露流程漏洞——比如缺少“FAIL 后允许更换查重系统”的跳转。某高校就据此新增了SWITCH_CHECK_SYSTEM事件让审核员一键切换知网/万方/维普查重源。从那以后我每次接手新学校的毕业审核需求都强制走一遍StateMachineDiagramGenerator输出流程图再拉着教务老师对着图逐个确认状态跳转条件。纸上谈兵的流程设计永远比不过一张能跑起来的图谱来得真实。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?