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 BootSSM 是 Spring SpringMVC MyBatis 三个框架的组合各管一段Spring 管对象的创建、依赖注入和事务SpringMVC 专门处理 HTTP 请求从进入方法到返回页面的过程MyBatis 把 SQL 写在独立的 XML 映射文件里不和 Java 代码混在一起。这套系统选它而不是 Spring Boot我在原论文里看到技术描述也确实是 SSM JSP MySQL 的组合项目里 Spring 管理业务 BeanSpringMVC 接收请求做参数绑定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 返回 ModelAndViewJSP 用${}表达式取值登录状态靠 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 只做参数接收和页面跳转不写 SQLService 层处理业务规则比如注册时判断用户名是否已存在、登录时校验密码Mapper 接口只声明方法真正的 SQL 写在 Mapper.xml 里。这样做的直接好处是改动数据库表结构时大概率只动 XML 映射文件业务代码不用跟着变。有一个细节值得注意JSP 页面放在 WEB-INF/views 下而不是 webapp 根目录。WEB-INF 目录下的文件不能通过浏览器直接输入 URL 访问必须由 Controller 转发或者重定向才能进入。这种做法能防止用户绕过登录校验直接访问某个 JSP 页面是一个成本极低但很有效的安全性设计。2.3 一次完整的请求链路从 JSP 表单到 MySQL理解了分层和目录再看一次完整请求是怎么走通的。以登录为例我在代码里追踪了整个链路1. 用户在 login.jsp 输入用户名和密码点击提交 2. 表单 POST 到 /loginweb.xml 配置的 DispatcherServlet 拦截请求 3. HandlerMapping 根据 URL 找到 UserController 里的 login 方法 4. Spring 自动注入 UserServiceService 里再注入 UserMapper 5. UserMapper.xml 里 idselectByUsernameAndPassword 的 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 idselectByUsernameAndPassword resultTypeUser SELECT id, username, password, role, real_name FROM t_user WHERE username #{username} AND password #{password} /selectMyBatis 的参数绑定用 #{} 而不是直接拼接字符串这一点很关键。${} 是文本替换#{} 是预编译占位符前者会造成 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; } MapString, Object params new HashMap(); params.put(userId, loginUser.getId()); params.put(startDate, start); params.put(endDate, end); // 按用户和时间范围查询 ListHealthRecord records healthRecordService.listByUserAndDate(params); model.addAttribute(records, records); return record_list; }这段代码处理了两个边界情况。第一个是 start 和 end 参数加了 requiredfalse也就是说用户可以不选时间范围直接查全部记录不会因为缺少参数报 400 错误第二个是 start 和 end 都为空时后端查到的 SQL 不能拼出无效的 BETWEEN 子句需要在 Mapper.xml 里用动态 SQL 判断。select idselectByUserAndDate resultTypeHealthRecord SELECT * FROM t_health_record WHERE user_id #{userId} if teststartDate ! null and startDate ! AND record_date #{startDate} /if if testendDate ! 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 项目最稳定版本避免直接上 17MySQL5.7 或 8.0实测 5.7 兼容性更好8.0 注意驱动版本Tomcat8.5对应 JDK 1.8兼容 Servlet 3.1IDEA2020 及以上社区版够用导入 Web 项目即可Maven3.6如果源码带 pom.xml 则必装项目里有 jdbc.properties 文件数据库连接参数集中配置在这里。先建数据库再改连接信息顺序不能反否则启动时就会直接报数据库连接失败。jdbc.drivercom.mysql.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/health?useUnicodetruecharacterEncodingutf8useSSLfalse jdbc.usernameroot jdbc.password你自己的密码jdbc.url 里带 useUnicodetrue 和 characterEncodingutf8 是关键不加这两个参数插入中文数据大概率会乱码。useSSLfalse 是为了避免 MySQL 8.0 连接时的 SSL 告警5.7 下不配也不影响。5.2 导入工程与修改配置先跑通再改代码导入时先判断工程类型带 pom.xml 的是 Maven 工程直接用 IDEA 的 Open 选择 pom.xml 导入没有 pom.xml 的就是普通 Web 工程配置好 Tomcat 后把 Web 部署进去。我个人更建议先把依赖通过 Maven 拉齐否则 lib 目录里缺 jar 包会在启动时报 ClassNotFound。导入完成后按这个顺序配置在 MySQL 中执行项目自带的 SQL 脚本生成数据库和全部表结构修改 resources/jdbc.properties 的账号密码打开 mybatis-config.xml 检查 mapper 映射文件路径是否正确配置 TomcatDeployment 里把项目 context 设置成 /health启动后访问 http://localhost:8080/health/login.jsp提醒一句很多版本里源码的 SQL 脚本名称是 healthdb.sql 或 init.sql文件名可能不同但内容基本都是建库建表和初始管理员账号导入一次即可。5.3 常见问题排查5 个高频踩坑记录下面是这套项目最容易出现的几个问题每个我都按现象、原因、解决三段来写。现象一数据库连不上启动报 Access deniedMySQL 服务能 ping 通但启动时日志里出现 Access denied for user root。根因就是 jdbc.properties 里账号密码和本地 MySQL 实际不符合注意密码不能有空格或者被编辑器自动加了引号。解决是打开配置文件确认密码匹配然后重启 Tomcat。现象二JSP 页面中文显示乱码页面标题和健康数据里的中文全部变成问号。根因是连接串没带 characterEncodingutf8或者 JSP 页面顶部没有声明 pageEncoding。解决是两处都检查jdbc.properties 的 url 参数以及每个 JSP 第一行的% page contentTypetext/html;charsetUTF-8 %。现象三启动报 ClassNotFoundExceptionTomcat 启动后抛 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.ymlmybatis 的配置写在 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 这三个文件通读一遍再动代码很多启动不了的问题其实早在这三处就埋下了。希望这篇拆解能帮你把这套个人健康信息管理系统跑起来也祝二次开发顺利。本文还有配套的精品资源点击获取