1. 内容整体设计与思路拆解1.1 项目定位不是“作业”而是完整的工程实践拿到“Java Web 高校疫情防控web系统系统源码-SpringBoot2Vue3MyBatis-PlusMySQL8.0【含文档】”这个标题我第一反应是这不是一个简单的CRUD练习而是一个面向真实校园场景的信息化系统。高校疫情防控系统在2020年之后几乎是每所高校的刚需学生每日健康打卡、体温上报、请假出入校审批、异常情况追踪这些都是实实在在的业务场景。用SpringBoot2Vue3前后端分离架构来做说明作者是想把这个项目做成一个接近生产环境的标准工程而不是那种JSPServlet的老式教学代码。我实际拆解这类系统时通常会把需求分为三个层次基础层是学生和辅导员或管理员的登录认证与角色权限业务层是每日健康打卡、体温数据统计、请假审批流、异常记录管理展示层是用图表或表格直观呈现全校健康态势。SpringBoot2负责提供RESTful APIVue3负责页面渲染和交互MyBatis-Plus负责简化数据库操作MySQL8.0做持久化这套组合在目前的Java Web项目里属于非常主流的中小团队选型。1.2 为什么是这套技术栈而不是别的很多人会问为什么不用更轻的JPA或者为什么不用Spring Boot 3我有几点实际考虑。SpringBoot2对比Spring Boot 3最大的优势在于生态兼容性。目前大量第三方组件、老版本依赖在Spring Boot 2.x下最稳定尤其是MyBatis-Plus的Spring Boot 3 Starter在早期版本有一些兼容性问题很多教学资源和公司存量项目仍然基于2.x所以用SpringBoot2是一个很稳健的选择。MyBatis-Plus对比JPA或原生MyBatis可以说是“站在巨人的肩膀上”。JPA在复杂查询和SQL调优上不够直观原生MyBatis写XML又太繁琐而MyBatis-Plus内置了通用Mapper、条件构造器、分页插件能覆盖80%的单表CRUD剩下20%的复杂查询用自定义SQL补齐开发效率能提升至少一倍。对于高校疫情防控这种以单表操作和简单联表查询为主的系统MyBatis-Plus是最不折腾的选项。Vue3对比Vue2核心优势是Composition API和更高效的响应式机制。疫情打卡页面往往需要处理大量的表单状态和异步请求用Composition API组织逻辑比Options API更清爽。再加上Vite启动速度远超Webpack开发体验不是一个级别。这块我强烈建议直接用ViteVue3别用Vue CLI原因下文中我踩过的坑部分会详细说。MySQL8.0不用多说已经是当前数据库的事实标准版本。这里有个细节很多人忽略MySQL8.0默认认证插件是caching_sha2_password老版本Navicat和旧驱动会连不上所以项目里如果出现连接失败先排查驱动版本和连接URL参数这是最常见的坑之一。1.3 这套方案能帮你解决什么如果你是学生或刚转行Java开发的人这个项目能帮你把“会写接口”和“会做系统”之间的差距补上。它覆盖了权限拦截、统一返回体、异常处理、文件上传如学生上传健康码截图、定时任务每日打卡提醒这些真实项目才有的细节。如果你是辅导员或高校信息化部门的技术人员这个项目可以用极低的成本快速部署一套可用的健康打卡平台。SpringBoot2打包成jar直接扔到服务器上跑Vue3前端构建成静态文件用Nginx托管数据存在MySQL里整套东西没有复杂的中间件依赖一台2核4G的云主机完全带得动。所以这套方案的核心价值在于技术选型主流、代码结构清晰、业务场景真实、部署成本低。适合学习、适合二次开发、适合课程设计也能作为学校信息化建设的一个基础版本。2. 核心细节解析与实操要点2.1 数据库设计先看清业务再动手建表高校疫情防控系统的核心数据实体我梳理了一下大致是这几张表用户表学生、辅导员、管理员、每日健康打卡表、体温检测表、请假记录表、出入校申请记录表、异常情况记录表、通知公告表。其中用户表通常会有角色字段student/teacher/admin打卡表和请假表是最核心的业务表。设计打卡表时要特别注意不能简单地只存“今日体温”和“健康状况”还要考虑“今日是否已打卡”“打卡时间”“打卡位置”等信息。我当时做的时候打卡表结构大概是这样的id主键user_id关联用户表temperature体温精确到小数点后一位health_status健康状态枚举正常/咳嗽/发热等is_contact_risk是否接触高风险人群location打卡地点学生可能在校外remark备注create_time打卡提交时间可以再加一个打卡日期字段比如report_date用于区分“今天”和“历史记录”这里容易踩的第一个坑是不要用create_time去判断学生今天是否已打卡。因为打卡时间可能因为时区、手动改库等原因出现偏差最稳妥的做法是给打卡表加一个report_date字段每天只能插入当天日期的记录配合唯一索引user_id report_date从数据库层面防止重复打卡。请假和出入校申请表则要经历“提交 - 审批 - 通过/驳回”这几个状态。我建议用status字段0待审批/1通过/2驳回加上审批意见字段简化处理。不要一上来就设计工作流引擎疫情系统并非复杂OA过于复杂只会增加前后端联调成本。2.2 后端工程结构分包方式决定你能走多远SpringBoot2项目的包结构我推荐按模块划分而不是按技术类型划分。简单说就是controller、service、mapper这种大类分包只适合小项目一旦业务复杂起来代码找起来非常痛苦。按业务模块分包更合理比如com.example.epidemic ├── common 通用类统一返回体、异常处理、枚举 ├── config 配置类拦截器、跨域、MyBatis-Plus配置 ├── modules │ ├── auth 登录认证模块 │ ├── user 用户管理模块 │ ├── report 健康打卡模块 │ ├── leave 请假审批模块 │ └── notice 通知公告模块 └── utils 工具类日期处理、JWT工具等每个模块内部再分controller/service/mapper/entity这样模块之间互相独立新增功能不影响老代码。统一返回体是前后端分离项目必须做的一件事。我见过很多半路出家的项目接口返回有时是对象、有时是字符串、有时直接抛异常前端没法统一处理。我常用的返回结构是{ code: 200, message: 操作成功, data: { } }定义成一个Result类泛型设计所有Controller返回Result.success(data)或Result.fail(msg)前端用axios响应拦截器统一判断code能省掉大量重复的if-else判断。权限验证方面考虑到这是前后端分离项目Session机制不太好使我推荐用JWT做无状态认证。登录成功后后端返回一个token前端存储并在每次请求时放到Header里后端用拦截器校验token。JWT本身不算复杂关键是Token过期时间的设定校内系统可以把过期时间设为12小时或24小时避免学生频繁重新登录。2.3 MyBatis-Plus的使用要点不写SQL不等于不用懂SQLMyBatis-Plus最常用的三件套是BaseMapper、条件构造器LambdaQueryWrapper、分页插件。BaseMapper内置的selectById、insert、updateById这几个方法对付90%的单表操作绰绰有余。复杂一点的需求比如统计全校今日打卡人数可以用注解Select写原生SQL或者在mapper.xml里写。举个例子统计今日全院打卡率SQL大概是这样的SELECT COUNT(DISTINCT user_id) FROM report WHERE report_date CURDATE();配合MyBatis-Plus的分页插件PaginationInterceptor分页查询只要在Service层传入Page对象MyBatis-Plus自动帮你拼接limit语句不需要手写。这里要特别提醒一个坑MyBatis-Plus的分页插件配置在SpringBoot2中要注册一个MybatisPlusInterceptor的Bean同时指定PaginationInnerInterceptor如果漏了这一步分页会失效所有记录一次性查出来数据量一大系统就卡。另一个高价值功能是自动填充。create_time、update_time这种公共字段不必每次手动set使用TableField(fill FieldFill.INSERT)注解配合MetaObjectHandler全局填充省事还不容易漏。我建议所有业务表统一带上create_time、update_time、deleted逻辑删除这三个字段这几乎是企业级开发的标准了。逻辑删除也是MyBatis-Plus的一等公民。只需要在实体类字段上加TableLogic注解并在application.yml里配置逻辑删除的值为0和1删除操作就自动变为update deleted1查询自动过滤已删除数据。这个在用户管理、公告管理里非常实用物理删除用户会导致历史打卡数据关联断裂而逻辑删除不会。2.4 前端Vue3的工程化实践从页面到组件的组织思路Vue3项目的目录结构我习惯这样组织src ├── api 接口请求封装按模块拆分文件 ├── assets 静态资源 ├── components 公共组件 ├── router 路由配置 ├── store Pinia状态管理 ├── views 页面组件 └── utils 工具函数api目录下每个模块建一个js文件统一封装axios请求。比如report.js里是getTodayReport、submitReport、getReportHistory这几个方法。这样做的好处是页面组件里不直接出现axios代码接口路径集中在api文件夹里后端接口变动时只改一处。Vue3里我最喜欢的特性是Composition API的setup语法。以健康打卡页面为例打卡表单、今日状态、历史记录这些逻辑以前要分散在data、methods、computed里现在全部可以在setup里用ref、reactive、computed组织逻辑内聚性强得多。配合