恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
Spring Boot社区疫情防控管理系统开发实战:从数据库设计到WebSocket推送
首页
资讯中心
/
Spring Boot社区疫情防控管理系统开发实战:从数据库设计到WebSocket推送
Spring Boot社区疫情防控管理系统开发实战:从数据库设计到WebSocket推送
发布时间:2026/9/7 20:10:18
每年到这个节点私信里问得最多的就是“Spring Boot 社区疫情防控管理系统这道题怎么做”。说实话这道题在计算机毕业设计里属于典型的高性价比题目——它不像纯电商系统那样业务臃肿也不像纯算法题那样需要硬核创新点它正好卡在“需求明确、技术栈完整、工作量可控”这个区间。用 Spring Boot 做核心框架把健康打卡、出入登记、物资管理、通知公告这些业务串起来一套标准的 Restful 接口加权限控制、定时任务、消息推送就能完整展示应届生该有的工程能力。这篇就把我从需求设计到部署上线的完整过程拆开讲包括数据库表结构怎么设计、健康打卡和出入登记流程怎么落地、WebSocket 实时推送怎么做、Redis Stream 怎么用、最后怎么打包部署到 Tomcat以及我踩过的坑。适合正在选型、已经开题、或者代码写到一半卡住的同学参考。内容偏实操我会把可复现的代码和配置直接放出来你自己照着改就行。1. 项目定位与技术选型为什么是 Spring Boot 而不是 SSM 或 Spring Cloud1.1 这道题的需求边界先搞清楚系统到底要管什么很多同学拿到题目第一反应是“社区疫情防控”这个前缀很大担心业务太复杂。实际上毕业设计里的“社区疫情防控管理系统”本质是一个面向社区场景的信息管理平台核心用户有三类社区居民、社区工作者、系统管理员。需求拆开看无外乎这四块健康管理居民每日健康打卡、体温上报、异常状态标记、历史记录查询。出入管理社区出入口登记、来访人员记录、出入时间统计。信息发布通知公告发布、防疫知识推送、提醒消息触达。基础数据居民信息台账、楼栋房屋信息、社区工作者账号管理、系统数据统计大屏。这套需求说白了一个词就能概括——台账管理再加一点流程审批和消息通知。和电商系统比它的业务深度浅但覆盖面广非常适合用来展示 Spring Boot 的 CRUD、权限控制、定时任务、消息推送、文件上传、数据可视化这些常见技能点。所以第一步不是急着写代码而是拿着这个功能边界去画用例图、列功能清单这决定了你后面的论文和答辩能讲出多少东西。1.2 Spring Boot 的选型理由省事、主流、面试有得聊我见过不少同学在技术选型上纠结用 SSM 是不是显得基础扎实用 Spring Cloud 是不是更有含金量我的建议很直接毕设选 Spring Boot 是对的别在这个阶段强行上 Spring Cloud。Spring Boot 相比传统 SSM 最大的价值是“自动装配 约定大于配置”。你不需要手写一堆 XML 配置数据源、配置事务、配置 MyBatis 映射一个spring-boot-starter-web依赖加进去内嵌 Tomcat 直接跑起来。这对毕设开发效率的提升非常明显你省下来的时间可以去做前端页面、写论文、准备答辩。而 Spring Cloud 那套服务注册发现、网关、配置中心对于单机部署的社区管理系统来说完全是过度设计。答辩时老师大概率会问“你这个系统为什么不用微服务”你只要答清楚“当前业务规模单机足以承载微服务会引入不必要的运维复杂度但我在架构上保留了拆分空间”这就够了。选 Spring Boot 还有一个隐性好处就业市场认这个。你在简历上写“熟练使用 Spring Boot MyBatis-Plus Redis Vue”比写“熟悉 SSM 框架”更好找工作因为现在中小企业 Java 岗位的主流技术栈就是这些。1.3 技术栈与版本组合照着这套选不踩版本坑版本选择是很多新手容易翻车的地方。Spring Boot 的版本和 JDK、SpringfoxSwagger、MyBatis-Plus 都有兼容性问题我推荐这套经过验证的组合组件推荐版本说明JDK1.8主流毕设环境兼容性最好不要用 17 给自己找麻烦Spring Boot2.7.x稳定、资料多支持 JDK8和 springfox 3.0.0 需要额外配置兼容MyBatis-Plus3.5.x内置分页插件、代码生成器比纯 MyBatis 省一半代码MySQL8.0.x用 utf8mb4 编码支持 emoji 和生僻字Redis6.x用于缓存热点数据和 Redis Stream 消息队列前端Vue 2 Element UI毕设最稳组合或者直接用 Thymeleaf 模板引擎做服务端渲染Swaggerspringfox 3.0.0 或 springdoc-openapi2.6 版本用 springfox 会报 PathPattern 错误建议直接用 springdoc这里重点提醒一下 Spring Boot 2.6 和 springfox 3.0.0 的兼容问题Spring Boot 2.6 之后默认的路径匹配策略从 AntPathMatcher 改成了 PathPatternParserspringfox 3.0.0 没适配这个改动启动时会直接报Failed to start bean documentationPluginsBootstrapper或NullPointerException。解决办法有两个一是配置文件里加spring.mvc.pathmatch.matching-strategyant_path_matcher二是直接把 swagger 依赖换成 springdoc-openapi-ui 1.6.x。我建议后者一劳永逸后面 3.5 节会单独讲。2. 数据库设计与权限模型先把表结构和角色理清楚2.1 核心表设计与字段说明五张主表就能跑通全部业务我做这套系统时数据库没有设计得很花哨五张核心表基本就能覆盖全部功能居民表、健康打卡表、出入登记表、通知公告表、用户表。另外加一张楼栋表做数据隔离一张物资表做可选扩展。居民表resident的核心字段我这样设计CREATE TABLE resident ( id bigint(20) NOT NULL AUTO_INCREMENT, name varchar(50) NOT NULL COMMENT 姓名, id_card varchar(18) NOT NULL COMMENT 身份证号, phone varchar(11) NOT NULL COMMENT 手机号, building_no varchar(20) DEFAULT NULL COMMENT 楼栋号, unit_no varchar(20) DEFAULT NULL COMMENT 单元号, room_no varchar(20) DEFAULT NULL COMMENT 房号, health_status tinyint(1) DEFAULT 0 COMMENT 健康状态 0正常 1异常, is_isolated tinyint(1) DEFAULT 0 COMMENT 是否居家隔离, create_time datetime DEFAULT CURRENT_TIMESTAMP, update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY idx_building (building_no) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT居民信息表;健康打卡表health_check单独建表而不是在居民表里加字段是因为打卡是高频写操作、历史数据要留痕。一张打卡记录表包含居民 id、体温、症状描述、是否异常、打卡时间再加一个唯一索引(resident_id, check_date)防止同一天重复提交。出入登记表access_record记录每一次进出事件字段包括居民 id 或访客姓名、手机号、进出方向、体温、事由、登记时间。这张表是后面做 WebSocket 实时推送和统计的数据来源所以索引一定要建在create_time上不然查“今天进出多少人”时数据量大了会很慢。通知公告表就是标准的 title content publisher_id publish_time没什么特殊。用户表我用 Spring Security 默认的user表结构改造加了一个role字段区分管理员、社区工作者、居民三种角色。我踩过的坑是一开始为了省事把打卡记录和居民信息放在一张表里结果每次查询都要 group by写统计 SQL 时差点把自己绕晕。记住一个原则高频操作数据、有历史状态的业务一定要单独建表。2.2 角色权限与核心业务流程不是随便加个字段就能完事权限设计是答辩时老师最爱问的点。社区疫情防控管理系统至少要区分三种角色管理员、社区工作者、居民。居民能做的事很少健康打卡、查看自己的历史记录、收到通知。社区工作者负责审核异常打卡、登记进出人员、发布通知、查看本社区的统计数据。管理员负责账号管理、基础数据维护、全量数据导出。我用 Spring Security JWT 来做认证授权核心流程是登录成功后签发 JWT前端每次请求把 token 放在 Authorization 头里后端拦截器解析 token 拿到用户 id 和角色再通过注解或拦截器做接口级权限控制。一个比较重要的细节是不要把角色判断写死在 Controller 里到处复制粘贴。我建议做一个自定义注解RequireRole(admin)配合 Spring AOP 切面统一校验这样代码干净答辩时也能讲出设计思想。核心逻辑大概长这样Aspect Component public class RoleAspect { Before(annotation(requireRole)) public void checkRole(JoinPoint point, RequireRole requireRole) throws Exception { // 从 ThreadLocal 或 SecurityContext 获取当前用户角色 String currentRole getCurrentUserRole(); String requiredRole requireRole.value(); if (!requiredRole.equals(currentRole)) { throw new BusinessException(403, 无权限访问); } } }业务流程上健康打卡最核心的链路是居民提交体温和症状 → 后端校验是否异常 → 若体温超过阈值比如 37.3℃自动标记异常 → 推送提醒给社区工作者 → 工作者确认后更新居民健康状态。这套流程里校验和推送是重点。2.3 状态设计用数字字典代替散落魔法值我在做这套系统时最痛苦的不是写 CRUD而是维护各种业务状态。比如健康状态有正常、疑似、确诊、已康复出入登记有待审核、已放行、已拒绝隔离状态有未隔离、居家隔离、集中隔离。如果代码里到处都是if (status 1)到后面你根本记不住 1 代表什么。我的做法是建一个状态枚举类统一管理并用注释把字典值写清楚public enum HealthStatus { NORMAL(0, 正常), SUSPECTED(1, 疑似), CONFIRMED(2, 确诊), RECOVERED(3, 已康复); private final int code; private final String desc; // 构造方法和 getter 省略 }同时数据库里用tinyint存状态码页面展示时通过枚举转成中文描述。答辩时能讲出“业务状态字典化、前后端状态统一约定”这种词是加分项。别小看这一点工作后你会发现很多系统烂就烂在状态值不统一。3. Spring Boot 核心功能实操从打卡到统计的完整链路3.1 工程结构分层与配置目录结构长这样项目整体采用经典的分层架构controller 层负责接口接收参数和返回结果service 层处理业务逻辑mapper 层用 MyBatis-Plus 操作数据库。目录结构我放下面照着建就行com.example.community ├── CommunityApplication.java // Spring Boot 启动类 ├── config │ ├── SecurityConfig.java // Spring Security 配置 │ ├── RedisConfig.java // Redis 序列化配置 │ ├── WebSocketConfig.java // WebSocket 注册配置 │ └── SwaggerConfig.java // 接口文档配置 ├── controller │ ├── HealthCheckController.java // 健康打卡接口 │ ├── AccessRecordController.java // 出入登记接口 │ ├── NoticeController.java // 通知公告接口 │ └── UserController.java // 登录注册接口 ├── service │ ├── HealthCheckService.java │ └── impl │ └── HealthCheckServiceImpl.java ├── mapper │ ├── ResidentMapper.java │ └── HealthCheckMapper.java ├── entity │ ├── Resident.java │ └── HealthCheck.java ├── dto │ ├── LoginDTO.java │ └── HealthCheckDTO.java ├── common │ ├── Result.java // 统一返回结果 │ ├── BusinessException.java // 自定义异常 │ └── GlobalExceptionHandler.java // 全局异常处理 └── util └── JwtUtil.java // JWT 工具类启动类上就用SpringBootApplication然后加一行MapperScan(com.example.community.mapper)扫描 Mapper 接口这是 MyBatis-Plus 必经的一步漏了会报找不到 Bean 的错误。application.yml大概是这个风格注意路径匹配策略如果你用 springfox 3.0.0 就必须加最后那行server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/community?useUnicodetruecharacterEncodingutf8mb4serverTimezoneAsia/Shanghai username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver redis: host: localhost port: 6379 database: 0 mvc: pathmatch: matching-strategy: ant_path_matcher mybatis-plus: mapper-locations: classpath*:mapper/**/*.xml configuration: map-underscore-to-camel-case: true log-impl: org.apache.ibatis.logging.stdout.StdOutImpl这里单独说一下serverTimezoneAsia/Shanghai我遇到过不下十个同学问“为什么数据库连接报时间错误”十有八九是没加这个参数。MySQL 8.0 的驱动默认时区和本地不一致不加就会报The server time zone value is unrecognized。配置时区是最省事的解法。3.2 健康打卡接口与定时任务怎么写才不显得业余健康打卡接口是系统最核心的接口需求很简单居民提交今日体温和症状后端校验后落库。但要让这段代码不显得业余需要处理三个细节重复提交校验、参数校验、异常状态标记。我在HealthCheckServiceImpl里这样写的Service public class HealthCheckServiceImpl implements HealthCheckService { Autowired private HealthCheckMapper healthCheckMapper; Autowired private ResidentMapper residentMapper; Override public Result submit(HealthCheckDTO dto, Long residentId) { // 1. 校验今天是否已打卡 LocalDate today LocalDate.now(); Long count healthCheckMapper.selectCount( new LambdaQueryWrapperHealthCheck() .eq(HealthCheck::getResidentId, residentId) .eq(HealthCheck::getCheckDate, today) ); if (count 0) { throw new BusinessException(400, 今日已打卡请勿重复提交); } // 2. 体温异常自动标记 HealthCheck record new HealthCheck(); BeanUtils.copyProperties(dto, record); record.setResidentId(residentId); record.setCheckDate(today); if (dto.getTemperature() 37.3) { record.setIsAbnormal(1); } else { record.setIsAbnormal(0); } healthCheckMapper.insert(record); // 3. 同步更新居民健康状态 if (record.getIsAbnormal() 1) { Resident resident residentMapper.selectById(residentId); resident.setHealthStatus(HealthStatus.SUSPECTED.getCode()); residentMapper.updateById(resident); // 可以在这里调用消息推送服务通知社区工作者 } return Result.success(); } }注意我把“是否体温异常”的判断阈值 37.3 写成了一个常量而不是魔法值这一点在答辩时可以特意提一下很加分。定时任务这块我用Scheduled做一个每天 10 点自动统计并生成日报的功能。注意启动类或配置类上要加EnableScheduling注解否则定时任务不会生效。代码结构是Component public class DailyReportTask { Autowired private HealthCheckMapper healthCheckMapper; // cron 表达式每天 10:00 执行 Scheduled(cron 0 0 10 * * ?) public void generateDailyReport() { // 统计今日打卡人数、异常人数、未打卡居民列表 // 把结果插入报表表或推送通知 } }写到这里有个教训得分享Scheduled默认是单线程串行执行的如果你的系统里有多个定时任务一个任务卡住会影响其他任务执行。解决办法是在配置类里设置一个线程池比如spring.task.scheduling.pool.size5。毕设里遇到“定时任务偶尔不执行”基本就是这个原因。3.3 出入登记与 WebSocket 实时推送管理端页面不用刷新就能看到新记录出入登记本身是个标准 CRUD但我想让这道题目有点亮点所以加了 WebSocket 实时推送居民或访客在门岗完成登记后管理端页面不需要手动刷新就能实时看到最新进出记录。Spring Boot 集成 WebSocket 的流程比很多人想象中简单三步搞定第一步加依赖dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-websocket/artifactId /dependency第二步写一个 WebSocket 配置类注册一个SimpleUrlHandlerMapping或者用ServerEndpoint。我推荐用 Spring 封装的TextWebSocketHandler方式和 Spring 生态整合更顺Configuration public class WebSocketConfig implements WebSocketConfigurer { Autowired private AccessRecordWebSocketHandler handler; Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(handler, /ws/access) .setAllowedOrigins(*); } }第三步在业务代码里往 WebSocket 会话推消息。这里有个容易踩的坑WebSocket 的WebSocketSession不是线程安全的不能直接用ConcurrentHashMap存会话然后并发发送。我实际用的是CopyOnWriteArraySet存储会话集合发送时遍历并加同步锁Component public class AccessRecordWebSocketHandler extends TextWebSocketHandler { private static final CopyOnWriteArraySetWebSocketSession SESSIONS new CopyOnWriteArraySet(); Override public void afterConnectionEstablished(WebSocketSession session) { SESSIONS.add(session); } Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) { SESSIONS.remove(session); } public void pushNewAccessRecord(AccessRecord record) { String message JSON.toJSONString(Result.success(record)); for (WebSocketSession session : SESSIONS) { synchronized (session) { try { if (session.isOpen()) { session.sendMessage(new TextMessage(message)); } } catch (IOException e) { log.error(推送消息失败, e); } } } } }前端页面用原生WebSocket对象连接就行注意连接地址要写完整路径比如ws://localhost:8080/ws/access别漏了/ws前缀。这个功能做完后答辩时可以现场演示录入一条出入记录管理端页面立刻出现一条新数据效果很直观比干讲效果好得多。3.4 Redis Stream 做消息队列处理打卡异常通知与重试很多毕设项目根本没用到 Redis Stream但最近这个技术点挺热而且面试时也能聊。我在系统里用它做“异常打卡通知”的异步消息队列流程是生产者健康打卡接口发现体温异常把提醒消息写入 Redis Stream。消费者后台异步从 Stream 里拉取消息调用通知服务短信或站内信提醒社区工作者。失败重试消费失败后不直接丢弃而是把消息重新放回 Stream 或被 Pending Entries List 记录下次继续消费。生产端写入消息用StringRedisTemplate的opsForStream()方法public void sendAbnormalNotification(HealthCheck record) { MapString, String message new HashMap(); message.put(residentId, String.valueOf(record.getResidentId())); message.put(temperature, String.valueOf(record.getTemperature())); message.put(checkDate, record.getCheckDate().toString()); stringRedisTemplate.opsForStream() .add(stream:abnormal-check, message); }消费端我用一个Scheduled定时任务轮询 Redis Stream读取并确认消息Component public class AbnormalCheckConsumer { Scheduled(fixedDelay 3000) public void consume() { ListMapRecordString, Object, Object records stringRedisTemplate.opsForStream() .read(StreamOffset.create(stream:abnormal-check, ReadOffset.lastConsumed())); for (MapRecordString, Object, Object record : records) { try { // 发送通知逻辑 processNotification(record.getValue()); // 确认消息从 PEL 中移除 stringRedisTemplate.opsForStream().acknowledge(stream:abnormal-check, group-1, record.getId()); } catch (Exception e) { log.error(消费异常通知失败, e); // 不确认消息会留在 Pending 列表下一次可重查 } } } }这里说下为什么不用 RabbitMQ毕设环境可能就一台服务器再装一个 Erlang 和 RabbitMQ 光排环境问题就能浪费一天。Redis Stream 是 Redis 5.0 自带的功能你只要装了 Redis 就能用能实现消息队列 80% 的需求对毕设来说完全够。答辩时如果老师问“为什么不用专业消息队列”你可以说“考虑到项目规模和数据量Redis Stream 足够承载同时减少了系统组件依赖便于部署维护”。3.5 Swagger 接口文档springfox 3.0.0 与 Spring Boot 2.6 的兼容处理接口文档是毕设系统很出彩的部分写完接口直接生成在线文档答辩时打开 Swagger 页面展示接口列表比自己对着 Postman 演示规范很多。但这里有个大坑就是 Spring Boot 2.6 与 springfox 3.0.0 默认不兼容。如果你直接用最新版 Spring Boot 初始化项目然后加springfox-boot-starter3.0.0启动时会报一个空指针异常位置基本在documentationPluginsBootstrapper。原因前面说过路径匹配策略改了。解决方法有两个我推荐第二个方法一在application.yml里加一行配置让 springfox 走旧的路径匹配策略spring: mvc: pathmatch: matching-strategy: ant_path_matcher方法二放弃 springfox改用 springdoc-openapi依赖如下dependency groupIdorg.springdoc/groupId artifactIdspringdoc-openapi-ui/artifactId version1.6.14/version /dependencyspringdoc 对 Spring Boot 2.6 的兼容性更好默认访问路径是/swagger-ui/index.html接口 JSON 路径是/v3/api-docs。注解用法和 Swagger 2 差不多Tag对应原来的ApiOperation对应原来的ApiOperation。切换成本很低强烈建议直接用 springdoc省去配置WebMvcConfigurer的麻烦。4. 本地运行与服务器部署别在最后一步翻车4.1 命令行运行项目开发环境不止点绿箭头很多同学习惯了 IDEA 里直接点运行按钮对命令行启动一无所知。但毕业设计答辩现场很可能用老师的电脑或者一台没配好 IDE 的机器你最好掌握命令行启动的方式。最简单的开发环境启动方式# 在项目根目录下执行会先执行单元测试再启动 mvn spring-boot:run # 跳过测试推荐省时间 mvn spring-boot:run -DskipTests如果你的电脑没有配 Maven但项目里带了mvnw和mvnw.cmdSpring Initializr 生成的项目自带就执行./mvnw spring-boot:run -DskipTests这里我踩过一个坑在 Windows 的 CMD 里执行mvn spring-boot:run有时会卡在“Downloading...”半天没反应这是 Maven 中央仓库网络慢导致的。解决办法是给 Maven 配阿里云镜像。在 Maven 安装目录的conf/settings.xml里加mirror idaliyunmaven/id mirrorOfcentral/mirrorOf name阿里云公共仓库/name urlhttps://maven.aliyun.com/repository/public/url /mirror配好镜像后依赖下载速度会明显提升。4.2 打包部署到独立 Tomcatwar 包改造步骤有些学校要求毕设必须部署到外置 Tomcat不接受java -jar一行命令跑完。这时你需要把默认的 jar 打包方式改成 war。修改pom.xml里的 packaging 类型packagingwar/packaging修改启动类继承SpringBootServletInitializer并重写configure方法SpringBootApplication public class CommunityApplication extends SpringBootServletInitializer { Override protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { return builder.sources(CommunityApplication.class); } public static void main(String[] args) { SpringApplication.run(CommunityApplication.class, args); } }然后排除内嵌 Tomcat避免和外置容器冲突dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-tomcat/artifactId scopeprovided/scope /dependency执行打包mvn clean package -DskipTests打包完成后在target目录下得到xxx.war把它复制到外置 Tomcat 的webapps目录启动 Tomcat 后访问http://localhost:8080/xxx/即可。注意访问路径里多了一个项目名/xxx这是很多人部署后 404 的原因之一页面里如果有写死的接口地址/api/login要改成/xxx/api/login或者直接把 war 包改名为ROOT.war去掉项目名。4.3 常见问题速查表遇到这些错别慌毕设做到最后翻车最多的不是业务代码而是环境问题。我把高频问题整理成表格基本覆盖了 Spring Boot 项目最常见的坑报错现象可能原因解决方案Port 8080 was already in use端口被占用命令行执行netstat -ano找 PID任务管理器结束进程或改server.portCannot load JDBC driver class com.mysql.jdbc.DriverMySQL 驱动类名写错或依赖缺失MySQL 8.0 用com.mysql.cj.jdbc.Driver确认 pom 里有 mysql-connector-jThe server time zone value is unrecognized数据库连接没配时区URL 后加serverTimezoneAsia/ShanghaiInvalid bound statement (not found): xxxMapper.xxxMapper 接口和 XML 未绑定检查application.yml的mapper-locations确认 XML 的 namespace 和接口全限定名一致Whitelabel Error Page404路由或静态资源路径不对先确认 Controller 是否加了RequestMapping再用 Swagger 验证接口是否存在Failed to configure a DataSource启动时数据源配置缺失确认application.yml里数据库连接信息完整java.lang.IllegalStateException: Failed to load ApplicationContext启动时 Bean 冲突或 Bean 缺失看完整堆栈通常是 Mapper 没扫描到或 Service 实现类没加Service跨域请求失败前后端分离时没配置跨域写一个CorsConfig或用CrossOrigin注解跨域问题单独说一句如果前端用 Vue 开发端口是 8081后端是 8080浏览器会拦截跨域请求。我习惯写一个全局配置类省得每个 Controller 都加注解Configuration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/**) .allowedOriginPatterns(*) .allowedMethods(GET, POST, PUT, DELETE, OPTIONS) .allowedHeaders(*) .allowCredentials(true) .maxAge(3600); } }4.4 论文与答辩可以从哪些点做深别只讲 CRUD如果只是把 CRUD 写完就去答辩老师可能会觉得工作量平平。我建议你在现有系统基础上挑一到两个点做深既能让论文有得写又能硬气地回答老师的提问。我推荐这三个方向按投入产出比排序第一个是数据可视化。用 ECharts 做一个社区健康数据统计大屏展示近 14 天打卡趋势、各楼栋异常数量柱状图、出入流量折线图。这项技术的实现成本不高ECharts 就是前端引入一个 JS 文件后端提供一个统计接口但视觉效果好演示时非常惊艳。第二个是消息通知链路。把 Redis Stream 消费到的异常提醒通过 WebSocket 推送给管理端再加上站内信记录形成一条完整的“检测-入队-消费-推送”链路。整个链路打通后论文里可以画时序图答辩时可以讲异步解耦的设计思想。第三个是系统安全层面的细节。比如密码用 BCrypt 加密存储、接口参数用Valid注解校验、登录接口做验证码防暴力破解、文件上传做类型白名单校验。这些点不用全部做完挑两个写进论文老师问“系统安全性怎么保证”时你就有话说了。最后说几句实在话做毕业设计这事最怕的不是不会写代码而是手里一堆资料却不知道怎么落地。这套社区疫情防控管理系统本质上就是用 Spring Boot 把业务台账管起来再把常见的技术组件合理地嵌进去。我见过太多人纠结“要不要用最新版框架”结果版本冲突调了一周都没跑起来。选方案永远是稳定优先技术要为业务服务。我个人实际操作下来最大的体会是先跑通最小闭环再逐步加功能。第一天先搭好 Spring Boot 项目连上数据库写一个最简单的查询接口确认链路通了后面的东西都是在这个骨架上长肉。如果一上来就想着把 WebSocket、Redis Stream、权限控制全部集成完再启动项目大概率会陷入“集成了十天什么都没跑起来”的窘境。先让系统转起来再谈优化和亮点。