资讯详情

资讯详情

SpringBoot+Java个人健康管理系统:追踪与干预闭环设计

去年帮学弟把关毕业设计他问得很直接老师给的题目是基于SpringBoot与Java的个人健康管理系统后面还挂了个副标题叫智能个体健康追踪与干预平台。我搜了一圈参考感觉全是增删改查这怎么写得出亮点这个疑问我太熟悉了。健康管理系统的难点从来不在CRUD而在标题里追踪和干预这两个词——数据进来了能不能形成连续的追踪链条分析出问题之后能不能给出让人愿意执行的干预动作至于个人全生命周期健康守护说白了就是不同年龄段用不同的分析标准。今天就把这个经典的毕设题目完整拆一遍从需求拆解、技术选型、数据库设计、核心代码到答辩准备正在开题或已经写了一半的同学可以直接对着抄。后来我陆续看过不少同题的成品得分差距真的很大。有的做完就是三个页面录入、列表、个人中心评委问两句就露馅。有的功能不多但把记录→分析→干预→反馈这条闭环做通了答辩时现场演示一套完整的健康管理流程分数明显高一档。这篇文章要解决的问题就是怎么把后者这种闭环感落地成代码而不是停在PPT上。1. 先拆题追踪、干预、全生命周期各自意味着什么1.1 追踪不是记录流水账而是数据连续性很多同学把健康追踪理解成用户每天往系统里录体重和血压这没错但只对了一半。追踪的价值在于连续两个字——单独的体重数据没有任何意义一组按时间排列的体重数据才能看出趋势是稳定、上升还是下降。所以系统从设计第一天起就要为连续性服务而不是做一个高级记事本。落到功能上至少要有三件事。第一每个指标要有独立的时间轴录入时把记录时间存清楚查询时能按天、按周、按月做聚合。第二要有缺失数据的感知用户连续几天没录体重系统应该能发现并提醒这种细节非常体现工程意识。第三趋势可视化的数据结构要提前设计好ECharts折线图需要的是日期数值的序列这个结构最好在数据库查询阶段就组织好不要在内存里二次加工。我的建议是指标类型不要写死。用一张health_record表通过record_type字段区分weight、blood_pressure、heart_rate、blood_sugar、sleep_duration等。这样做的好处是新增指标不用改表结构、不用加接口前端一个下拉框把类型传进来服务端统一处理。缺点是没法给特定指标建专用字段索引但对毕设的数据量来说完全够用。1.2 干预平台才是这个题目的分值点如果只看追踪你的系统和一张Excel表没有本质区别。真正让评委眼前一亮的地方在于干预系统分析了用户的数据之后能不能生成有针对性的建议和计划并且推动用户去执行一个完整的干预闭环是这样的分析出BMI偏高 → 系统生成减重干预计划 → 计划里包含每日运动目标和饮食建议 → 用户逐项打卡 → 打卡结果再反馈回系统作为下一轮分析的输入。这条链路跑通了你的项目就有了平台的概念而不是一个单机记录工具。实现上需要两张表intervention_plan干预计划和intervention_task计划里的具体任务。计划是总纲任务是每天要执行的单元。一个计划可以包含多条任务任务可以按天生成也可以一次性生成一周的任务让用户自由选做。我在代码里采用的是懒生成策略只生成当天的任务第二天由定时任务补上这样避免一次性生成一大堆过期任务没人管也方便任务完成状态的统计。1.3 全生命周期要控制范围别给自己挖坑全生命周期这个词听起来很大——婴幼儿、青少年、中老年不同阶段的关注指标和参考标准都不一样真要面面俱到一个毕设是做不完的。合理的做法是把用户按年龄段分组不同年龄段对应不同的指标参考区间和建议模板。比如18到39岁这个组重心是BMI、作息、运动量40到59岁这个组增加血压等指标60岁以上重点关注血压、心率和慢性病提醒。实现上就是在user表加一个age_group字段分析规则里做分层判断。这样既回应了标题里的全生命周期又控制住了开发量答辩时还能理直气壮地说系统覆盖了用户从成年到老年的各个健康阶段。模块范围也建议卡在这几块用户管理、健康档案、指标记录、趋势分析、风险预警、干预计划、任务提醒、数据看板。看上去多其实每个模块的核心逻辑都很直白比做一个半吊子的智能推荐系统靠谱得多。2. 技术选型SpringBoot Java 为什么是毕业设计的标准答案2.1 技术栈组合与各自的理由先给出一套我验证过比较稳的组合适合大多数拿到这个题目的同学层次选型理由后端框架SpringBoot 2.7.x Java 8生态成熟资料多Java 8在各种环境的兼容性最好ORMMyBatis-Plus 3.5.x单表CRUD零SQL分页插件好用比JPA更容易跟答辩评委解释数据库MySQL 8.0免费、稳定毕设数据量绰绰有余缓存Redis可选做验证码、短期token或缓存分析结果加分项不是必需权限认证Sa-Token 或自研JWTSa-Token上手极快比Spring Security少写很多配置前端Vue 3 Element Plus ECharts组件成熟图表漂亮和管理后台的气质很搭接口风格RESTful JSON前后端分离答辩演示时也更直观为什么推荐SpringBoot而不是更轻量的框架两个原因。第一毕业设计的评分逻辑里工程完备性是很重要的一环SpringBoot自带的配置管理、异常处理、打包部署机制让你天然拥有一个规范的项目骨架。第二面试和后置学习都用得上Spring全家桶是Java岗位的基本盘做一个SpringBoot项目写在简历上是加分项比用某个小众框架更有说服力。2.2 目录结构设计要能讲出道理项目包结构直接反映设计水平评委大概率会让你讲一下每个包是干什么的。我的分层如下com.example.health ├── controller // 接口层只做参数接收和结果返回 ├── service // 业务层核心逻辑必须有接口实现类 ├── mapper // 数据访问层MyBatis-Plus的Mapper接口 ├── entity // 实体类和数据库表一一对应 ├── dto // 数据传输对象接收前端参数 ├── vo // 视图对象返回给前端的结构 ├── config // 配置类跨域、拦截器、定时任务等 ├── common // 通用类统一返回结果、异常、常量 └── utils // 工具类日期、校验、计算controller只负责两件事接收参数、调用service。service里放业务规则。mapper里尽量只有MyBatis-Plus生成的基础方法复杂统计SQL可以手写但也要放在mapper层。这样分层最大的好处是答辩时好讲接口层、业务层、数据层分离各层职责单一这句话说出来评委对你的印象分就上来了。2.3 基础依赖和配置文件pom.xml里最核心的依赖是这样dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.3.1/version /dependency dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version8.0.33/version /dependency dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependencyapplication.yml里几个关键配置spring: datasource: url: jdbc:mysql://localhost:3306/health_system?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: 你的密码 mybatis-plus: configuration: map-underscore-to-camel-case: true log-impl: org.apache.ibatis.logging.stdout.StdOutImpl global-config: db-config: id-type: auto mapper-locations: classpath*:mapper/**/*.xml这里有两个细节要认真对待一是MySQL连接串里必须带serverTimezone否则Java 8的LocalDateTime和数据库的datetime对接时会出现时区偏差常见报错是通信链路失败或时间差8小时二是MyBatis-Plus开启map-underscore-to-camel-case后user_name这样的数据库字段才能自动映射到userName实体属性忘记配置会导致查出来的对象属性全是null而且是那种很难定位的部分为null。3. 数据库设计健康数据表结构怎么建才经得起追问3.1 用户域基础信息与健康档案分开user表存登录信息和基本人口学特征health_profile表存健康档案两者分开的原因是档案数据更新频率低不适合跟频繁登录操作混在同一张表。user表结构大概是这样CREATE TABLE user ( id BIGINT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(255) NOT NULL, nickname VARCHAR(50), gender TINYINT COMMENT 1男 2女, birthday DATE, age_group VARCHAR(20) COMMENT young/middle/elderly, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP );health_profile则存身高、初始体重、既往病史、是否有慢性病标志等。身高是后续BMI计算必需的字段所以初始化用户档案时这个字段不能为空。年龄分组不建议每次查询时现算因为生日变了年龄组也会变维护起来麻烦不如在用户注册或完善档案时一次性算好存进age_group字段后续分析服务直接读取。3.2 健康指标表一张表打天下的取舍前面提过用一张health_record表承载所有指标这是毕设性价比最高的方案。实际建表时我会比常规方案多一个secondary_value字段专门用来处理血压这种两个值的指标CREATE TABLE health_record ( id BIGINT AUTO_INCREMENT PRIMARY KEY, user_id BIGINT NOT NULL, record_type VARCHAR(32) NOT NULL COMMENT weight/blood_pressure/heart_rate/blood_sugar/sleep_duration, record_value DECIMAL(8,2) NOT NULL COMMENT 主值如体重kg、收缩压mmHg, secondary_value DECIMAL(8,2) COMMENT 辅助值如舒张压mmHg, unit VARCHAR(16), record_time DATETIME NOT NULL COMMENT 测量时间, note VARCHAR(255), create_time DATETIME DEFAULT CURRENT_TIMESTAMP, INDEX idx_user_type_time (user_id, record_type, record_time) );为什么要加secondary_value而不直接把血压存成120/80字符串因为字符串没法参与数学运算和比较后续要判断舒张压是否超过90就得在Java里做字符串拆分写起来很丑也容易出错。拆成两个数字字段所有判断都在SQL或简单比较里完成代码干净得多。联合索引idx_user_type_time是本表最重要的索引因为绝大多数查询都是某个用户、某个指标类型、按时间排序这个索引能让这类查询走索引而不是全表扫描。别小看这一行答辩时能解释出设计索引的理由是很加分的。3.3 干预域计划、任务、预警三张表联动CREATE TABLE intervention_plan ( id BIGINT AUTO_INCREMENT PRIMARY KEY, user_id BIGINT NOT NULL, plan_name VARCHAR(100), plan_type VARCHAR(32) COMMENT weight_control/exercise/sleep, goal_value DECIMAL(8,2) COMMENT 目标值, start_date DATE, end_date DATE, status TINYINT COMMENT 0待执行 1进行中 2已完成 3已中止, create_time DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE intervention_task ( id BIGINT AUTO_INCREMENT PRIMARY KEY, plan_id BIGINT NOT NULL, task_name VARCHAR(100), task_type VARCHAR(32) COMMENT exercise/diet/sleep, task_date DATE, completed TINYINT DEFAULT 0, complete_time DATETIME, reward_points INT DEFAULT 10 ); CREATE TABLE health_alert ( id BIGINT AUTO_INCREMENT PRIMARY KEY, user_id BIGINT NOT NULL, alert_type VARCHAR(32) COMMENT high_bmi/high_blood_pressure, alert_level VARCHAR(16) COMMENT warning/danger, alert_content VARCHAR(255), status TINYINT DEFAULT 0 COMMENT 0未读 1已读, create_time DATETIME DEFAULT CURRENT_TIMESTAMP );这三张表的分工很清晰plan定义要干什么、目标是什么、什么时间范围task定义每天具体做什么、做了没有alert记录系统发现了什么风险、用户读没读。我强烈建议把task设计成按天一条记录而不是一条task记录带一个日期范围因为打卡动作天然是当天一次的按天建模会让今天有没有完成这个查询变得非常简单一个等值条件就出来了。4. 核心功能模块的实现路线从入库到出图再到出建议4.1 指标录入接口先校验再入库用户每录入一条健康数据系统要做三层检查格式校验、业务校验、落库。格式校验用Controller层的Validated注解和DTO上的校验注解就能搞定业务校验要放到Service层比如体重不可能为负数、心率不可能是0落库时要注意记录时间和记录类型不能被前端随意传。RestController RequestMapping(/api/health/record) public class HealthRecordController { PostMapping public ResultVoid addRecord(RequestBody Valid HealthRecordDTO dto) { healthRecordService.addRecord(dto); return Result.success(); } }Service public class HealthRecordServiceImpl implements HealthRecordService { Override public void addRecord(HealthRecordDTO dto) { // 1. 指标类型白名单校验 if (!RecordType.isValid(dto.getRecordType())) { throw new BizException(不支持的指标类型); } // 2. 数值范围校验 RecordType type RecordType.valueOf(dto.getRecordType()); if (dto.getRecordValue().compareTo(type.getMinValue()) 0 || dto.getRecordValue().compareTo(type.getMaxValue()) 0) { throw new BizException(数值超出合理范围); } // 3. 记录时间不能晚于当前时间 if (dto.getRecordTime().isAfter(LocalDateTime.now())) { throw new BizException(记录时间不能晚于现在); } // 4. 入库 HealthRecord record new HealthRecord(); BeanUtils.copyProperties(dto, record); record.setUserId(UserContext.getUserId()); healthRecordMapper.insert(record); } }这里用枚举集中管理每种指标的单位、合理范围、展示名称后续分析规则、前端下拉列表都能复用避免在多个地方散落魔法数字。比如RecordType枚举里定义weight的最小值是1、最大值是500blood_pressure的最小值是30、最大值是300写清楚之后前端校验和后端校验可以共用一套规则不会出现两边标准不一致的情况。4.2 趋势查询接口聚合逻辑要在SQL里做给前端折线图的数据核心查询是某用户、某指标、某时间范围内的全部记录。这个接口本身不复杂但有一个性能习惯要养成按日期聚合时不要查出所有明细后在Java里做groupBy而是在SQL里用DATE_FORMAT做分组。Override public ListTrendPointVO getTrend(Long userId, String recordType, LocalDate start, LocalDate end) { return healthRecordMapper.selectTrend(userId, recordType, start, end); }Mapper对应的XML大致如下select idselectTrend resultTypecom.example.health.vo.TrendPointVO SELECT DATE_FORMAT(record_time, %Y-%m-%d) AS datePoint, AVG(record_value) AS avgValue, MAX(record_value) AS maxValue, MIN(record_value) AS minValue FROM health_record WHERE user_id #{userId} AND record_type #{recordType} AND record_time BETWEEN #{start} AND #{end} GROUP BY DATE_FORMAT(record_time, %Y-%m-%d) ORDER BY datePoint /select同一天录了多条数据时取平均值是一个稳妥的选择。如果你想让系统看起来更懂行可以在前端把当日平均和当日波动范围一起展示ECharts用一个折线加面积图就出来了视觉上立刻比单条折线图高一个档次。这个接口的数据结构设计好之后后面做健康周报、月度总结都可以直接复用只是把分组粒度从day改成week或month。4.3 风险预警录入后立即触发一轮分析预警触发的时机有两种一种是用户每次录完数据立刻触发另一种是定时任务每天晚上统一扫描。我建议两者都做录入时实时触发让用户当场看到系统提示您血压偏高的反馈体验感很强定时任务做兜底防止用户某天漏录入导致判断断层。预警判断的逻辑用一个独立服务承载Service public class RiskAlertService { public void evaluateAfterRecord(Long userId, String recordType, BigDecimal value) { RiskLevel level judge(recordType, value); if (level ! RiskLevel.NORMAL) { healthAlertMapper.insert(buildAlert(userId, recordType, level)); } } private RiskLevel judge(String recordType, BigDecimal value) { // 按类型查阈值表返回正常/警告/危险 } }这里有个小的设计选择预警记录写入health_alert表之后用户在前端的消息中心里能看到未读消息看到后标记已读。这个已读/未读机制虽然简单但让系统有了主动通知用户的能力比干巴巴的列表生动很多。4.4 干预计划的生成闭环当用户的某个指标持续异常比如最近7天BMI一直处于超重区间系统应该主动推荐一份干预计划。生成逻辑分四步先读取用户最近一段时间的指标记录再做汇总判断计算均值、变化斜率然后匹配预置的干预模板最后按模板生成计划及每天的task。计划生成后用户可以在前端确认或放弃。确认后每天凌晨的定时任务根据计划生成当天task用户在页面里打卡打卡数据回写后第二天生成任务时会同步读取昨天的完成率并据此微调建议文案。这个记录→分析→干预→反馈→再分析的闭环是整个系统智能感的来源。强烈建议答辩演示时完整走一遍这个流程比讲十页PPT都管用。Component public class PlanGenerateService { public InterventionPlan generatePlan(Long userId, String reasonType) { // 1. 读取最近7天指标记录 ListHealthRecord records healthRecordMapper.selectRecent(userId, 7); // 2. 计算均值与趋势 AnalysisSummary summary analysisService.summarize(records); // 3. 匹配干预模板 PlanTemplate template templateService.match(reasonType, summary); // 4. 生成计划主记录和首日task InterventionPlan plan new InterventionPlan(); plan.setUserId(userId); plan.setPlanName(template.getName()); plan.setPlanType(template.getType()); plan.setStartDate(LocalDate.now()); plan.setEndDate(LocalDate.now().plusDays(template.getDays())); plan.setStatus(0); interventionPlanMapper.insert(plan); generateDailyTask(plan, LocalDate.now()); return plan; } }5. 智能到底怎么实现计算、分级与建议生成规则5.1 基础指标计算BMI与基础代谢率BMI的计算很简单体重kg除以身高m的平方。代码里要注意BigDecimal的精度处理除法的精度位数要显式指定否则会抛ArithmeticExceptionpublic BigDecimal calcBmi(BigDecimal weightKg, BigDecimal heightCm) { BigDecimal heightM heightCm.divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_UP); return weightKg.divide(heightM.multiply(heightM), 1, RoundingMode.HALF_UP); }基础代谢率可以选用营养学中常用的Mifflin-St Jeor公式男性和女性系数不同这也是个体化的一个体现public BigDecimal calcBmr(BigDecimal weightKg, BigDecimal heightCm, Integer age, Integer gender) { BigDecimal base BigDecimal.valueOf(10).multiply(weightKg) .add(BigDecimal.valueOf(6.25).multiply(heightCm)) .subtract(BigDecimal.valueOf(5).multiply(BigDecimal.valueOf(age))); return gender 1 ? base.add(BigDecimal.valueOf(5)) : base.subtract(BigDecimal.valueOf(161)); }BMR算出来之后可以结合用户设置的活动系数估算每日消耗热量干预计划里的每日摄入目标就从这个值推导出来。这样生成的建议就不是拍脑袋的建议少吃而是根据您的代谢水平每日摄入建议控制在1800千卡左右说服力完全不一样。5.2 风险判断规则阈值表的设计比算法重要毕设阶段的智能不靠机器学习靠的是临床指南里成熟的阈值分组。以血压为例目前临床常用的分级大致如下分类收缩压舒张压正常小于 120小于 80正常高值120-13980-89高血压大于等于 140大于等于 90BMI的分组、空腹血糖的正常区间、静息心率的参考范围也是类似的思路。把这些阈值集中放到一个枚举或配置类里而不是散落在if语句中。这样做的一个额外好处是将来要支持不同年龄段的差异化标准只需扩展阈值表的结构业务代码不用大面积改。具体判断时用声明的区间做比较避免出现边界值被两边同时命中的问题。写区间判断代码时一定要明确规定每个区间的开闭。我的习惯是用枚举实现并且采用下含上不含的原则public enum BmiLevel { UNDERWEIGHT(偏瘦, BigDecimal.ZERO, BigDecimal.valueOf(18.5)), NORMAL(正常, BigDecimal.valueOf(18.5), BigDecimal.valueOf(24)), OVERWEIGHT(超重, BigDecimal.valueOf(24), BigDecimal.valueOf(28)), OBESE(肥胖, BigDecimal.valueOf(28), null); private final String label; private final BigDecimal low; private final BigDecimal high; public static BmiLevel of(BigDecimal bmi) { for (BmiLevel level : values()) { boolean geLow level.low null || bmi.compareTo(level.low) 0; boolean ltHigh level.high null || bmi.compareTo(level.high) 0; if (geLow ltHigh) { return level; } } return NORMAL; } }这里用的是下含上不含左闭右开原则BMI 18.5归为正常起始24.0归为超重起始28.0归为肥胖起始不会出现18.5既算偏瘦又算正常的bug。这个边界问题的处理细节面试官和评委都很爱问提前想清楚能答得很漂亮。5.3 趋势判断用最小二乘法做简单预测最近一周体重在上升这种结论最好由程序算出来而不是靠肉眼看折线图猜。常见的做法是拿最近N天的数据做线性回归用斜率判断趋势方向。最小二乘法拟合直线的斜率公式k (n·Σxy - Σx·Σy) / (n·Σx² - (Σx)²)代码实现也不复杂public BigDecimal calcTrendSlope(ListTrendPoint points) { int n points.size(); if (n 3) { return BigDecimal.ZERO; // 数据太少不判断趋势 } BigDecimal sumX BigDecimal.ZERO, sumY BigDecimal.ZERO; BigDecimal sumXY BigDecimal.ZERO, sumXX BigDecimal.ZERO; for (int i 0; i n; i) { BigDecimal x BigDecimal.valueOf(i); BigDecimal y points.get(i).getValue(); sumX sumX.add(x); sumY sumY.add(y); sumXY sumXY.add(x.multiply(y)); sumXX sumXX.add(x.multiply(x)); } BigDecimal numerator BigDecimal.valueOf(n).multiply(sumXY).subtract(sumX.multiply(sumY)); BigDecimal denominator BigDecimal.valueOf(n).multiply(sumXX).subtract(sumX.multiply(sumX)); if (denominator.compareTo(BigDecimal.ZERO) 0) { return BigDecimal.ZERO; } return numerator.divide(denominator, 4, RoundingMode.HALF_UP); }斜率大于0说明总体上升小于0说明总体下降绝对值大小反映变化剧烈程度。数据点少于3个时不判断趋势这是一个很合理的业务约定。基于斜率定性地给出体重呈上升趋势的提示比单纯看今天比昨天重了0.5kg科学得多因为短期波动会被平滑掉。5.4 建议文案的生成模板加数据填充干预建议不需要接入AI大模型用模板加数据填充就够用了。实现上可以做一张建议规则表每条规则包含触发条件和建议文案模板两个字段触发条件满足时把用户数据填入模板。比如BMI为超重时建议文案可能是根据您最近的BMI(24.5)评估体重处于超重区间。建议您在接下来4周内每周安排3次30分钟的中等强度有氧运动同时将每日摄入控制在1800千卡左右。系统已为您生成减重计划您可以在我的计划中查看。看起来像是算出来的建议实际就是模板加几个数字但用户体验和答辩演示效果都很好。关键是要把思路讲清楚规则引擎在这个阶段不需要引入重量级框架用一个策略模式或者Map触发条件, 建议模板就能实现。这个取舍在答辩时是加分项——说明你知道什么是合适的复杂度没有过度设计。6. 避坑指南与答辩准备经历过才知道的细节6.1 我见过翻车最多的五个地方第一时区问题。LocalDateTime和MySQL的datetime对接不上、JSON序列化后前端时间差8小时根源都在serverTimezone和Jackson配置。排查思路是先确认数据库时间再在接口返回里打印时间字段逐段定位。这个问题在体检项目里尤其隐蔽因为健康数据全是时间序列错了就是全错。第二BigDecimal精度。体重、身高、BMI这些字段如果数据库里用double或float会出现0.1加0.2不等于0.3的问题。所有涉及测量值的字段统一用DECIMALJava侧用BigDecimal比较用compareTo而不是equals。不要嫌麻烦这一步能省下后面大量的排查时间。第三JSON循环引用。如果实体类里配了关联关系如User关联List而HealthRecord又关联UserJackson序列化时会出现无限递归直接栈溢出。解决方法是给其中一边加忽略标注或者干脆在VO层做字段裁剪不要直接把实体返回给前端。我个人更推荐后者接口返回什么字段由VO控制安全又灵活。第四MyBatis-Plus分页不生效。很多人装了分页插件但忘了配置PaginationInnerInterceptor导致page查询返回全量数据。最直接的检查方法看SQL日志里有没有LIMIT。没有LIMIT就说明插件没生效回去检查MybatisPlusConfig里的拦截器注册。第五跨域问题。前端跑在5173端口后端跑在8080端口典型的CORS问题。SpringBoot里加一个全局CorsConfig放行指定来源和请求头别在Controller上逐个加注解。至于前端联调时的请求地址建议写在一个配置文件里方便打包部署时切换。6.2 答辩时怎么把智能讲清楚答辩时最怕被问你这个智能体现在哪里这个问题答得好不好直接决定分数。我的建议是准备一个一条龙演示脚本先用一个演示账号录入几天不同趋势的数据比如BMI从正常到偏高的变化然后打开趋势分析页展示折线图接着让系统生成干预计划再去我的计划里把今天的任务打卡最后展示打卡后系统给出的新一轮反馈。全程3到5分钟零口误评委看完自然就理解这个项目的闭环结构了。如果评委追问算法层面可以坦率回答本项目的智能分析采用基于临床分级标准的规则判断和基于最小二乘法的趋势预测不依赖大规模训练数据在个人健康管理场景下规则方案的可解释性和可维护性更强。这句话既承认了技术边界又给出了合理的选型理由很加分。千万不要硬吹自己做了深度学习评委追问几个细节就露馅。6.3 提升完成度的小技巧最后分享几个能显著提升完成度的细节。一是预置演示数据项目启动时通过初始化脚本生成一个演示账号和两三周的模拟健康记录免得答辩现场临时手输数据不仅慢而且显示不出趋势效果。二是把提醒做成定时任务用Spring的Scheduled注解每天定时检查是否有未完成任务有则生成站内提示。这个功能看起来小但非常能体现工程意识因为定时任务、任务调度是评委眼中企业级的标配。三是增加一个健康周报页面每周日自动汇总本周指标均值、趋势和完成率形式上很像真实产品也是很好的收尾功能。可以再加一个简单的数据导出把趋势数据导出成CSV虽然只有十几行代码但给评委的完成度印象是实打实的。这些功能都不难但组合在一起你的系统就从实现了基本功能变成了完成了完整产品闭环。我在实际带项目时见过最可惜的情况就是同学代码写得挺好但演示顺序混乱、数据一塌糊涂最后被评委误判成半成品。所以别忘了毕业设计的分数一半在实现一半在呈现。把闭环跑通、把故事讲顺、把数据备好这个题目拿到高分的把握就非常大了。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →