简介:一套面向Java学习者与课程设计者的家庭健康管理系统完整项目,基于SSM(Spring+SpringMVC+MyBatis)框架,围绕家庭管理、成员管理、健康指标管理、指标上报和健康报告等功能设计,覆盖从数据库建模到前后端交互的典型业务闭环,适合作为毕业设计或项目实践参考。压缩包共107个文件,总大小约806KB,其中包含34个Java源码文件、21个JSP页面、17个XML配置以及JS、CSS等前端资源,并附带SQL脚本可初始化数据库,解压后能清晰看到后台逻辑、页面模板与静态资源的组织方式。当前已有42人学习/下载,整体项目轻量但结构完整,适合快速读懂SSM整合流程和家庭健康场景下的指标管理实现思路。通过源码可以掌握用户管理、家庭成员维护、指标上报及健康报告生成等模块的编码方式,同时获得可直接运行的系统原型,便于二次扩展或用于答辩展示。
1. 切入点:家庭健康管理为什么需要一个 SSM 项目
家里长辈的血压、血糖、心率这些数据,现在大多记录在纸质的本子上,或者散落在微信聊天记录里。时间一长,想找某个月的记录对比看看趋势,翻半天也翻不全。这个基于 SSM 框架(Spring + Spring MVC + MyBatis)的家庭健康管理系统,解决的就是这个“数据分散、难以追踪”的问题——它把家庭成员的健康指标统一录入、存储、展示,支持按时间维度查看趋势,还能对异常指标给出基本判断。适合两类人:一是想给家里老人做健康记录管理的开发者,二是刚开始接触 SSM 整合、需要一个完整 Java Web 项目来练手的学习者。它不是一个大而全的医疗系统,而是一个目标明确、结构清晰的健康指标管理工具,正好可以作为从“会写单模块代码”到“能整合一个完整项目”的过渡案例。
2. 技术选型与整体架构:SSM 三层结构是怎么串起来的
2.1 为什么选 SSM 而不选 Spring Boot
这个项目用的是经典的 SSM 框架组合,也就是 Spring + Spring MVC + MyBatis。现在很多新项目直接上 Spring Boot,但 SSM 依然有它的价值:它把配置过程完全暴露出来,你能看到每个 Bean 是怎么装配的、事务是怎么控制的、SQL 是怎么和 Java 方法绑定的。对于理解 Java Web 底层机制来说,这种“手动档”反而是一种很好的学习材料。
从架构上看,项目分了标准的三层:表现层(Controller)、业务层(Service)、持久层(Mapper/DAO)。Spring 负责管理对象的生命周期和依赖注入,Spring MVC 负责接收 HTTP 请求并路由到对应的 Controller,MyBatis 负责把 Java 方法和 SQL 语句映射起来,处理数据库的读写操作。前端是 JSP + HTML + CSS + JavaScript,通过 Ajax 调用后端接口,拿 JSON 数据渲染页面。
2.2 工程目录结构:拿到源码先看哪里
这里用一个通用的 Maven 工程结构来说明。实际项目中目录名可能有差异,但分层思路是一致的:
family-health-manager/ ├── pom.xml # Maven 依赖配置 ├── src/main/java │ ├── com/health │ │ ├── controller/ # 表现层,处理前端请求 │ │ │ ├── UserController.java │ │ │ ├── HealthDataController.java │ │ │ └── LoginController.java │ │ ├── service/ # 业务层接口 │ │ │ ├── UserService.java │ │ │ └── HealthDataService.java │ │ ├── service/impl/ # 业务层实现 │ │ │ ├── UserServiceImpl.java │ │ │ └── HealthDataServiceImpl.java │ │ ├── mapper/ # MyBatis 数据访问接口 │ │ │ ├── UserMapper.java │ │ │ └── HealthDataMapper.java │ │ ├── entity/ # 实体类,对应数据库表 │ │ │ ├── User.java │ │ │ └── HealthData.java │ │ └── interceptor/ # 登录拦截器等 │ │ └── LoginInterceptor.java │ ├── resources │ │ ├── spring/ # Spring 配置文件 │ │ │ ├── applicationContext.xml │ │ │ └── spring-mvc.xml │ │ └── mapper/ # MyBatis XML 映射文件 │ │ ├── UserMapper.xml │ │ └── HealthDataMapper.xml │ └── jdbc.properties # 数据库连接配置 └── src/main/webapp ├── WEB-INF │ └── jsp/ # JSP 视图 │ ├── login.jsp │ ├── index.jsp │ └── health/list.jsp ├── static/ # 静态资源 │ ├── css/ │ └── js/ └── index.html # 入口页面第一次拿到源码的人,我建议按这个顺序捋:先看 pom.xml 了解项目依赖,再看 jdbc.properties 改成本地数据库配置,然后从 LoginController 开始沿着“请求 → Service → Mapper → SQL”这条链路读一遍,整个项目就通了。
2.3 数据库表设计:用户和健康指标怎么建模
这个系统的核心是两张表:用户表(t_user)和健康指标记录表(t_health_data)。用户表负责存储家庭成员的账号信息,包括用户名、密码、姓名、年龄、角色等字段。密码存储用的是 MD5 加密后的密文,这是 SSM 项目里很常见的做法,虽然现在更推荐 BCrypt,但作为教学项目 MD5 仍然随处可见。
健康指标记录表则是整个系统的核心,一条记录对应一次测量数据。字段大致包括:记录 ID、用户 ID(外键)、体重、收缩压、舒张压、血糖、心率、体温、测量时间、备注。把血压拆成收缩压和舒张压两个字段,而不是存成一个字符串,是为了后续做数值范围判断和趋势图展示时可以直接参与运算,这个设计在开发时值得沿用。
3. 核心模块拆解:从登录认证到健康指标录入的完整流程
3.1 登录认证:拦截器 + 会话控制怎么配合
这个系统有一个登录拦截器(LoginInterceptor),它实现了 Spring MVC 的 HandlerInterceptor 接口,在请求进入 Controller 之前先检查 Session 里有没有用户信息。如果没有就重定向到登录页,有就放行。这里直接看核心代码:
public class LoginInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 从 Session 中获取当前登录用户 User user = (User) request.getSession().getAttribute("currentUser"); if (user == null) { // 未登录,跳转到登录页面 response.sendRedirect(request.getContextPath() + "/login"); return false; } // 已登录,放行请求 return true; } }这段代码的逻辑很直接:从 Session 里取用户对象,取不到就跳回登录页。关键在于这个拦截器需要注册到 Spring MVC 的配置里,并且要指定哪些路径需要拦截、哪些路径放行——通常登录接口本身、静态资源(CSS/JS/图片)是需要排除的,否则会出现“登录页自己都加载不了样式”的问题。
在 spring-mvc.xml 里注册拦截器的常见写法是:
<mvc:interceptors> <mvc:interceptor> <!-- 拦截所有请求 --> <mvc:mapping path="/**"/> <!-- 放行登录相关接口和静态资源 --> <mvc:exclude-mapping path="/login"/> <mvc:exclude-mapping path="/static/**"/> <mvc:exclude-mapping path="/css/**"/> <mvc:exclude-mapping path="/js/**"/> <mvc:exclude-mapping path="/images/**"/> </mvc:interceptor> </mvc:interceptors>这里有一个很容易踩的坑:如果你把/login的 POST 提交路径也拦截了,用户输入账号密码点击登录后,请求根本到不了 Controller,而是被重定向回登录页,界面上看不出任何报错,只会觉得“登录按钮点了没反应,页面闪了一下”。排查方式是在浏览器开发者工具里看网络请求的响应状态码,如果是 302 并且 Location 指向登录页,那基本就是拦截路径配置的问题。
3.2 健康指标录入:Controller、Service、Mapper 三层协作
录入一条健康指标数据,是贯穿整个项目架构的典型操作。前端页面把表单里的各项指标通过 Ajax 提交到后端,后端经过三层处理后写入数据库。先看 Controller 层的处理方法:
@Controller @RequestMapping("/health") public class HealthDataController { @Autowired private HealthDataService healthDataService; @RequestMapping(value = "/add", method = RequestMethod.POST) @ResponseBody public Result add(@RequestBody HealthData healthData, HttpSession session) { // 从 Session 中获取当前登录用户,作为这条记录的归属 User currentUser = (User) session.getAttribute("currentUser"); if (currentUser == null) { return Result.error("登录已过期,请重新登录"); } // 将用户 ID 绑定到健康数据对象上 healthData.setUserId(currentUser.getId()); // 调用业务层执行新增 boolean success = healthDataService.addHealthData(healthData); if (success) { return Result.success("记录成功"); } else { return Result.error("记录失败,请检查数据格式"); } } }注意到 Controller 用@RequestBody接收前端传过来的 JSON 字符串,Spring 会调用 Jackson 库把它自动转换成 HealthData 实体对象。这里有一个隐含的要求:前端传的字段名必须和实体类的属性名一致,否则框架会抛异常或者字段全部为 null。比如前端传{"systolicPressure": "120"},实体类里的属性必须叫systolicPressure,如果你写的是systolic,那这个值就丢了。
Service 层的实现则承担了数据校验和业务规则判断的职责:
@Service public class HealthDataServiceImpl implements HealthDataService { @Autowired private HealthDataMapper healthDataMapper; @Override public boolean addHealthData(HealthData healthData) { // 基本参数校验:关键指标不能为空 if (healthData.getSystolicPressure() == null || healthData.getDiastolicPressure() == null) { throw new RuntimeException("血压数据不能为空"); } // 合理性校验:收缩压范围 70-250,舒张压范围 40-150 int systolic = healthData.getSystolicPressure(); int diastolic = healthData.getDiastolicPressure(); if (systolic < 70 || systolic > 250 || diastolic < 40 || diastolic > 150) { throw new RuntimeException("血压数据超出合理范围"); } // 如果没有指定测量时间,默认取当前时间 if (healthData.getMeasureTime() == null) { healthData.setMeasureTime(new Date()); } // 调用持久层写入数据库 int rows = healthDataMapper.insert(healthData); return rows == 1; } }这段代码展示了一个合格开发者在业务层会做的事:不只是简单地把数据往数据库里塞,而是在入口处做了两层校验——空值校验和合理性校验。合理性校验里的血压范围是根据常识设定的:一个人的收缩压如果显示 300,那大概率是录入时多打了个数字。这种在业务层拦截错误数据的方式,比让数据库报错要友好得多。
最后看 Mapper 层的 XML 映射文件,它是 MyBatis 的核心。把 Java 方法insert和一条 SQL 语句绑定:
<insert id="insert" parameterType="com.health.entity.HealthData"> INSERT INTO t_health_data ( user_id, weight, systolic_pressure, diastolic_pressure, blood_glucose, heart_rate, temperature, measure_time, remark ) VALUES ( #{userId}, #{weight}, #{systolicPressure}, #{diastolicPressure}, #{bloodGlucose}, #{heartRate}, #{temperature}, #{measureTime}, #{remark} ) </insert>注意 SQL 里的字段名是下划线风格(systolic_pressure),而#{}里写的是实体类的属性名(systolicPressure)。如果数据库连接配置里设置了mapUnderscoreToCamelCase=true,MyBatis 会自动把下划线风格映射成驼峰风格;如果没有设置,查询时的 ResultMap 就要手动做字段映射,否则查出来的对象属性全部是 null。这个配置项在 mybatis-config.xml 里,往往也是新手最容易忽略的细节。
3.3 历史记录查询与趋势展示:数据怎么变成可视化的图表
有了录入的数据,下一步就是把它们查出来展示。这里的查询不是简单的“查出所有记录”那么简单,而是带了筛选条件:按时间范围查、按家庭成员查、按指标类型查。Controller 层的查询接口接收userId和dateRange两个参数,组装后传给 Service 层。
Service 层按条件查询后,返回一个List<HealthData>。前端拿到这个列表后,通过 ECharts 或者 Chart.js 这类图表库把数据渲染成折线图。以 ECharts 为例,核心的 JavaScript 代码大致是这样的:
// 从后端接口获取健康指标历史数据 $.ajax({ url: '/health/list', data: { userId: $('#userId').val(), startDate: '2025-01-01', endDate: '2025-03-31' }, dataType: 'json', success: function (res) { if (res.code !== 200) { alert('加载数据失败:' + res.message); return; } // 准备图表数据 var dates = []; var systolicData = []; var diastolicData = []; res.data.forEach(function (item) { dates.push(item.measureTime.substring(0, 10)); systolicData.push(item.systolicPressure); diastolicData.push(item.diastolicPressure); }); // 初始化 ECharts 折线图 var chart = echarts.init(document.getElementById('trendChart')); chart.setOption({ tooltip: { trigger: 'axis' }, legend: { data: ['收缩压', '舒张压'] }, xAxis: { type: 'category', data: dates }, yAxis: { type: 'value', name: 'mmHg' }, series: [ { name: '收缩压', type: 'line', data: systolicData }, { name: '舒张压', type: 'line', data: diastolicData } ] }); } });这段代码从接口拿回数据后,做了一次数据转换:把后端返回的 JSON 数组拆成 ECharts 需要的两个数据系列。这里有一个实际的开发经验:后端返回的数据最好按测量时间排序,否则折线图上会看到日期乱序造成的折线交叉回跳,看起来像数据错了,实际上只是排序问题。如果接口没有排好序,可以在 SQL 里加ORDER BY measure_time ASC,前端排序也可以,但在 SQL 里处理更干净。
4. 项目运行:从零到跑通的全流程操作
4.1 环境准备:JDK、Tomcat、Maven 和数据库的版本组合
要把这个项目跑起来,需要准备一套 Java Web 开发环境。推荐的版本组合是这样:JDK 1.8(SSM 项目的标配,高版本 JDK 可能会有兼容性问题)、Maven 3.6+(管理项目依赖)、Tomcat 8.5 或 9.x(部署 Web 应用)。数据库方面用 MySQL 5.7 及以上版本,或者 MariaDB 也可以。
为什么强调版本组合?因为 SSM 框架是十几年前开始流行的技术栈,很多老项目在 JDK 11 以上的环境中会碰到反射报错或 JSP 编译失败的问题。这不是代码的问题,而是版本兼容性问题。所以如果本地装了高版本 JDK,建议单独准备一个 1.8 环境,或者用 IDE 里自带的 JDK 切换功能,别在版本上折腾太久。
4.2 建库建表:初始化数据库脚本
项目源码里一般会附带一个init.sql或者database.sql脚本文件。拿到的第一件事就是在 MySQL 里执行这个脚本,创建数据库和表结构。如果没有附带脚本,按照实体类手写建表 SQL 也不难,核心表结构大致如下:
CREATE DATABASE IF NOT EXISTS family_health_db DEFAULT CHARACTER SET utf8mb4; USE family_health_db; -- 用户表 CREATE TABLE t_user ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(100) NOT NULL, real_name VARCHAR(30), age INT, role TINYINT DEFAULT 0 COMMENT '0-家庭成员 1-管理员', create_time DATETIME DEFAULT CURRENT_TIMESTAMP ); -- 健康指标记录表 CREATE TABLE t_health_data ( id INT PRIMARY KEY AUTO_INCREMENT, user_id INT NOT NULL, weight DECIMAL(5,1) COMMENT '体重kg', systolic_pressure INT COMMENT '收缩压mmHg', diastolic_pressure INT COMMENT '舒张压mmHg', blood_glucose DECIMAL(4,1) COMMENT '血糖mmol/L', heart_rate INT COMMENT '心率bpm', temperature DECIMAL(3,1) COMMENT '体温℃', measure_time DATETIME COMMENT '测量时间', remark VARCHAR(255) COMMENT '备注', FOREIGN KEY (user_id) REFERENCES t_user(id) );字符集用 utf8mb4 而不是 utf8,是因为 utf8mb4 能完整支持一些特殊字符和 emoji,虽然这个系统里不太可能输入 emoji,但这是当前数据库建表的默认习惯。外键约束在建表时就声明好,防止出现没有归属用户的孤儿数据。
4.3 配置调整与启动:三步把项目跑起来
第一步,修改jdbc.properties文件里的数据库连接信息,把 URL、用户名、密码改成自己本地的,这是必须做的一步。很多新手在这一步容易漏掉数据库密码,或者把 URL 里的数据库名写错,导致启动时数据源初始化失败。
第二步,用 Maven 打包。在项目根目录执行mvn clean package,如果配置了阿里云等国内镜像仓库,依赖下载会快很多。打包完成后在target目录下会生成一个 WAR 包,这个包就是可以部署的完整应用。
第三步,把 WAR 包扔到 Tomcat 的webapps目录下,启动 Tomcat,访问http://localhost:8080/项目名/就能看到登录页面。或者更简单的方式是在 IDEA 里直接配置 Tomcat,点击运行按钮一键部署。这里以 IDEA 配置 Tomcat 为例,要点是:在 Run Configuration 里选择 Tomcat Server -> Local,Deployment 选项卡里点击加号选 Artifact,Application context 填/或/family-health,然后启动。启动日志里看到Deployment of web application archive的字样就说明部署成功了。
4.4 运行验证:怎么确认系统真的正常
跑起来之后,用几个典型操作验证系统是否正常。首先注册一个新用户,然后登录,登录成功后应该能看到管理首页。接着录入一条健康指标数据,比如血压 120/80、心率 72、血糖 5.6,保存后去历史记录页面查这条数据是否存在。最后再看趋势图页面,确认折线图上有对应的点。
如果登录后访问任何页面都被弹回登录页,说明 Session 没有正常写入或者拦截器配置有问题;如果录入数据时提示“记录失败”,优先打开浏览器开发者工具看网络请求,找到对应的 POST 请求,查看响应信息里的具体错误提示;如果页面样式全乱了,那是静态资源路径配置有问题,检查spring-mvc.xml里是否配置了mvc:resources映射。
5. 避坑指南:SSM 项目最常见的五个坑与排查方法
5.1 查询结果全部是 null:驼峰映射没有开启
现象:登录功能正常,但查询健康指标列表时,前端收到的数据里每个字段都是 null。数据库里明明有数据,接口也没有报错。
原因:数据库表字段是下划线风格(systolic_pressure),实体类属性是驼峰风格(systolicPressure),MyBatis 默认不会自动把下划线映射成驼峰。如果查询时没有配置 ResultMap,也没有开启驼峰映射,Java 对象就接收不到数据库返回的值。
解决:在mybatis-config.xml的<settings>节点里加上<setting name="mapUnderscoreToCamelCase" value="true"/>,重新启动服务,查询结果就正常了。这个配置项对 insert 不影响,对 select 影响极大,拿到项目第一件事就可以检查它。
5.2 登录接口被拦截导致无法登录
现象:输入正确的用户名密码,点击登录后页面刷新了一下又回到登录页,没有任何错误提示。后台日志里也没有任何登录相关的请求记录。
原因:登录提交路径/login被拦截器拦截了。注册拦截器时写了<mvc:mapping path="/**"/>,但没有把/login添加到<mvc:exclude-mapping>里,导致 POST 请求在到达 Controller 之前就被拦下。
解决:在 spring-mvc.xml 的拦截器配置中,把登录接口路径和静态资源路径都加到排除列表里。如果登录接口是/user/login,那exclude-mapping就写/user/login,注意路径要完全匹配,不要写/login去排除一个/user/login的接口,那样照样会被拦截。
5.3 前端传日期字符串报 400 错误
现象:录入健康指标时,测量时间字段传的是2025-03-20 08:30:00这样的字符串,后端接口直接返回 HTTP 400,控制台报错信息是 JSON 解析失败。
原因:Spring MVC 在把 JSON 字符串转换成 Java 对象时,默认使用 Jackson 的格式。Jackson 对java.util.Date类型的默认解析格式是 ISO 8601 的时间戳格式,yyyy-MM-dd HH:mm:ss这种带空格的标准日期格式不在默认支持范围内,所以直接解析失败。
解决:有三种常见做法。第一种是前端把日期字符串改成时间戳,new Date().getTime()转换成毫秒数再传给后端;第二种是在实体类的日期字段上加@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")注解;第三种是在 Spring MVC 配置里注册一个全局的日期转换器,统一处理所有日期格式的转换。第二种最省事,推荐优先使用。
5.4 静态资源无法访问,页面只有纯文本
现象:登录页能打开,但完全没有样式,也没有任何图片,查看页面源代码能看到<link>标签引用的是/static/css/style.css,但浏览器访问这个路径返回 404。
原因:Spring MVC 的前端控制器DispatcherServlet映射了/,它会拦截所有请求,包括静态资源。如果配置里没有显式放行静态资源,Tomcat 默认的静态资源处理器就不会工作,CSS、JS、图片全部 404。
解决:在 spring-mvc.xml 里配置静态资源映射,把/static/**映射到实际资源目录:
<mvc:resources mapping="/static/**" location="/static/"/> <mvc:resources mapping="/css/**" location="/static/css/"/> <mvc:resources mapping="/js/**" location="/static/js/"/>这样浏览器访问/static/css/style.css时,Spring MVC 会直接把文件返回给浏览器。配置完成记得重新启动 Tomcat,因为部分 IDE 热部署不会自动重载 XML 配置文件。
5.5 中文乱码:从 JSP 到数据库全链路排查
现象:页面录入中文备注信息,保存到数据库后查看变成了问号或乱码。
原因:这一般是多个环节的编码不一致导致的。可能是 JSP 页面本身没有声明 UTF-8 编码,可能是 Spring MVC 的 CharacterEncodingFilter 没有配置,也可能是数据库连接 URL 里没有指定characterEncoding=utf8,三个环节任何一个断了,中文就乱了。
解决:按链路逐个排查。JSP 页面顶部的pageEncoding设为 UTF-8;web.xml 里配置 CharacterEncodingFilter 的<init-param>设为 UTF-8 并设置<force-encoding>true</force-encoding>;jdbc.properties 里的连接 URL 加上?useUnicode=true&characterEncoding=utf8。三个都做齐,乱码问题基本不会再出现。
6. 二次开发指南:给这个健康管理系统加一个“用药提醒”模块
这个项目的结构清晰,分层明确,做二次开发只需要顺着现有的模式往下加功能。下面以“用药提醒”为例,完整体验一次从建表到前后端联通的开发流程。
6.1 加表加实体:按现有模式扩展数据模型
先建一张用药提醒表,字段包含提醒 ID、用户 ID、药品名称、用药剂量、用药时间、是否已服药。SQL 直接模仿t_health_data的风格,保持命名规范一致:
CREATE TABLE t_medication_reminder ( id INT PRIMARY KEY AUTO_INCREMENT, user_id INT NOT NULL, medicine_name VARCHAR(50) NOT NULL, dosage VARCHAR(30) COMMENT '用药剂量,如1片/次', remind_time VARCHAR(10) COMMENT '提醒时间,格式HH:mm', status TINYINT DEFAULT 0 COMMENT '0-未服药 1-已服药', create_time DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES t_user(id) );再创建对应的实体类MedicationReminder.java,字段和表结构一一对应。注意不要只用基本类型 int,而是用包装类型 Integer,这样数据库里的 NULL 值可以被正确接收,不会因为自动拆箱引发空指针异常。
6.2 照着现有链路写三层代码
最省事的做法是直接照着HealthDataController、HealthDataServiceImpl、HealthDataMapper三个文件的代码风格,把“用药提醒”对应的三个类写出来。不要去改动已有的 Controller、Service 或 Mapper,而是新增一套平行的代码,这样不会影响现有功能。Mapper 的 XML 文件也新建一个MedicationReminderMapper.xml,在里面写 insert、selectByUserId、updateStatus 三个方法对应的 SQL。
写 Service 层的时候,可以在updateStatus这个方法里加一个业务逻辑:当用户把某条提醒标记为“已服药”时,自动在t_health_data表里插入一条备注为“服药”的健康记录,把两个模块串起来。这种小的业务联动,就是体系的加分项。
6.3 前端页面的接入方式
JSP 页面新建一个reminder.jsp,页面上用 Ajax 调用新增的三个接口。列表展示用selectByUserId查出当天所有提醒,每条提醒旁边有一个“标记已服药”的按钮,点击后调用updateStatus。提醒时间可以和业务层里获取当前时间做对比,时间到了就在页面顶部弹出一条提示,这个用 JavaScript 的setInterval定时轮询接口就能实现,不用上 WebSocket。
6.4 改造完成后的验证方法
新模块开发完,验证不能只靠“录入一条数据看看成功没”。我习惯的做法是走一遍异常流程:先不登录直接访问提醒列表接口,确认拦截器返回 401;再登录后新增一条提醒,确认数据落库;把提醒时间改成当前时间,确认前端提示生效;最后把一条提醒标记为已服药,检查t_health_data表里是否新增了一条联动记录。四条路径全部走通,这个模块才算真的开发完成。
这个项目的可扩展点其实还有不少:引入 ECharts 仪表盘展示身体综合评分、加一个上传体检报告的附件管理功功能、用定时任务实现微信推送提醒等。每一条都是沿着“Controller 新增接口 + Service 新增业务逻辑 + Mapper 新增 SQL + JSP 新增页面”的模式走,架构本身不会成为瓶颈。
做二次开发这几年,我翻车最多的情况,不是代码逻辑写不出来,而是改完代码没有走全验证流程就直接交付。特别是拦截器这种“全局生效”的模块,加一个路径配置可能影响所有请求。从那以后我每次改完拦截器或 Spring 配置,都强制把登录、退出、带参数查询、无参数查询这几条路径重新走一遍。希望这篇拆解能帮你在跑通这个项目的同时,也把这套验证意识带进自己的开发习惯里。
本文还有配套的精品资源,点击获取