☰
SpringBoot居民健康与慢性病管理信息系统:毕设开发与实现详解
2026/10/15 6:02:20 网站建设 项目流程

做毕设选题的时候,很多人一看到“居民健康和慢性病管理信息系统”这种题目,第一反应是“又是一个管理系统,增删改查没意思”。但我的看法完全不同:这种题目恰恰是毕设里性价比最高、最容易做出亮点的一类。原因很简单——它的业务场景足够真实,社区卫生院、基层医院对健康档案管理和慢病随访有明确需求,你做出来的东西看得见、摸得着,答辩的时候也很好讲清楚。

这个项目基于 SpringBoot 构建,核心围绕居民健康档案、慢病登记、随访记录、用药提醒、健康预警与评估这几个模块展开。对 Java 方向的毕设来说,它不要求你搞什么高深算法,但能把 SpringBoot、MyBatis-Plus、MySQL、Vue 这些主流技术栈完整过一遍,属于典型的“覆盖面广、实现难度可控”的好题目。

不管你是打算直接改造现成的项目,还是想从零开始自己写,这篇文章都会把整个系统的需求拆解、表结构设计、核心模块实现、以及我实际开发时踩过的坑全部摊开讲。看完之后,你自己动手做一个能演示、能答辩、还能写进简历的项目,时间上完全来得及。

1. 项目到底做什么:核心需求与功能画像

1.1 从业务场景倒推功能清单

先别急着写代码,把业务场景想清楚,功能清单就自然出来了。慢性病管理的业务一句话描述:一个社区里有很多居民,其中一部分人患有高血压、糖尿病等慢性病,基层医生需要定期掌握他们的身体状况,记录体检数据、随访结果,在指标异常时发出预警。

从这句话可以倒推出系统必备的模块:

  • 居民档案管理:基础信息、既往病史、过敏史、家族病史、联系方式。
  • 健康体检记录:每次体检的各项指标数据,比如身高体重、血压、血糖、血脂。
  • 慢病专项管理:高血压、糖尿病等不同病种的登记与专项随访记录。
  • 随访计划与提醒:医生给患者制定随访计划,系统按计划生成待办和提醒。
  • 用药管理:开药记录、用药方案、服药提醒。
  • 健康评估与预警:根据血压、血糖等指标自动评估风险,超标触发预警。
  • 系统管理:用户管理、角色权限、操作日志、数据字典。

每个模块单独拎出来都不算难,但合在一起就是一个完整的业务闭环。答辩的时候,评委问你“这个系统解决了什么问题”,你可以很自然地回答:把原先社区医生用纸质台账管理慢病患者的方式,变成了信息化、结构化、可预警的线上流程。

1.2 用户角色与权限边界设计

这个系统至少有三类角色:系统管理员、医生(随访管理员)、居民用户。

权限设计的核心问题是“医生能看哪些人、居民能看什么内容”。我建议直接用 RBAC(基于角色的访问控制),不要给每个用户单独挂权限字段。具体到表结构,就是 user(用户表)、role(角色表)、user_role(用户角色关联表)、menu(菜单表)、role_menu(角色菜单关联表)这五件套。

这里有一个容易被忽视的业务细节:医生不应该看到全量居民数据,只能看到分配给自己的那部分。所以我在居民表里加了一个关联设计,通过 doctor 和 resident 的关系维护,比如在居民表里存 follow_doctor_id,或者单独建一张 doctor_resident 关联表。前者简单直接,适合毕设;后者扩展性好,适合以后加多人协同。

提示:权限这块不用做得太重。毕设阶段把“登录认证 + 菜单级权限 + 数据归属隔离”做到位,已经超过绝大多数同期作品了。

2. 技术选型:为什么是 SpringBoot 这套组合

2.1 框架选型的现实考量

毕设选型的第一原则:技术要主流、资料要好找、答辩要好讲。SpringBoot 在这三点上都是最优解。它内置 Tomcat,打成 jar 包就能跑,部署演示特别方便,而且社区资料极其丰富,遇到问题一搜就有答案。

持久层我的建议是直接用 MyBatis-Plus。很多人纠结要不要用原生 MyBatis,我的观点很明确:毕设周期就几个月,MyBatis-Plus 帮你把单表增删改查、分页、条件构造器这些重复劳动全部封装好了,省下来的时间应该花在业务逻辑和界面打磨上,而不是写一堆重复的 XML 映射。而且 MyBatis-Plus 在简历上是加分项,很多公司确实在用。

前端有两种选择:一种是 Vue + Element Plus 做前后端分离,另一种是用 Thymeleaf 模板引擎做服务端渲染。如果你已经会 Vue,毫不犹豫选前者,前后端分离的架构在答辩时可以多讲十分钟的接口设计和跨域处理;如果你前端基础薄弱,Thymeleaf 能让你快速出完整页面,风险更低。我自己倾向 Vue,因为演示效果更接近真实业务系统。

2.2 分层架构与包结构规划

无论选哪种前端,后端都建议遵循经典的分层架构:Controller 接收请求、Service 处理业务、Mapper 操作数据库。包结构可以这样规划:

com.example.chdms ├── controller # 接口层 │ ├── system # 登录、用户、菜单 │ ├── resident # 居民档案 │ ├── follow # 随访管理 │ └── report # 统计报表 ├── service # 业务逻辑层 │ └── impl # 接口实现 ├── mapper # MyBatis-Plus Mapper ├── entity # 数据库实体类 ├── dto # 前端交互对象 ├── vo # 视图返回对象 ├── config # 配置类(安全、跨域、拦截器) ├── common # 通用返回结果、异常处理、工具类 └── ChdmsApplication.java

这个结构里,最容易被忽略的是 dto 和 vo 的区分。很多同学直接把 entity 丢给前端,这张表有多少字段,接口就返回多少字段,改起来很痛苦。我更建议 entity 跟数据库一一对应,内部使用;返回给前端的数据用 vo 组装,只保留前端需要的字段。比如居民列表页只需要 id、姓名、性别、年龄、慢病标签,就不应该把过敏史、身份证号这些敏感字段全塞回去。

3. 数据库设计:慢性病管理系统的表结构拆解

3.1 核心表设计

数据库设计是整个项目的地基。地基歪了,后面写多少代码都别扭。我见过不少同学把大把精力花在用户注册登录上,到答辩前数据库里只有两张表,那内容撑不起来,也没法体现工作量。

慢性病管理系统的核心不是用户表,而是健康档案表、慢病登记表和随访记录表。我最终落地的核心表有这么几张:

表名作用关键字段
sys_user登录用户id, username, password, real_name, role_id, status
resident居民健康档案id, name, gender, birth_date, id_card, phone, address, allergy_history, family_history, follow_doctor_id
physical_exam体检记录id, resident_id, exam_date, height, weight, systolic, diastolic, fasting_blood_sugar, total_cholesterol, triglycerides
chronic_disease慢病登记id, resident_id, disease_type, diagnose_date, current_status, description
follow_up_record随访记录id, resident_id, disease_id, follow_date, systolic, diastolic, blood_sugar, medication_plan, advice, next_follow_date
medication_record用药记录id, resident_id, drug_name, dosage, frequency, start_date, end_date
health_alert健康预警id, resident_id, alert_type, alert_level, alert_content, status, create_time
sys_role角色id, role_name, role_code

以随访记录表为例,它的关键点在于把随访内容结构化了。随访不是写一段文字描述就完事,而是要提取出血压、血糖、用药方案这些结构化字段。有了结构化字段,后面做预警、做统计图、做趋势分析才有数据基础。

3.2 关键字段与设计误区

这里重点说几个我实际踩过的设计误区。

第一个误区:把年龄直接存在居民表里。年龄是随时间变化的,存一个固定值,第二年就不准了。正确做法是存出生日期 birth_date,查询时用 SQL 或者 Java 代码实时计算年龄。MySQL 里可以直接这样算:TIMESTAMPDIFF(YEAR, birth_date, CURDATE()) AS age。

第二个误区:慢性病类型用纯数字编码存。比如 1 代表高血压、2 代表糖尿病。这样存没问题,但做演示和开发的时候,每次都要去查字典,非常不方便。我的做法是用字典表统一管理疾病类型,页面上通过数据字典接口动态加载,既规范又灵活。

第三个误区:所有表都用自增主键而不用逻辑删除。健康档案这类业务数据,删除应该用逻辑删除标记,也就是加一个 deleted 字段(0 未删除,1 已删除),而不是物理 DELETE。MyBatis-Plus 里只要配置了 @TableLogic,就会自动帮你处理逻辑删除,非常方便。这个细节在答辩时被问到“数据安全怎么做”的时候,是一个很加分的点。

4. 核心功能模块实现:从登录到健康预警

4.1 认证授权模块

登录认证我用的方案是 JWT(Json Web Token),一个比较标准的无状态登录方案。为什么不用传统的 Session?“Session 是存在服务器内存里的,用户一多、服务一重启,登录状态就丢了。JWT 是把用户信息加密签名后放在客户端,服务器不存状态,天然适合前后端分离的架构,也方便以后横向扩展。”

核心逻辑大概是这样:登录接口校验用户名密码,成功后用 JWT 生成 token 返回前端;前端把 token 存在本地,每次请求放到请求头里;后端写一个拦截器统一校验 token,解析出当前用户信息,放行或拒绝。

// JWT 工具类核心方法(简化版) public String generateToken(Long userId, String username) { return Jwts.builder() .setSubject(username) .claim("userId", userId) .setExpiration(new Date(System.currentTimeMillis() + 3600_000L)) .signWith(secretKey, SignatureAlgorithm.HS256) .compact(); }

拦截器里要注意的是:白名单放行,登录接口、验证码接口、居民端查询公开信息这些不需要 token 的路径要明确排除掉,否则会出现反复被拦截器挡在门外的问题。

4.2 居民健康档案管理

居民档案管理是系统里最典型的 CRUD 模块,但“典型”不代表可以随便写。档案列表的分页查询、关键字搜索、按慢病类型筛选,这些高频操作要做顺手。

用 MyBatis-Plus 的分页插件实现列表查询,核心代码非常简洁:

// 分页查询居民列表 public Page<ResidentVO> pageResident(int pageNum, int pageSize, String keyword, Long diseaseType) { LambdaQueryWrapper<Resident> wrapper = new LambdaQueryWrapper<>(); wrapper.like(StringUtils.hasText(keyword), Resident::getName, keyword) .eq(diseaseType != null, Resident::getDiseaseType, diseaseType) .orderByDesc(Resident::getCreateTime); Page<Resident> page = residentMapper.selectPage(new Page<>(pageNum, pageSize), wrapper); // 转 VO 并填充年龄、慢病标签等字段 return convertToVO(page); }

这一段实现了三个很常用的功能点:模糊查询(keyword 按姓名搜索)、条件筛选(按慢病类型)、排序。Controller 层接收分页参数时要做参数校验,页码不能小于 1,页大小控制在合理范围,避免有人恶意传一个超大 pageSize 把接口拖垮。

档案新增和编辑时,身份证号要做唯一性校验。同一身份证不能重复建档,这是业务硬规则。实现时可以在 resident 表的 id_card 字段建唯一索引,同时在 service 里做一次预检,双保险。

4.3 慢病随访与监测模块

随访模块是这个系统的业务灵魂。它的流程是:医生给某位高血压患者建档登记,制定随访计划(比如每月随访一次),系统在计划到期时生成待办提醒,医生按计划进行随访并录入随访指标,最后根据指标结果调整用药方案或建议转诊。

随访记录的保存要注意一个设计点:同一次随访可能同时涉及高血压病种的血压数据和糖尿病病种的血糖数据,所以随访明细可以单独拎出一张表,用 follow_up_type 区分指标类型,这样后续加新病种(比如慢阻肺)的时候不需要改表结构,扩展性好。

-- 随访记录主表 CREATE TABLE follow_up_record ( id BIGINT PRIMARY KEY AUTO_INCREMENT, resident_id BIGINT NOT NULL COMMENT '居民ID', disease_id BIGINT COMMENT '慢病登记ID', follow_date DATE NOT NULL COMMENT '随访日期', follow_type VARCHAR(32) COMMENT '随访方式:门诊/电话/上门', doctor_id BIGINT COMMENT '随访医生ID', medication_plan VARCHAR(255) COMMENT '当前用药方案', advice VARCHAR(255) COMMENT '随访建议', next_follow_date DATE COMMENT '下次随访日期', remark VARCHAR(255), deleted TINYINT DEFAULT 0, create_time DATETIME DEFAULT CURRENT_TIMESTAMP );

随访计划提醒我用的是最简单的方案:写一个定时任务,每天早上扫描一遍所有慢病登记的 next_follow_date,把三天内到期的随访任务写入待办表,医生登录首页就能看到今日待办和即将到期的随访列表。这个方案不引入消息中间件,对毕设来说完全够用,又能体现你对业务的理解。

4.4 健康预警与统计报表

预警模块是系统的一个亮点功能,也是答辩时可以重点演示的部分。规则也很直白:如果某位居民的收缩压高于 140 或者舒张压高于 90,就自动生成一条高血压预警;空腹血糖高于 7.0 mmol/L 则生成血糖预警。

实现上有两种做法。一种是在保存体检记录和随访记录时同步触发规则检查,适合实时性要求高的场景。另一种是定时任务批量扫描,适合数据量大的离线场景。我采用的是前者,在 Service 层的 save 方法后面调用一个独立的 ruleCheck 方法,把规则判断逻辑抽出来单独维护。后面想加新规则(比如 BMI 超过 28 预警),只需要在规则方法里加一段判断,不影响主流程。

统计报表用 ECharts 展示。首页放一个区域折线图展示最近 12 个月的随访趋势,一个饼图展示系统内慢病类型的分布比例,再放一个滚动条播放最近一周新增的预警记录。这些图表数据全部由后端统计接口提供,聚合查询用 MyBatis-Plus 的 groupBy 就能实现,不需要写复杂的 SQL。

5. 实操中踩过的坑与排查实录

5.1 常见问题速查表

把我在开发过程中遇到的高频问题整理成一张表,方便你直接对照排查:

问题现象根本原因解决方案
前端请求接口报 401拦截器没有把登录接口加入白名单在拦截器配置中显式排除 login、captcha 路径
日期数据返回变成时间戳或格式错误后端没有统一配置 JSON 日期格式在 application.yml 配置 spring.jackson.date-format,或使用 @JsonFormat
分页查询 total 一直是 0分页插件依赖没引入或版本不匹配确认引入 mybatis-plus-boot-starter 且配置了分页插件
部署到 Linux 后文件上传失败上传目录不存在或权限不足,临时目录 /tmp 被清理配置独立的静态资源目录,启动时自动创建目录
中文乱码数据库连接 URL 缺少 characterEncoding 参数在 JDBC URL 末尾加上 useUnicode=true&characterEncoding=utf8

5.2 几个典型的 Bug 现场还原

第一个 Bug 是 JWT 过期时间问题。当时我设置了 2 小时过期,结果演示过程中前端页面打开时间稍长,操作一下又跳回登录页,非常尴尬。后来我把过期时间设置为一整天,同时前端在收到 401 响应后跳到登录页。这里提醒一下:毕设演示环境,过期时间别设太短,除非你有心做一个完整的刷新 token 机制,否则演示当场掉线确实很影响观感。

第二个 Bug 是跨域问题。前后端分离项目里,Vue 跑在 8080 端口,后端跑在 8081 端口,前端直接发 AJAX 请求会被浏览器拦掉。我在后端配置了一个全局跨域过滤器,放行所有来源和方法,允许前端携带 token 请求头。注意一个细节:放行方法和请求头要写全,否则会被 OPTIONS 预检请求挡掉。

第三个 Bug 是逻辑删除字段造成的查询失效。配置了 @TableLogic 之后,MyBatis-Plus 会自动在查询语句里加上 deleted=0 条件,但你写了自定义 SQL 的时候要注意,JOIN 查询里关联表的逻辑删除条件不会自动添加,需要手动在 SQL 里补上。这个问题不细看真的很难发现。

第四个 Bug 比较隐蔽,是定时任务的重复执行。我在本地测试的时候,到点发现生成了重复的待办记录。查了半天发现是开发环境开了多个服务实例,同一份定时任务在每个实例上各跑了一次。解决方式是给任务加分布式锁,或者干脆在数据库里对记录加唯一索引,但重复执行也要保证最终结果幂等。对毕设来说,用数据库唯一索引兜底最省事,重启前保证只有单实例运行就行。

6. 答辩演示与简历包装建议

6.1 演示顺序怎么安排最加分

答辩演示的顺序其实是有讲究的。我建议不要上来就一个个点菜单,而是讲一个完整的业务故事。

第一步,用管理员账号登录,快速介绍一下系统概况,包括首页的数据看板(居民总数、慢病患者数、今日随访待办、预警数量)。第二步,新增一位居民档案,演示建档顺便讲解身份证唯一性校验。第三步,给这位居民登记高血压慢病,录入一条体检记录,走到健康档案详情页展示趋势图,这时故意录入一个偏高的血压值,让系统弹出预警,把预警模块的亮点顺势带出来。第四步,演示随访录入和下次随访计划生成,最后切到居民端账号,演示居民查看自己的档案和预警信息。

这四步走完,整个系统的业务闭环就完整了。评委看到的是一个“能跑通真实业务流程”的系统,而不是一堆孤立功能的拼凑。

6.2 毕设代码的质量底线

最后聊一下代码质量。不需要你写出工业级代码,但有几条底线要守住:不要在 Controller 里写业务逻辑,所有判断放到 Service;统一使用自定义返回对象 Result,不要到处 return Map;异常要统一处理,用 @RestControllerAdvice 全局异常拦截,而不是让堆栈信息直接裸露给前端;关键业务操作记录日志,比如登录、建档、删除档案这些敏感操作。

这几条做到位,代码质量在毕设这个层面已经算优秀的了。面试官翻你 GitHub 项目的时候,第一眼看的就是包结构是否清晰、有没有全局异常处理、接口返回是否规范,这些比多写一个花哨功能更能体现工程素养。

最后再说一点个人体会。我做完这个项目最大的收获,不是学会了 SpringBoot 的某个特性,而是明白了一个道理:做一个管理系统,最难的永远不是 CRUD 代码,而是把业务的真实逻辑理解透,再用代码把它准确表达出来。慢病随访的流程、预警规则的定义、权限边界的划分,这些才是这个项目的灵魂。你把这个灵魂讲透了,毕设答辩基本上就稳了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询