
字数多内容尽量扎实我直接按一篇可发布的博文来写结构上不套模板围绕这个毕业设计题目的选型、设计、实现、避坑、部署来说。1. 这个题目为什么值得做需求拆解与技术选型校园疫情防控信息管理系统这个名字听起来像是2020到2022年之间特别火的一类毕业设计题。现在再做它很多人会问一句“疫情都过去了这题还不过时吗”我的看法是如果你只把它理解成“管理核酸记录和健康码”那确实过时了。但如果你把它抽象成一套校园场景下的健康信息采集、审批流转、异常预警、数据统计平台那它本质上就是一个典型的企业级信息管理系统。这类系统的业务逻辑、权限模型、数据流转方式放在任何行业里都成立你换一个业务域比如换成“校园访客预约系统”“实验室设备报修系统”架构和代码几乎能平移过去。这正是这个题目在毕业设计里经久不衰的原因。从技术选型上看Java SpringBoot是这个题目最稳妥的组合。原因很简单SpringBoot是目前Java后端开发的事实标准网上资料多、社区活跃、面试也爱问。你把这个项目做完不只是拿到一个毕业设计而是把SpringBoot的自动装配、starter机制、事务管理、拦截器、参数校验这些核心知识点全部过了一遍之后找工作时面试官问起来你有一整套完整的项目经验可以讲。相比用PHP写个简单后台、或者用Python的Flask搭个轻量服务SpringBoot这个选型在“毕业设计答辩”和“求职面试”两个维度上都有明显优势。前后端分离还是单体应用是另一个需要想清楚的问题。我的建议是如果你只有一两个月时间不要硬上前后端分离。SpringBoot ThyemeLeaf模板引擎 Bootstrap一套代码搞定页面渲染和数据交互逻辑清晰答辩时也好讲。如果导师明确要求前后端分离那就SpringBoot写RESTful接口前端用Vue3 Element Plus配合JWT做登录鉴权。这个方案不是不行但你要额外处理跨域、Token刷新、路由守卫、打包部署这些事工作量至少多出三分之一。毕设的核心是“把一个闭环做完整”而不是“把技术栈堆得多高”这一点务必记住。2. 角色权限与数据流转先想清楚“谁在什么时候能看什么”做管理系统第一步不是写代码而是把角色和权限边界画清楚。校园疫情防控信息管理系统里用户大致分成三类普通学生/教职工、辅导员/院系管理员、校级管理员。这三类人看到的数据范围完全不同。普通用户只能看到自己的健康上报记录和审批状态辅导员能看本班级或本院系的数据能导出、能处理异常校级管理员能看全校的汇总统计能管理用户、发布通知、配置规则。权限这块如果做不好后面所有功能都会跟着乱。我给这个系统设计的权限模型是三层第一层是Spring Boot的拦截器做登录态校验第二层是自定义的角色注解做接口级别的权限控制第三层是数据查询时通过条件拼接做数据范围的控制。前两层很多教程都会讲但第三层是很多人忽略的。举个例子辅导员查学生健康上报记录SQL就一定要带学院和班级条件不能只判断一个角色就完事。否则一个辅导员登录后他理论上可以遍历出所有学生的数据这就是越权漏洞。这类问题在答辩时只要被老师点出来基本很难圆场。数据流转是另一个核心。一个学生的体温异常整个链路应该是这样的学生提交健康上报 - 系统比对异常规则体温超过设定阈值、位置异常、健康状态异常- 自动生成一条预警记录 - 推送通知给对应辅导员 - 辅导员查看异常详情标记为待处理 - 填写处理意见 - 系统把结果回填到上报记录。这个流程设计出来之后你再看数据库表结构心里就非常清楚了无非就是用户表、上报记录表、异常预警表、审批记录表这几张核心表再加字典表、通知表、日志表这些辅助表。3. 数据库表结构一张表一张表讲清楚为什么这么设计先给出一份核心表关系用户表sys_user关联角色表sys_role通过中间表做多对多健康上报记录表health_report以user_id关联用户异常预警表abnormal_alert以report_id关联上报记录审批记录表approval_record以alert_id关联预警记录。这四张表是主线其余的表都围绕它们扩展。以健康上报记录表为例字段设计上要考虑到“每日一报”这个业务特点。我用的是id、user_id、report_date、body_temperature、health_status正常/异常、location、contact_history、symptom_desc、create_time、update_time。其中report_date和user_id建议建联合唯一索引这样能保证一个用户一天只能报一次比在代码里先查再插要可靠得多。body_temperature用decimal(4,1)存储可以存36.5这种数据查询时也方便做范围比较。异常预警表是我觉得这个系统里比较有设计感的一张表。字段包括id、report_id、alert_type、alert_level、status待处理/已处理/已忽略、handler_id、handle_time、handle_remark、create_time。alert_type可以设计成字典编码比如101表示体温异常102表示位置异常103表示健康状态异常。alert_level分一般、紧急两级紧急级别是体温超过某个更高阈值或者同宿舍多条异常报告同时出现。这样设计的好处是预警规则本身是配置化的如果学校想调整阈值直接改配置表和规则代码不需要动表结构。班级和专业信息我建议单独建表不要直接塞在用户表的某个字段里。原因很简单统计场景里经常要按学院、按班级汇总单独建表后用id关联聚合查询和筛选都要干净得多也不容易出现“一个班名称改了历史数据全乱”的情况。这里我把学院表college、班级表class_info和用户表拆开用户只保存三个外键字段索引也不需要额外建太多查询性能在毕业设计的并发量下完全够用。4. 核心功能实现健康上报、审批流转、异常预警健康上报接口是这个系统里最核心、也是最应该做得规整的一个接口。前端页面提交的数据包括体温、健康状态、位置、接触史、症状描述后端接收后不能直接落库要做三件事参数校验、查重校验、然后才是插入。参数校验我用的是spring-boot-starter-validation给DTO字段加NotNull、DecimalMax这类注解Controller里用Validated触发校验。用户名下当天是否已上报就用前面说的联合唯一索引来处理插入时捕获DuplicateKeyException用全局异常处理器转成友好提示这样既保证了并发下的正确性代码也干净。审批流转我建议用一个状态字段驱动而不是在代码里写一堆if-else。预警记录的状态我设计成0待处理、1已处理、2已忽略。辅导员处理异常时只需要把状态从0改成1或2同时写入处理人、处理时间、处理意见。如果后续想扩展成多级审批比如辅导员处理后还要院系领导复核那就再加一个review_status字段或者直接引入一个简单的流程引擎。真要有这个需求我推荐一个轻量方案审批记录表里多存一个current_node和target_node每次操作就是一次状态迁移用一张独立的审批记录表把所有流转历史都存下来。异常预警的自动识别逻辑我放在Service层做抽了一个AlertRuleService。它的职责是拿到一条新鲜上报的健康数据逐条匹配规则。规则不写死在代码里而是从配置表里读取。举个例子配置表里有一条规则体温大于等于37.3且小于38预警等级为“一般”类型为“体温偏高”体温大于等于38预警等级为“紧急”。这样改阈值只需要改数据库配置不用改代码重新部署。规则引擎的代码本身不复杂就是一个规则的遍历列表逐条判断但这么设计之后整个系统的扩展性明显提升。如果你想把这块做得更漂亮还可以把规则抽成一个独立的策略接口不同类型的异常各自实现一个判断方法。另外前端页面上有一个功能我很推荐做出来健康上报日历视图。用前端框架的日历组件把当前用户一个月的上报情况用不同颜色标出来绿色是正常黄色是异常已处理红色是异常未处理灰色是未上报。这个页面在答辩演示时视觉效果非常好而且实现起来不复杂后端提供一个按月份查询上报状态的接口就够了。5. SpringBoot原理与项目结合自动装配、循环依赖、版本兼容做这个项目时有几个SpringBoot的知识点会真实地踩到不是背面试题而是写代码写出来的。第一个是自动装配。SpringBoot的核心是spring-boot-autoconfigure模块它根据classpath下的jar包和application.yml里的配置自动帮你生成一堆Bean。这个项目里最能说明问题的就是spring-boot-starter-data-redis的引入。你只要在项目里引入这个starterSpringBoot就会自动帮你创建RedisTemplate和StringRedisTemplate这两个Bean前提是配置里有redis连接信息。它靠的是EnableAutoConfiguration注解加META-INF/spring.factories文件里的自动配置类列表来扫描每一个自动配置类上都有ConditionalOnClass、ConditionalOnMissingBean这类条件注解。理解了这个机制你就能明白为什么加了依赖之后“什么都不用配就能用”也就能明白为什么有时候配置了感觉不生效——大概率是条件注解没有满足。第二个是循环依赖。这个项目里我的预警规则Service和审批Service之间曾经出现过循环依赖A中注入了BB中又注入了A。SpringBoot 2.6版本开始Spring官方默认禁止了循环依赖启动阶段直接报错。我当时的处理方式是重构把两个Service共用的逻辑抽到第三个Service里消除循环。不建议用Lazy注解去绕那只是延迟注入治标不治本而且后续维护的人会非常困惑。答辩时如果被问到这个点你可以解释清楚为什么需要避免循环依赖这会是一个很好的加分项。第三个是版本不兼容。前两年SpringBoot 3.x发布之后很多人直接把新建项目的版本选择到3.x结果发现JDK 8不能用了必须JDK 17以上SpringCloud对应的组件版本也要跟着换javax.的包名全部变成jakarta.旧项目里一堆import全部要改。我做这个项目时用的是SpringBoot 2.7.x JDK 8原因只有一个稳。毕业设计追求的是稳定可用、资料多好查错2.7.x是2.x的最后一个大版本该修的bug都修了网上教程、博客、论坛里踩坑记录一搜一大把而3.x虽然新但很多老资料里的代码跑不起来。如果你是做毕业设计不要追新选你最有把握的组合。6. 事务、定时任务、数据统计别让细节拖垮整体事务这块我遇到过两个典型的坑。第一个是事务不生效。我在Service层写了一个方法里面依次执行更新上报记录、写预警数据、写入通知表本意是一个事务。但这个方法被同类另一个方法调用而调用方没有打Transactional于是里面所有操作都是各自独立提交的如果第二步出错第一步已经提交了数据就对不上。这就是经典的“自调用事务失效”。解决方法是把需要事务保障的操作放到一个独立的Bean里从外部调用或者用编程式事务TransactionTemplate。第二个坑是事务粒度太大。有段时间我直接在整个统计接口上加了Transactional统计方法里做了三次聚合查询和一次Excel导出本地测试时发现导出一条几千条数据就要好几秒而且长期占用数据库连接。后来我把这个接口的Transactional去掉改成只读场景不加事务性能立刻上来了。记住事务只加在有写操作且需要原子性的方法上查询方法默认不加这种事不用多想了一定要养成习惯。定时任务在这个系统里有一个很实际的需求每天晚上9点自动统计当天未上报的学生名单生成一条待办通知推送给辅导员。SpringBoot里做定时任务很简单在启动类或配置类上用EnableScheduling然后在方法上加Scheduled(cron 0 0 21 * * ?)就行。这里要注意的是定时任务里做的事情要设计成幂等的比如重复执行两次结果不能变。我的做法是先查当天已经生成过通知的辅导员id列表过滤掉之后再批量生成新的通知这样即使服务器因为某种原因同一天执行了两次任务也不会产生重复通知。数据统计页面是这个项目的“门面”又是容易被忽略的地方。我建议至少实现3个统计模块全校当日上报率饼图、各学院近7天上报趋势折线图、异常事件分类统计柱状图。统计SQL不用写得太复杂上报率和趋势都可以用GROUP BY加日期函数搞定。例如统计近7天每天的应报人数和实报人数用JOIN拼接用户表再按日期分组就能拿到。前端我用的ECharts后端只需提供几个统计接口直接返回聚合后的JSON数组渲染很轻松。如果数据量将来真的涨到几十万条再用定时任务把统计结果提前算好存进一张统计报表表查询时只读表就行这是后话但答辩时你可以主动提这个优化思路老师会觉得你考虑到了扩展性。7. 文件导出、消息通知与日志让系统用起来像个产品答辩时老师最看重的是系统能不能完成一个完整的“业务闭环”。健康上报只是入口审批预警只是过程数据导出和消息通知也是闭环里不能少的一环。我用EasyExcel做数据导出支持按条件查询后一键导出Excel导出的列包括学号、姓名、班级、体温、健康状态、上报时间、异常处理结果。EasyExcel比传统的POI好用得多内存占用低写起来也简单定义一个实体类加注解一行代码就能写出Excel文件。导出时有一个细节文件名里带日期比如“20240601_计算机学院_健康上报记录.xlsx”这样用户下载多个文件时不会搞混。消息通知我用的是两种方式。一种是站内信系统内部的通知表用户登录后在首页右上角能看到未读数量的小红点另一种是邮件通知异常预警触发时调用JavaMailSender往辅导员的邮箱发一封邮件。站内信的实现是个标准功能一张通知表加一个已读状态字段就搞定。邮件这里有个小坑很多学校的邮箱对第三方SMTP密码有独立设置不是直接用登录密码需要到邮箱设置里开启SMTP并生成专用授权码。这个我在测试时就卡了半天后来换用QQ邮箱的授权码才通。答辩演示时不要依赖邮件发送现场网络不通或者邮箱服务不稳定会卡住演示节奏把邮件发送做成可选功能SQL里记录发送状态就行。日志这块我直接用了Spring Boot自带的Logbacklogback-spring.xml里按天滚动保留30天把Controller层的请求日志、Service层的业务日志、异常日志分开打印。做系统时你可能觉得日志不太重要但真正调试问题时你就知道日志多关键了。比如学生数据上报失败参数校验没通过前端只提示“上报失败”如果后端没有把具体原因打印出来排查问题只能靠猜效率极低。我习惯在Service层每个核心业务入口都打一条INFO日志记录入参、处理结果和耗时异常时打ERROR并带上完整的异常堆栈。部署到linux环境上后用grep加awk就能分析日志非常方便。8. 部署上线与答辩准备从本地跑起来到他人能访问毕设项目如果只在idea里能跑说服力是不够的。我建议至少把它部署到一台云服务器上让导师同学通过浏览器访问。云服务器选最便宜的1核2G配置就够操作系统用CentOS 7或Ubuntu 20.04都行。项目打包用Maven执行mvn clean package -DskipTests生成一个jar包用nohup java -jar xxx.jar --spring.profiles.activeprod命令启动然后把jar包放到systemd服务里管理开机自启。配置文件的区分很重要我用application-dev.yml和application-prod.yml两个环境dev连本机MySQLprod连云服务器上的MySQL数据库账号密码通过环境变量注入不写死在代码里。这样既方便本地开发也方便线上部署。数据库部署我直接用了宝塔面板虽然有些大牛不屑于用这种可视化面板但对于独立完成一个毕业设计的学生来说它真的能节省大量时间和精力MySQL、Nginx、Redis面板上点几下就能装好配好。服务器的安全组一定记得把3306端口对公网关闭只允许本地访问否则数据库就会被全网扫描和爆破。线上环境我还会加一层Nginx反向代理监听80/443端口把请求转发到SpringBoot的8080端口同时开启HTTPS证书。为什么用Nginx而不是直接暴露8080因为HTTPS、静态资源缓存、连接超时这些能力Nginx做起来非常顺手SpringBoot内嵌的Tomcat也能做但配置更繁琐而且把8080端口暴露给公网总觉得不安心。答辩之前务必要做的事有这么几件第一准备一份正常的演示数据如果数据库里全是测试垃圾数据演示效果会大打折扣。第二把所有页面完整走一遍流程反复确认核心功能没有bug尤其是登录鉴权、上报提交、异常处理这条主链路。第三准备一些团队里常见的Redis和MySQL性能优化点以及自己项目的后续发展计划老师喜欢问“你项目有没有考虑性能优化”“有记录用户行为数据吗”这类问题。我当时被问到的是“如果高峰期几千人同时上报系统会不会卡”我讲了自己的优化思路前端做防重复提交按钮、后端加Redis分布式锁避免重复插入、静态资源走CDN、数据库连接池适当调大。这个回答老师很满意因为能看出你真的深入想过系统的极限在哪里。