ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

SSM+MySQL个人健康信息管理系统源码解析与实战

SSM+MySQL个人健康信息管理系统源码解析与实战

简介:基于 SSM 与 MySQL 的个人健康信息管理系统项目文档,面向 Java Web 方向的毕业设计、课程设计学习者,可直接用于个人健康数据管理类选题的规划、开题与设计说明撰写。压缩包共 1 个文件,为约 5.26MB 的 docx 文档,内容覆盖项目背景及意义、经济/人员/法律/操作可行性分析、功能需求(注册登录、个人信息维护、健康数据记录、提醒设置、数据分析与报告)、SSM 分层架构、数据库表设计以及功能性/性能/安全性测试方案。文档按完整开发流程组织,对用户表、健康数据表、健康提醒表、数据分析表等核心表的设计思路有具体描述,并将 JSP 前端展示、SpringMVC 请求处理、MyBatis 数据访问等层次贯通起来,方便对照自己的系统做功能补全和细节完善。文内还包含中英文摘要、目录框架与写作脉络,能帮助快速搭建毕业论文结构。目前已有 77 人学习,适合作为健康管理、信息管理类毕业设计项目的参考资料。

1. 项目先看清:SSM + MySQL 个人健康信息管理系统,能干什么、适合谁

第一次拿到这套 SSM + MySQL 的个人健康信息管理系统源码时,我原以为它又是一个只写了注册登录的“毕设壳子”,翻完目录才发现,用户注册登录、健康指标记录、健康提醒设置、历史数据查看、管理员角色管理全都齐了,连数据库脚本和 JSP 页面都是一套完整的。这类项目在国内 Java Web 课程设计和毕业设计里出镜率很高,很多计算机专业学生会选它做课题,工作两三年的开发者也常拿它复习 SSM 三层架构的配合方式。它适合三类人:准备毕设答辩的学生,想快速搭一个健康类 Web 应用原型的开发者,以及想捋一遍 Spring + SpringMVC + MyBatis 实际协作流程的 Java 学习者。下文我会按拆解顺序,先把架构和目录讲透,再落到数据库表和核心代码,最后给出一套能照做的部署和改造路线。

2. 架构与目录拆解:SSM 三层结构各司其职

拿到源码第一件事,我习惯先通读 web.xml,因为 SSM 项目的入口配置全在那里:DispatcherServlet 的映射路径、Spring 容器加载哪个 XML 配置文件、字符编码过滤器有没有配 UTF-8,这些决定了项目能不能正常起。这套个人健康信息管理系统的工程结构属于典型的传统 Java Web 分层,包名划分很规矩,下面拆开讲。

2.1 技术选型:为什么毕设课设偏爱 SSM 而不是 Spring Boot

SSM 是 Spring + SpringMVC + MyBatis 三个框架的组合,各管一段:Spring 管对象的创建、依赖注入和事务,SpringMVC 专门处理 HTTP 请求从进入方法到返回页面的过程,MyBatis 把 SQL 写在独立的 XML 映射文件里,不和 Java 代码混在一起。这套系统选它而不是 Spring Boot,我在原论文里看到技术描述也确实是 SSM + JSP + MySQL 的组合,项目里 Spring 管理业务 Bean,SpringMVC 接收请求做参数绑定,MyBatis 操作 MySQL,分工边界非常清楚,特别适合作为教学和答辩项目。

有一说一,Spring Boot 确实比 SSM 上手快,不用写一堆 XML 配置,启动一个 Web 服务一个 main 方法就够了。但 Boot 的自动配置把太多细节藏住了,很多初学者学完 Boot 依然不清楚一个请求是从哪里进来的。SSM 则相反,applicationContext.xml、springmvc.xml、web.xml 每个配置都摆在明面上,翻一遍配置就能把请求链路看完整。我的看法是,理解 SSM 之后再去看 Boot 的自动配置,几乎等于开卷考试,规则都有迹可循,这也是为什么很多高校课程设计仍然要求用 SSM 而不是直接上 Boot。

页面技术用的是 JSP,没有做前后端分离。这在今天看来有些老,但放在这种内部管理类系统里其实是加分项:一个 JSP 文件里同时写 HTML、EL 表达式和 JSTL 标签,后端把数据塞进 Model 就能在页面上渲染,改起来很直接。原项目的典型流程是 Controller 返回 ModelAndView,JSP 用${}表达式取值,登录状态靠 session 保存,这套做法在中小型 Web 系统里非常稳定。

2.2 包结构与分层职责:从 controller 到 mapper 不迷路

我把源码目录整理了一下,典型结构如下:

src/ ├── main/ │ ├── java/ │ │ └── com/health/ │ │ ├── controller/ # 前端控制器,接收请求并路由 │ │ │ ├── UserController.java │ │ │ └── HealthRecordController.java │ │ ├── service/ # 业务接口与实现 │ │ │ ├── UserService.java │ │ │ ├── impl/UserServiceImpl.java │ │ │ └── impl/HealthRecordServiceImpl.java │ │ ├── mapper/ # MyBatis Mapper 接口 │ │ │ ├── UserMapper.java │ │ │ └── HealthRecordMapper.java │ │ ├── entity/ # 数据库表对应的实体类 │ │ │ ├── User.java │ │ │ └── HealthRecord.java │ │ └── util/ # 工具类(日期处理等) │ │ └── DateUtil.java │ └── resources/ │ ├── jdbc.properties # 数据库连接参数 │ ├── mybatis-config.xml # MyBatis 全局配置 │ └── mapper/ # SQL 映射 XML 文件 │ ├── UserMapper.xml │ └── HealthRecordMapper.xml └── webapp/ ├── WEB-INF/ │ ├── web.xml # 项目入口配置 │ └── views/ # JSP 页面 │ ├── login.jsp │ ├── register.jsp │ ├── index.jsp │ ├── record_add.jsp │ └── record_list.jsp └── static/ # CSS/JS 静态资源

分层逻辑很清晰:Controller 只做参数接收和页面跳转,不写 SQL;Service 层处理业务规则,比如注册时判断用户名是否已存在、登录时校验密码;Mapper 接口只声明方法,真正的 SQL 写在 Mapper.xml 里。这样做的直接好处是,改动数据库表结构时大概率只动 XML 映射文件,业务代码不用跟着变。

有一个细节值得注意:JSP 页面放在 WEB-INF/views 下而不是 webapp 根目录。WEB-INF 目录下的文件不能通过浏览器直接输入 URL 访问,必须由 Controller 转发或者重定向才能进入。这种做法能防止用户绕过登录校验直接访问某个 JSP 页面,是一个成本极低但很有效的安全性设计。

2.3 一次完整的请求链路:从 JSP 表单到 MySQL

理解了分层和目录,再看一次完整请求是怎么走通的。以登录为例,我在代码里追踪了整个链路:

1. 用户在 login.jsp 输入用户名和密码,点击提交 2. 表单 POST 到 /login,web.xml 配置的 DispatcherServlet 拦截请求 3. HandlerMapping 根据 URL 找到 UserController 里的 login 方法 4. Spring 自动注入 UserService,Service 里再注入 UserMapper 5. UserMapper.xml 里 id=selectByUsernameAndPassword 的 SQL 被执行 6. 查询结果返回给 Service,再返回给 Controller 7. 登录成功:user 对象写入 session,重定向到 /index 8. 登录失败:返回 login.jsp,页面用 EL 表达式显示 errMsg

这套链路最大的特点就是每一层都能被单独测试和替换。比如想从 MySQL 换成 Oracle,只需要改 jdbc.properties 里的驱动和 URL,再检查一遍 SQL 方言,Service 和 Controller 完全不用动。想给登录加验证码,也只在 Controller 里加一段校验逻辑,不影响底层数据访问。这种低耦合设计就是 SSM 在中小型系统里经久不衰的核心原因。

3. 数据库设计:4 张表撑起健康管理闭环

数据库是这套系统的地基。我打开项目自带的 SQL 脚本后确认,核心表一共 4 张,分别对应用户、健康指标记录、健康提醒和健康报告。表数量不多,但表间关系设计得比较完整,能看出来是参照了真实的健康管理业务场景,而不是随便建几张表凑数。

3.1 用户表:账号、角色与个人基础信息

用户表是整套系统的主表,除了账号密码之外还存了姓名、性别、年龄、手机号等基础信息,以及一个 role 角色字段。原论文里提到系统包含管理员角色,医院或健康管理机构可以充当管理员,对接管整个系统的用户和数据。这个字段我拆的时候特意看了下默认值是 USER,管理员账号需要手动在数据库里改。

CREATE TABLE t_user ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT '主键', username VARCHAR(50) NOT NULL COMMENT '登录账号', password VARCHAR(100) NOT NULL COMMENT '登录密码', role VARCHAR(20) DEFAULT 'USER' COMMENT '角色:USER/ADMIN', real_name VARCHAR(50) COMMENT '真实姓名', gender VARCHAR(10) COMMENT '性别', age INT COMMENT '年龄', phone VARCHAR(20) COMMENT '手机号', create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '注册时间' ) COMMENT='用户表';

字段说明:username 和 password 是登录凭证,代码里直接用明文拼接 SQL 查询——这在项目里是能跑但不够安全的地方,下面的避坑章节我会单独说;role 决定登录后跳转到普通用户界面还是管理员界面;real_name、gender、age、phone 都属于个人健康档案的基础信息,后续健康数据统计时会按年龄段分组,所以 age 字段单独建列而不是从身份证解析,是有意为之。

3.2 健康记录表:身高体重血压怎么存

健康记录表是业务核心,用户每次录入的身体指标都存这一张表。我拆的时候注意到一个设计细节:血压字段拆成了收缩压和舒张压两个字段分别存储。很多人第一次做健康类系统会把血压存成一个字符串比如 120/80,看起来省事,实际做数据分析时要拆字符串才能算平均值,非常痛苦。这套系统的做法是规范做法。

CREATE TABLE t_health_record ( id INT PRIMARY KEY AUTO_INCREMENT, user_id INT NOT NULL COMMENT '关联 t_user.id', height DECIMAL(5,2) COMMENT '身高cm', weight DECIMAL(5,2) COMMENT '体重kg', systolic DECIMAL(5,2) COMMENT '收缩压mmHg', diastolic DECIMAL(5,2) COMMENT '舒张压mmHg', heart_rate INT COMMENT '心率,次/分', blood_sugar DECIMAL(5,2) COMMENT '空腹血糖mmol/L', record_date DATE COMMENT '记录日期', create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '录入时间', INDEX idx_user_date (user_id, record_date) ) COMMENT='健康指标记录表';

DECIMAL(5,2) 表示最多 5 位数字、保留 2 位小数,身高体重血压血糖这种连续型数值都用这个类型;heart_rate 是整数所以用 INT。联合索引 idx_user_date 建在 user_id 和 record_date 两个字段上,这是这套系统数据量大了以后仍然能保持查询速度的关键,因为最常见的操作就是按用户和时间范围查记录。record_date 是用户选择或系统自动生成的业务日期,create_time 是数据实际写入时间,两个字段职责不同,不能合并。

3.3 提醒表与健康报告表:功能闭环的另外两块拼图

健康提醒表支撑的是“定时喝水、按时吃药、定时运动”这类功能,字段设计得比较简单:提醒标题、每日提醒时间、开关状态。真正要做消息推送的话,这里还需要扩展一个推送渠道字段,但作为课设级别的系统,能把提醒时间和开关状态存下来已经够用了。

CREATE TABLE t_reminder ( id INT PRIMARY KEY AUTO_INCREMENT, user_id INT NOT NULL COMMENT '关联用户ID', title VARCHAR(100) COMMENT '提醒内容', remind_time TIME COMMENT '每日提醒时间', status TINYINT DEFAULT 0 COMMENT '0未启用 1启用', create_time DATETIME DEFAULT CURRENT_TIMESTAMP ) COMMENT='健康提醒表'; CREATE TABLE t_health_report ( id INT PRIMARY KEY AUTO_INCREMENT, user_id INT NOT NULL COMMENT '关联用户ID', report_date DATE COMMENT '报告日期', report_content TEXT COMMENT '分析结果与健康建议', create_time DATETIME DEFAULT CURRENT_TIMESTAMP ) COMMENT='健康报告表';

健康报告表用于存储系统对用户一段时间内健康数据的分析结果。这套系统的报告生成逻辑相对简单,主要是根据最近录入的数据算平均值,然后给出模板化的建议,比如血压偏高就提示少盐少油、规律作息。真正要做到智能分析,可以接入 AI 算法做疾病风险预测,这是原论文里提到的未来趋势,也是后面二次开发章节我会展开讲的点。

3.4 关键查询 SQL:按时间取数做趋势分析

健康管理类系统最核心的查询就两类:按时间范围查明细,以及按天聚合算平均值。我整理了两条项目中用的典型 SQL。

-- 按日期范围查某用户健康记录,时间倒序 SELECT id, height, weight, systolic, diastolic, heart_rate, blood_sugar, record_date FROM t_health_record WHERE user_id = #{userId} AND record_date BETWEEN #{startDate} AND #{endDate} ORDER BY record_date DESC; -- 近30天每天的平均心率 SELECT DATE_FORMAT(record_date, '%Y-%m-%d') AS stat_day, AVG(heart_rate) AS avg_heart_rate FROM t_health_record WHERE user_id = #{userId} AND record_date >= DATE_SUB(CURDATE(), INTERVAL 30 DAY) GROUP BY stat_day ORDER BY stat_day;

第一条 SQL 的业务场景是用户查看历史记录时按起止日期筛选;第二条是为健康趋势图准备的数据,按天分组算平均值,返回结果直接就能喂给前端画折线图。DATE_FORMAT 在这里起到把 datetime 类型的记录日期统一成字符串日期的作用,避免同一天多条记录因为时间不同被分到不同分组。要注意的是 MySQL 里 DATE_SUB(CURDATE(), INTERVAL 30 DAY) 得到的是 30 天前的日期,边界条件是包含当天的,实际业务中如果要求严格的 30 天窗口需要再确认边界语义。

4. 核心模块实现:登录校验与健康记录的两段关键代码

前面把架构和表结构都拆完了,这一章深入到代码层面。我挑了两个最能代表 SSM 协作方式的模块来讲:登录和健康记录录入。前者体现了三层架构的数据流,后者涉及参数绑定、session 校验和重定向这些 Web 开发高频操作。

4.1 登录模块:Controller + Service + Mapper 三层怎么配合

登录是最经典的 SSM 演示场景。先看 Controller 层,负责接收请求参数和决定页面跳转。

@Controller @SessionAttributes("loginUser") public class UserController { @Autowired private UserService userService; @RequestMapping(value = "/login", method = RequestMethod.POST) public String login( @RequestParam("username") String username, @RequestParam("password") String password, Model model, HttpSession session) { // 调用 Service 层做真正的登录校验 User user = userService.login(username, password); if (user != null) { // 登录成功,把用户对象放进 session,后续页面判断登录状态靠它 session.setAttribute("loginUser", user); return "redirect:/index"; } // 登录失败,携带错误信息返回登录页 model.addAttribute("errMsg", "账号或密码错误,请重新输入"); return "login"; } }

这段代码有几个点值得说。@RequestMapping 里指定了 POST 方法,这意味着通过浏览器直接输入 /login 地址访问不会命中这个接口,能拦截一部分误操作。scope 方面,@SessionAttributes 注解和 session.setAttribute 是两种不同的状态管理方式,实际生效的是 session.setAttribute,这个注解更多是配合 SpringMVC 的模型数据处理用的,我在拆解时发现项目里这两个并用确实容易让人困惑。返回值方面,登录成功用 redirect 不用 forward,是为了防止用户刷新浏览器时重复提交登录表单,这是 AB 端系统通用做法。

再看 Service 层和数据层,Service 里不写 SQL,只是调 Mapper 接口再返回结果。

@Service public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Override public User login(String username, String password) { return userMapper.selectByUsernameAndPassword(username, password); } }
<select id="selectByUsernameAndPassword" resultType="User"> SELECT id, username, password, role, real_name FROM t_user WHERE username = #{username} AND password = #{password} </select>

MyBatis 的参数绑定用 #{} 而不是直接拼接字符串,这一点很关键。${} 是文本替换,#{} 是预编译占位符,前者会造成 SQL 注入,后者不会有这个问题。原项目里登录用的这个查询没有走入参对象,如果后续改造,把两个参数包进一个 Map 或者用一个 LoginDTO 对象,SQL 可读性会更好。

4.2 健康记录录入:参数校验与 session 身份绑定

健康记录录入模块的安全性设计比登录更有参考价值。看这段 Controller 代码。

@RequestMapping(value = "/record/add", method = RequestMethod.POST) public String addRecord(@ModelAttribute("record") HealthRecord record, HttpSession session, Model model) { // 从 session 中取出当前登录用户,防止用户伪造别人的 user_id User loginUser = (User) session.getAttribute("loginUser"); if (loginUser == null) { // 未登录直接踢回登录页 return "redirect:/login"; } // 强制把当前登录用户ID写入记录,忽略页面提交的 user_id 字段 record.setUserId(loginUser.getId()); // 调用业务层入库 healthRecordService.addRecord(record); // 添加成功跳转列表页 return "redirect:/record/list"; }

这里的核心思路是:user_id 不信任前端传值,而是从 session 里取当前登录用户。很多初级开发者会把用户 ID 放在表单隐藏域里提交,后端直接存,这等于给了攻击者伪造数据归属的机会,改一下隐藏域就能把健康记录写到别人名下。这套系统用 session 强制覆盖,是一个很值得抄的安全设计。

参数校验方面,@ModelAttribute 会把表单里所有与 HealthRecord 字段同名的参数自动绑定到对象属性上。比如表单里有个 input 的 name 是 weight,提交后 record.getWeight() 就能拿到值,省去了手动 request.getParameter 的重复代码。但如果前端传了 record_date 为空字符串,绑定后得到的可能是空字符串而不是 null,入库时容易报日期格式错误。我一般会在 Service 层加一道校验:日期为空就取当天日期,数值范围异常直接抛业务异常。这套系统在 Service 层做了一部分校验,但没做前后端双重验证,属于可以加强的地方。

4.3 历史数据查询:时间范围筛选安全地拼进 SQL

数据查询模块的典型场景是按日期筛选健康记录。

@RequestMapping("/record/list") public String list(@RequestParam(value = "start", required = false) String start, @RequestParam(value = "end", required = false) String end, HttpSession session, Model model) { User loginUser = (User) session.getAttribute("loginUser"); if (loginUser == null) { return "redirect:/login"; } Map<String, Object> params = new HashMap<>(); params.put("userId", loginUser.getId()); params.put("startDate", start); params.put("endDate", end); // 按用户和时间范围查询 List<HealthRecord> records = healthRecordService.listByUserAndDate(params); model.addAttribute("records", records); return "record_list"; }

这段代码处理了两个边界情况。第一个是 start 和 end 参数加了 required=false,也就是说用户可以不选时间范围直接查全部记录,不会因为缺少参数报 400 错误;第二个是 start 和 end 都为空时,后端查到的 SQL 不能拼出无效的 BETWEEN 子句,需要在 Mapper.xml 里用动态 SQL 判断。

<select id="selectByUserAndDate" resultType="HealthRecord"> SELECT * FROM t_health_record WHERE user_id = #{userId} <if test="startDate != null and startDate != ''"> AND record_date >= #{startDate} </if> <if test="endDate != null and endDate != ''"> AND record_date &lt;= #{endDate} </if> ORDER BY record_date DESC </select>

是 MyBatis 动态 SQL 里最常用的标签,test 里写判断条件,满足条件才拼进 SQL。这里要注意 XML 中小于等于号不能直接用 <=,需要写成 <= 转义,很多人第一次写 MyBatis 动态 SQL 都在这里翻车。查询结果按 record_date 倒序返回,列表页最新数据在最上面,符合操作习惯。这套系统的列表查询已经具备基础的分页接口雏形,但项目里没有集成 PageHelper 这类分页插件,数据量大之后需要改造。

5. 部署实战与排查记录:从零把项目跑起来

源码拆明白了,接下来就是让它跑起来。SSM 项目部署有固定的步骤,但也有不少容易踩的坑。我按实际经验把整个过程和常见问题写清楚,照着做基本能跑通。

5.1 环境准备:JDK、Tomcat、MySQL 版本怎么搭

这套系统基于 Java 传统 Web 开发,依赖如下:

组件版本建议说明
JDK1.8SSM 项目最稳定版本,避免直接上 17
MySQL5.7 或 8.0实测 5.7 兼容性更好,8.0 注意驱动版本
Tomcat8.5对应 JDK 1.8,兼容 Servlet 3.1
IDEA2020 及以上社区版够用,导入 Web 项目即可
Maven3.6+如果源码带 pom.xml 则必装

项目里有 jdbc.properties 文件,数据库连接参数集中配置在这里。先建数据库再改连接信息,顺序不能反,否则启动时就会直接报数据库连接失败。

jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/health?useUnicode=true&characterEncoding=utf8&useSSL=false jdbc.username=root jdbc.password=你自己的密码

jdbc.url 里带 useUnicode=true 和 characterEncoding=utf8 是关键,不加这两个参数,插入中文数据大概率会乱码。useSSL=false 是为了避免 MySQL 8.0 连接时的 SSL 告警,5.7 下不配也不影响。

5.2 导入工程与修改配置:先跑通再改代码

导入时先判断工程类型:带 pom.xml 的是 Maven 工程,直接用 IDEA 的 Open 选择 pom.xml 导入;没有 pom.xml 的就是普通 Web 工程,配置好 Tomcat 后把 Web 部署进去。我个人更建议先把依赖通过 Maven 拉齐,否则 lib 目录里缺 jar 包会在启动时报 ClassNotFound。

导入完成后,按这个顺序配置:

  1. 在 MySQL 中执行项目自带的 SQL 脚本,生成数据库和全部表结构
  2. 修改 resources/jdbc.properties 的账号密码
  3. 打开 mybatis-config.xml 检查 mapper 映射文件路径是否正确
  4. 配置 Tomcat,Deployment 里把项目 context 设置成 /health
  5. 启动后访问 http://localhost:8080/health/login.jsp

提醒一句,很多版本里源码的 SQL 脚本名称是 healthdb.sql 或 init.sql,文件名可能不同,但内容基本都是建库建表和初始管理员账号,导入一次即可。

5.3 常见问题排查:5 个高频踩坑记录

下面是这套项目最容易出现的几个问题,每个我都按现象、原因、解决三段来写。

现象一:数据库连不上,启动报 Access denied

MySQL 服务能 ping 通,但启动时日志里出现 Access denied for user 'root'。根因就是 jdbc.properties 里账号密码和本地 MySQL 实际不符合,注意密码不能有空格或者被编辑器自动加了引号。解决是打开配置文件确认密码匹配,然后重启 Tomcat。

现象二:JSP 页面中文显示乱码

页面标题和健康数据里的中文全部变成问号。根因是连接串没带 characterEncoding=utf8,或者 JSP 页面顶部没有声明 pageEncoding。解决是两处都检查:jdbc.properties 的 url 参数,以及每个 JSP 第一行的<%@ page contentType="text/html;charset=UTF-8" %>。

现象三:启动报 ClassNotFoundException

Tomcat 启动后抛 ClassNotFoundException: org.springframework.web.context.ContextLoaderListener。原因是项目没有把 Spring 的 jar 包发布到 WEB-INF/lib 下。Maven 工程多数是依赖没刷新,执行一次 reimport 即可;普通 Web 工程需要手动检查 lib 目录把缺的 jar 补进去。这类问题最耗时间,尽量用 Maven 管理依赖。

现象四:端口被占用,Tomcat 起不来

8080 端口被其他程序占了,启动时报端口已被使用。解决是不用改代码,直接改 conf/server.xml 里的 Connector 端口,改成 8081 之类的可用端口即可,访问地址也跟着变。

现象五:Mapper 接口绑定异常,启动时抛 BindingException

报 Invalid bound statement,原因是 Mapper.java 接口和 Mapper.xml 的 namespace 或者方法 id 没对上。检查 UserMapper.xml 里 namespace 是否等于接口全限定名,select 标签的 id 是否等于接口方法名。这是 SSM 项目特有的问题,我每次写新接口都强制检查这两个值一致才继续下一步。

6. 二次开发思路:从 SSM 迁移 Spring Boot 或加个健康图表

项目跑通之后,改造方向有两个:一是把整套 SSM 工程改造成 Spring Boot 项目,二是给系统加一个可视化健康趋势模块。前者适合想在毕设里体现新技术点的学生,后者适合想做功能增强的开发者。

6.1 改造成 Spring Boot:改动最小化的迁移路径

改造的核心是把 web.xml 和两个 spring XML 配置全部删掉,替换成 Spring Boot 的 starter 依赖。保留的是 Mapper.xml、实体类、Service 层代码。数据库连接参数从 jdbc.properties 挪到 application.yml,mybatis 的配置写在 application.yml 的 mybatis 节点下。这个迁移过程大概半天时间,做完之后启动方式从部署 Tomcat 变成直接跑 main 方法,调试效率提升很大,还能顺理成章用上 PageHelper 分页和 Druid 连接池。

6.2 给系统加一个健康趋势图表:前端图表 + 后端聚合查询

另一个改造路线不动框架,只加页面。前端引入 ECharts,用第 3 章里那条近 30 天平均心率查询生成一个折线图。后端新增一个接口返回统计结果,返回格式是 JSON 数组,每个元素包含日期和平均值。前端用 Ajax 拉数据后 setOption 渲染。这样做的好处是不碰现有代码结构,新接口单独走一个 Controller,不动原来的 JSP 页面,风险最小。

6.3 验证方式与一处安全加固

改造完成后,把注册、登录、记录录入、历史查询四条主流程各跑一遍,确认数据能正常入库、页面能正常跳转。另外我强烈建议把登录密码从明文改成 MD5 加盐存储,在 UserServiceImpl 里加一个加密工具类即可,数据库里已有用户的密码需要同步更新。这个改动成本很低,但答辩或者面试时讲出来,能明显体现出工程意识。

从那以后我每拆一个 SSM 项目,都会先把 web.xml、jdbc.properties、Mapper.xml 这三个文件通读一遍再动代码,很多启动不了的问题其实早在这三处就埋下了。希望这篇拆解能帮你把这套个人健康信息管理系统跑起来,也祝二次开发顺利。

本文还有配套的精品资源,点击获取

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进