最近帮一个学弟远程看了套基于 SpringBoot + Vue + MySQL 的大健康养老公寓管理系统,他是拿来当毕业设计用的,前后折腾了两周,踩了不少坑,最后顺利通过答辩。这系统确实很适合做毕设选题——业务场景清晰、技术栈主流、工作量适中,既不会简单到没东西写,也不会复杂到做不完。今天我把这套系统的完整拆解整理出来,从数据库设计到后端接口、从页面联调到打包部署,连论文写作的思路一起讲清楚,给正在做同类选题的同学一份可以直接参考的实操笔记。
1. 项目定位与整体技术架构
先说说这套系统到底是干什么的。大健康养老公寓管理系统,核心是解决养老公寓日常运营中“老人信息管理、健康数据追踪、护理任务安排”这三件最头疼的事。很多养老公寓还在用Excel记老人档案,用微信群排护理班次,健康数据散落在纸质体检单上,想调个历史血压记录都费劲。这套系统就是把整个流程线上化——老人入住建档、房间床位分配、每日健康数据录入、异常波动预警、护理任务分配都统一到一套平台里管理。
技术选型上用了 SpringBoot + Vue + MySQL 这套组合,可以说是Java全栈开发最经典的搭配了。为什么选这套而不是其他方案?我拆解一下:
后端用 SpringBoot,核心优势是“约定大于配置”,不用像传统SSH那样写一堆XML配置文件,一个application.yml就能搞定数据源、端口、日志等核心配置。内置的Tomcat容器也让部署变得简单,打一个jar包扔服务器上就能跑。对于毕设场景来说,SpringBoot的生态资料极其丰富,遇到问题一搜就能找到解决方案,不像一些冷门框架卡住半天没人理。
前端选 Vue 而不是 JSP 或者 Thymeleaf,是因为这套系统的交互集中在“数据录入和展示”上——健康指标要频繁新增、趋势图表要动态刷新、护理任务要实时更新状态。这类场景天然适合前后端分离的架构:Vue负责页面渲染和用户交互,后端只提供JSON数据接口。再加一个 Element UI 组件库,表格、表单、弹窗、日期选择器这些常用组件都封装好了,开发效率比手写HTML快好几倍。我见过很多同学用JSP做这种系统,页面越写越乱,而Vue的单文件组件模式天然把页面拆成小块,后期维护和答辩讲解都轻松很多。
数据库用 MySQL,这个没什么争议。开源免费、稳定可靠、教程多,而且 MySQL 8.0 之后的窗口函数、JSON类型等功能足够应对这种体量的管理系统。通过 Navicat 或者 MySQL Workbench 直观管理表结构和数据,对不熟悉命令行操作的同学非常友好。
这套系统的目标用户和角色权限,我建议这样设计:
| 角色 | 核心权限 | 典型操作场景 |
|---|---|---|
| 系统管理员 | 全部模块 | 维护老人档案、分配房间床位、创建护理任务、管理所有数据 |
| 护理人员 | 健康数据、护理任务 | 录入每日体征数据、查看我的任务列表、标记任务完成 |
| 老人家属 | 健康数据(只读)、基础信息 | 查看老人健康趋势图、浏览公寓通知公告 |
这样的三角色设计既覆盖了业务核心场景,又在权限控制上给了论文足够大的发挥空间。
2. 数据库设计——这是整个系统的地基
数据库设计的好坏直接决定后续开发是顺滑还是痛苦。我见过太多毕设项目,业务逻辑和页面都写完了,突然发现表结构缺字段、表关系串不起来,回过头来改表结构,结果前后端代码几乎重写了一遍。所以第一步一定要把表设计扎实。
2.1 核心表结构与字段设计
这套系统的核心表我梳理下来有这9张:
- sys_user(用户表)——存储登录账号,关联角色
- elderly_info(老人信息表)——核心档案,包含姓名、性别、出生日期、身份证号、家属联系方式等
- room_info(房间表)——楼栋、楼层、房间号、床位数、入住状态
- bed_info(床位表)——关联房间,标记当前入住老人
- health_record(健康记录表)——每天录入血压、心率、血糖、血氧、体温等指标
- nursing_task(护理任务表)——任务内容、指派人、执行人、优先级、状态、截止时间
- medication_reminder(用药提醒表)——用药名称、剂量、频率、开始日期、结束日期
- notice_info(公告表)——公寓通知公告的发布与查看
- dict_data(数据字典表)——统一管理性别、优先级、任务状态等枚举值
拿最有代表性的 elder_info 和 health_record 来细说。老人信息表的字段设计要注意几个点:身份证号是唯一标识,建议加唯一索引;家属联系人和紧急联系电话是必填信息;入住日期和床位ID要预留外键关联。health_record 表尤为关键,设计字段时要考虑后续的查询场景——按老人、按日期范围、按指标类型筛选趋势数据,因此老人ID和记录日期要建联合索引,常见的查询SQL比如:查某位老人最近7天的血压记录,SELECT * FROM health_record WHERE elderly_id = ? AND record_date BETWEEN ? AND ? ORDER BY record_date DESC,有联合索引的话即使数据量到几十万条也能秒级返回。
2.2 关键表关系与字段类型选取
表之间的关系我建议用最直观的方式:
- 一张床位同时只关联一位老人,床位表里加 elderly_id 字段,入住时写入,退住时清空
- 健康记录和护理任务都通过 elderly_id 关联老人,形成一对多关系
- 用户表和老人信息表之间,护理人员登录后要能通过 user_id 找到自己负责的老人列表,所以老人表里加一个 careworker_id 字段做责任人标记
字段类型选取上有个特别容易踩坑的地方——金额、健康指标这类带小数的数据,一定要用 DECIMAL 而不是 FLOAT。比如血糖值,用 DECIMAL(4,1) 存6.5,显示和计算都不会丢精度。日期时间字段优先用 DATETIME,如果只关心日期就用 DATE,别两张表一种用 TIMESTAMP 一种用 DATETIME,后面写SQL比较时很容易出问题。文本类型方面,通知公告内容可能会比较长,用 TEXT 或者 VARCHAR(2000) 都比 VARCHAR(255) 稳妥。
下面给出 health_record 表的建表SQL参考,字段设计可以说直接决定后面前端页面的数据展示:
CREATE TABLE `health_record` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', `elderly_id` bigint NOT NULL COMMENT '老人ID,关联elderly_info表', `record_date` date NOT NULL COMMENT '记录日期', `blood_pressure_high` int DEFAULT NULL COMMENT '收缩压(mmHg)', `blood_pressure_low` int DEFAULT NULL COMMENT '舒张压(mmHg)', `heart_rate` int DEFAULT NULL COMMENT '心率(次/分)', `blood_sugar` decimal(4,1) DEFAULT NULL COMMENT '血糖(mmol/L)', `blood_oxygen` int DEFAULT NULL COMMENT '血氧饱和度(%)', `temperature` decimal(3,1) DEFAULT NULL COMMENT '体温(℃)', `record_note` varchar(500) DEFAULT NULL COMMENT '备注信息', `create_by` bigint DEFAULT NULL COMMENT '记录人ID', `create_time` datetime DEFAULT NULL COMMENT '创建时间', PRIMARY KEY (`id`), KEY `idx_elderly_date` (`elderly_id`, `record_date`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='健康记录表';2.3 数据初始化与测试数据的重要性
表建好不等于数据库设计完成,还有一步很多同学会忽略——准备一套完整的初始化数据和测试数据。你在写后端的时候,每个接口联调都需要真实数据,总不能先在前端表单一条条录入,再去验证列表和图表接口。我的习惯是建完表立刻写一套SQL脚本,插入3-5位老人、10-20条健康记录、若干条护理任务,覆盖各种状态和边界情况。
比如健康记录要多造几天的数据用于展示趋势图,包含一天内多次记录的、隔几天记录的,最好造几天“异常数据”(比如血压哪天突然飙到180),这样测试预警和突出显示效果时顺手验证。初始化数据最好用SQL语句写在一个 .sql 文件里,方便随时重建测试环境,不要手动在Navicat里一个个点着录入,效率低还容易漏。
数据字典表虽然看起来不起眼,但对整个项目提升很明显。把性别、任务优先级、任务状态、公告类型这些枚举值抽成字典表,前端下拉框选项从接口动态查,后端代码里也不用写死1代表男、2代表女这种魔法数字。答辩时老师问“你这个系统的扩展性怎么保证”,这就是一个很好的回答点。
3. 后端核心模块实现——SpringBoot落地细节
数据库设计好之后,后端开发就有了清晰的蓝图。我按照“搭框架 → 做认证 → 写业务”的顺序来讲,这也是毕设开发效率最高的路径。
3.1 SpringBoot项目搭建与核心配置
创建一个全新的 SpringBoot 项目,我推荐用 Spring Initializr(start.spring.io)生成基础脚手架,选 Java 8 或 11、SpringBoot 2.7.x 版本。这里要特别提醒:不要一上来就选 SpringBoot 3.x。3.x 对 JDK 版本要求高(至少要17),而且很多第三方集成组件还没有完全适配,对于毕设项目来说完全没有必要冒这个险。2.7.x 已经足够稳定,网上资料也是最多的,遇到问题几乎都能搜到答案。
依赖方面,核心就这五个:Spring Web 用于接口开发、Spring Data JPA 或 MyBatis-Plus 用于数据访问、MySQL Driver 连接数据库、Lombok 简化实体类代码、Spring Security 和安全相关的处理。我用 MyBatis-Plus 更多一些,它的 BaseMapper 内置了增删改查和分页方法,开发效率极高,而且代码生成器可以一键生成实体类、Mapper、Service、Controller,省掉大量重复的CRUD代码。
application.yml 是后端的核心配置文件,我给出一个常用配置:
server: port: 8080 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/elderly_care?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true username: root password: 你自己的密码 jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT+8 mybatis-plus: configuration: map-underscore-to-camel-case: true global-config: db-config: logic-delete-field: deleted logic-delete-value: 1 logic-not-delete-value: 0日期格式化这块一定要配上,否则前端拿到的日期时间格式是乱七八糟的时间戳,联调时闪瞎眼。逻辑删除配置也建议开启,老人误建档或者任务删错了,直接物理删除数据对日后统计影响很大,逻辑删除只是标记deleted=1,查询时MyBatis-Plus自动过滤,安全又省心。
3.2 认证授权——JWT + 拦截器方案
宿舍管理系统这种类型的项目,接口不能裸奔——谁都能调用;但也不能用太复杂的认证方案。我强烈推荐 JWT(JSON Web Token)方案,实现简单、无状态、前后端分离兼容性极好。
JWT的逻辑是这样的:用户登录成功后,后端把用户ID和角色等信息加密生成一个token字符串返回给前端。前端存在本地,每次请求在请求头里带上这个token。后端写一个拦截器,拦截所有需要认证的接口,验证token签名是否正确、是否过期。这个方案比Session更合适前后端分离架构,Session天然依赖Cookie,跨域时Cookie处理很麻烦,而token是前端主动携带的,跨域配置就简单多了。
核心配置三步走:
- 加依赖:jjwt 或 java-jwt 框架,二选一
- 写一个 JwtUtil 工具类:generateToken 生成token、parseToken 解析token、isTokenExpired 判断是否过期
- 写一个 JwtInterceptor 拦截器:实现 HandlerInterceptor 接口,在 preHandle 方法里从请求头取token、校验、通过后放行,并把当前用户信息存入ThreadLocal
拦截器注册也有一点需要注意——登录接口、验证码接口这些必须放行,Swagger接口文档页面也要放行,否则在线调试文档都打不开。放行路径可以用如 /api/auth/, /doc.html, /webjars/这种通配符搞定。注册拦截器需要实现 WebMvcConfigurer 接口,重写 addInterceptors 方法。
另外后端还需要写好两件事:统一的返回结果类和全局异常处理。自定义一个 Result 类,包含 code、message、data 三个字段,所有接口都返回这个统一格式。用 @RestControllerAdvice + @ExceptionHandler 做全局异常拦截,业务异常直接 throw new BusinessException("错误信息"),框架自动包装返回。这样前端axios拦截器里只要判断 code 不等于200,统一弹出错误提示,不用每个接口单独写异常判断,联调效率翻倍。
3.3 健康数据模块——业务逻辑与查询优化
健康数据管理是这套系统的核心业务模块,包含录入、查询、趋势分析和异常预警四块。录入口是护理人员每天操作的,数据结构与前端表单一一对应,Controller层接收 JSON 请求体,Service层做必填校验和合理性校验,然后保存到数据库。
这里我多说一句“合理性校验”,比如月经记录血压240/180这种离谱数据应该直接报错,避免脏数据进入后续统计。后端不校验只靠前端控制,接口被直接调用后脏数据就进来了。合理的校验逻辑比如:
// 血压合理性判断:收缩压范围 60-220,舒张压范围 40-120 if (record.getBloodPressureHigh() != null && (record.getBloodPressureHigh() < 60 || record.getBloodPressureHigh() > 220)) { throw new BusinessException("收缩压数据异常,请确认后再提交"); } if (record.getBloodPressureLow() != null && (record.getBloodPressureLow() < 40 || record.getBloodPressureLow() > 120)) { throw new BusinessException("舒张压数据异常,请确认后再提交"); }查询和趋势分析也是高频接口。趋势分析用时间范围查询最近N天的记录,在前端用ECharts绘制折线图。说实话这块前端工作量比后端大,后端只需要把数据按日期排好返回,前端关注怎么展示。有一个后端可以做的优化——分页查询的健康记录列表,参数带上 elderly_id 和 record_date 范围,MyBatis-Plus 零SQL就能搞定。
另外异常预警这里的逻辑建议做成独立的服务方法。比如判断最近一条血压记录是否超出正常范围,如果超出就在返回标记加一个字段。不用做得太重,能用即可,核心是把“业务逻辑写在Service层”这个思路贯彻好,别把逻辑堆在Controller里——那不是毕业设计该有的代码风格。
4. 前端Vue实现——从页面体验到前后端联调
前端是答辩时评委老师第一眼看到的东西,页面好不好看、交互顺不顺畅,直接影响第一印象。Vue 配合 Element UI 很快就能搭出一套界面专业的管理后台。
4.1 项目初始化与必要配置
前端工程我建议直接用 Vue CLI 创建(vue create elderly-care-web),选择 Vue 2 + Router + Vuex(Pinia) 的组合,UI库用 Element UI。Vue 2 配合 Element UI 的生态非常成熟,几乎所有组件都开箱即用。前端版本的选择和后端一样——求稳不追新。Vue 3 + Element Plus 虽然也是主流,但遇上兼容性问题排查成本更高,毕设用 Vue 2 一年一年的资料多,不踩坑。
项目结构我会按照模块化思路划分:
src/ ├── api/ // 按业务模块封装的请求接口 │ ├── auth.js │ ├── elderly.js │ ├── health.js │ └── task.js ├── assets/ // 静态资源 ├── components/ // 公共组件 ├── router/ // 路由配置文件 ├── store/ // 全局状态管理 ├── utils/ // 工具函数 │ ├── request.js // axios实例封装 │ └── auth.js // token存取 ├── views/ // 页面组件 │ ├── login/ │ ├── dashboard/ │ ├── elderly/ │ ├── health/ │ └── task/ └── App.vueaxios 封装这一步值得仔细做,因为它影响每个接口的调用方式。我通常在 utils/request.js 里做三件事:设置 baseURL、请求拦截器自动附加token、响应拦截器统一处理code和error。响应拦截器里判断 code 为401时,自动跳转登录页并清理本地失效token。这样前端所有接口调用代码都非常简洁,比如获取老人列表就一行:
getElderlyList(params) { return request({ url: '/api/elderly/list', method: 'get', params }) }4.2 核心页面设计——以健康档案和趋势图表为例
页面开发我建议先做登录页和整体框架,再做核心业务页。登录页逻辑不难,表单校验 + 提交用户名密码 + 存储token + 路由跳转,但要注意登录后要把用户信息和角色存到store里,后面菜单权限判断要用。
整体框架用 Element UI 的 Container 布局,左侧 Sidebar 是菜单列表,右侧是主内容区。菜单根据角色动态生成——管理员的菜单全量展示,护理人员只显示健康管理和任务管理,家属只显示健康查看和公告。这个动态菜单的实现在答辩时是个加分项,体现你考虑了多角色系统的可用性。
健康管理页面是重头戏,我用一个 Tab 拆成两个区域:健康记录列表和健康趋势图。记录列表用 el-table 展示,顶部放搜索条件(老人姓名、日期范围),下面用 el-pagination 做分页。录入用一个 Dialog 弹窗,里面表单按照前面的 health_record 字段渲染,提交到后端。
趋势图表用 ECharts 的折线图。本系统图表可以从 npm 安装 echarts,在组件里按需引入。一个关键经验:后端接口返回的数据结构,在前端要适度二次处理,formatData 一下再传给图表。比如ECharts的 xAxis 需要的是日期数组,series 需要的是数值数组,从接口返回的 [{recordDate:"2024-10-01", bloodPressureHigh:130}, ...] 这种数组,用 map 方法拆成两个数组再赋给图表配置项,就不会出现“数据明明拿到了但图表不显示”这种玄学问题。
4.3 路由守卫与跨域联调
路由守卫是前端必须做的一环,不然登录页可以随便跳转任何地址。Vue Router 的 beforeEach 钩子,在跳转前先看本地有没有 token,没有就跳登录页,有但在白名单页面(login)会自动跳首页。还需要注意,路由配置里加上 meta: { roles: ['ADMIN'] } 这种角色标注进一步做角色级控制,配合后端权限形成双重防线。
前后端联调时遇到最多的问题就是跨域。开发环境下我给前端配一个代理,在 vue.config.js 里:
module.exports = { devServer: { port: 3000, proxy: { '/api': { target: 'http://localhost:8080', changeOrigin: true } } } }这样前端请求 /api/xxx 会自动转发到后端的 8080 端口,不触发浏览器的跨域拦截。生产环境更简单,后端服务器上配置 Nginx 将前端静态文件和 /api 反向代理放一起,因为同源了自然不存在跨域。这个方法比在后端加 @CrossOrigin 注解要推荐得多——@CrossOrigin 是允许所有来源访问,生产环境虽然够用,但不够严谨,更专业的做法就是在网关层解决跨域。
5. 安全方案、分页配置与接口文档
安全是毕业设计答辩时候老师一定会问的方向,分页和接口文档则是实际开发体验的两个细节,放在一起说。
5.1 角色权限控制的落地方式
密码安全这里,一定要用 BCrypt 加密,不要用MD5。Spring Security 的 BCryptPasswordEncoder 内置了 BCrypt 算法,每次加密结果都会加随机盐,即使两个同样密码加密出来的密文也不同,有效抵御撞库攻击。注册用户时用 encoder.encode(password) 存储,登录验证用 encoder.matches(rawPassword, encodedPassword) 判断,非常简洁。
接口权限控制,除了前面说的 JWT 拦截器,再加上 Spring Security 的注解式权限控制。在方法上标注:
@PreAuthorize("hasRole('ADMIN')") @GetMapping("/api/elderly/delete/{id}")角色权限不足时 Spring Security 自动返回403,这样即使前端菜单被篡改,后端接口也进不去,逻辑闭环了。这个方案比手动写拦截器去判断角色要专业得多,答辩讲起来也是一套完整的“认证授权”体系。
5.2 MyBatis-Plus分页插件配置
分页是每个列表页的标配,MyBatis-Plus 的分页插件配置如下:
@Configuration public class MybatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); PaginationInnerInterceptor pagination = new PaginationInnerInterceptor(DbType.MYSQL); pagination.setMaxLimit(500L); interceptor.addInnerInterceptor(pagination); return interceptor; } }注意只有 new 了分页插件,Page 对象传参查询才生效,忘掉的后果就是查询直接把全表数据返回,让前端自己页面上切,“假分页”就是这么来的。用的时候 Service 层写法:
Page<ElderlyInfo> page = new Page<>(pageNum, pageSize); Page<ElderlyInfo> result = elderlyInfoMapper.selectPage(page, queryWrapper); return new PageResult<>(result.getRecords(), result.getTotal());返回给前端 total(总条数)和 records(当前页数据),前端分页组件页码刷新时传参即可。
5.3 Knife4j接口文档的接入
接口文档我建议用 Knife4j,它是 Swagger 的增强版,界面更美观,和 SpringBoot 集成也简单。加依赖,然后写一个简单的配置类,再用注解标注接口即可。
对于答辩时,直接在浏览器打开 /doc.html 页面,把每个接口的请求参数、返回结构展示给老师看,远比逐个打开前端页面展示接口要专业。老师问“你这里接口怎么设计的”,你直接切换到文档页面说一遍接口的请求响应格式,这个完成度直接拉满。
6. 论文结构规划与部署上线要点
系统代码开发完之后,还有两件大事:写论文、部署上线。很多同学代码写完了才发现论文无从下手,其实就是没有把开发过程和论文结构对应起来。
6.1 论文大纲与写作思路
毕业论文大致按这个结构写,完全能覆盖系统的所有亮点:
- 第一章 绪论:写大健康养老行业的背景、社会老龄化趋势、国内外研究现状。研究背景要写出“为什么养老公寓需要信息化管理系统”,落脚到现有方式的痛点上
- 第二章 关键技术介绍:SpringBoot、Vue、MySQL 分别介绍。注意不要大段抄官方文档,要结合本项目说明“为什么选它、它在系统里发挥什么作用”
- 第三章 系统需求分析:用例图、功能需求分析、非功能需求分析,从“养老公寓管理员/护理人员/家属”三个角色的实际操作场景提取需求
- 第四章 系统设计:系统总体架构图、功能模块设计、数据库概念设计(ER图)、物理表结构设计。这一章可以和代码同步完成,边写代码边整理
- 第五章 系统实现:每个核心模块放2-3个关键页面截图+关键代码片段,配少量文字说明。代码不要全篇贴,挑核心业务逻辑贴
- 第六章 系统测试:功能测试用例表、测试结果分析,再写一个性能测试或安全测试的简单分析
写论文最重要的一条建议:不要等代码全部写完了才动笔。系统的需求分析、概要设计、数据库设计这些章节,在开发前就应该有初稿,开发和写论文同步进行,这样代码实现过程中对需求的理解变化能及时反映到论文里,文档完成度也更高。
6.2 本地环境搭建与常见坑
本地跑通这个系统需要装的东西不少,我列一个检查清单:
- JDK 8 或 11
- Maven 3.6+
- Node.js 14+(Vue 2 项目用到 Node 16 也正常)
- MySQL 8.0
- Navicat 或 MySQL Workbench(用来导入SQL脚本)
- IDEA(后端开发)+ VS Code(前端开发)
安装时最容易出问题的几个点:
- MySQL 8.0 安装完默认密码认证方式和旧版不同,连接时要在 URL 里加 allowPublicKeyRetrieval=true & useSSL=false 参数,否则报连接错误
- Node 版本太高导致 node-sass 安装失败——建议用 Node 16,或直接改用 dart-sass 替代 node-sass
- Maven 依赖下载慢——配置阿里云镜像,在 settings.xml 的 mirror 节点加一条
6.3 服务器部署实战
部署到Linux服务器,整体思路是后端打 jar、前端打包成静态文件交给 Nginx。后端打包:
mvn clean package -DskipTests会在 target 目录生成 xxx.jar。把 jar 上传到服务器,运行:
nohup java -jar elderly-care-system.jar --spring.profiles.active=prod > app.log 2>&1 &第一次部署你会发现很多问题:数据库字符集没设置导致中文乱码、服务端口没开导致外网访问不了、内存配置不对导致启动失败。我的建议是——先在本机用生产模式把 jar 跑通,连上生产数据库验证一下,再上服务器,这样排查问题成本低很多。
前端打包:
npm run build生成的 dist 目录上传到 Nginx 的 html 目录,配置 Nginx 把 /api 路径反向代理到后端服务:
server { listen 80; server_name your-domain.com; location / { root /usr/share/nginx/html/dist; index index.html; try_files $uri $uri/ /index.html; } location /api/ { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }try_files 配置一定要加,否则Vue路由用 history 模式时,刷新页面会404。
7. 常见问题与排查建议
开发中遇到的各种问题,我挑最有代表性的几个做成速查表,方便大家遇到时直接对照解决:
| 问题现象 | 根因分析 | 解决方案 |
|---|---|---|
| 启动报 Access denied for user | 数据库账号密码错误或权限不足 | 检查application.yml的账号密码,MySQL执行 GRANT ALL PRIVILEGES ON elderly_care.* TO 'root'@'localhost' |
| 中文乱码 | 数据库表字符集不是utf8mb4,或连接URL没加编码参数 | 建库时指定 CHARACTER SET utf8mb4,URL加上 characterEncoding=utf8 |
| 接口返回401 | 请求头没带token,或token已过期 | 检查前端请求拦截器是否附加了token,后端检查拦截器放行路径配置 |
| 分页不生效返回全部数据 | MyBatis-Plus分页插件没配置 | 检查是否配置 MybatisPlusInterceptor 的 PaginationInnerInterceptor |
| 前端刷新页面404 | Vuerouter用了history模式,Nginx没有try_files配置 | Nginx加 try_files $uri $uri/ /index.html |
| 跨域报错 | 开发环境没配置代理,或后端没配CORS | 优先用 vue.config.js 的 devServer.proxy 方案 |
| 图表不显示但接口有数据 | 数据结构与ECharts配置不对应 | 前端用 console.log 打印接口返回,核对series.data是否数组 |
再补充几个我实际开发中总结的经验:
第一,后端Controller不要写太多代码。一个Controller的正常状态是30行以内,参数校验和业务逻辑全在Service层,Controller里只做参数接收和结果返回。答辩时老师看代码,一眼就能看出你的分层设计是否规范。
第二,接口统一返回格式别偷懒。哪怕只做一个模块,也要先把Result类写好。前后端联调的过程中改接口返回格式是最浪费时间的。
第三,Git版本控制从第一天就要用。每完成一个模块提交一次,万一代码改坏了能回滚,比每次Ctrl+Z安全太多。
第四,接口测试用 Postman 或 Apifox。一个接口写完立刻测,别拖到前端同事来催你时才知道接口报错。
毕设做完之后,这个项目如果想继续演进,我还建议可以加一个数据可视化大屏(入住率、健康情况总览)、家庭端的小程序、或者基于体检数据的健康风险评估模型。这些方向都能作为后续的“研究展望”写进论文,也能给项目本身增加深度。
个人的体会是,做这类管理系统毕业设计,技术本身并不是最大的障碍,真正的难点在于“把一个完整业务场景拆解成可落地的表结构和接口流程”,以及“每个环节诸如权限、分页、跨域这些细节下功夫”。这套养老公寓管理系统,麻雀虽小但是五脏俱全,做明白一个,对全栈开发的理解会加深很多。希望这篇拆解笔记能给你省下几周摸索的时间。