Java健康管理系统毕业设计:基于Servlet与MySQL的Web开发实践

发布时间:2026/9/20 9:35:36
Java健康管理系统毕业设计:基于Servlet与MySQL的Web开发实践 简介一套完整的《基于Java的健康管理系统》毕业设计项目包面向计算机相关专业需要完成Java方向毕设或系统学习健康管理类Web开发的学生与开发者。包内整合了项目报告、开题报告、答辩PPT、源代码、数据库及部署视频覆盖从需求分析、系统设计、编码实现到测试部署的完整流程。压缩包约143.18MB内部文件数量未单独统计主要文件类型包括Java后端源码、SQL数据库脚本、Word项目文档、PPT演示文稿及mp4部署操作视频基本可一包解决毕设选题、文档撰写和答辩展示需求。目前已有1267人学习下载。通过学习该资源用户可以对照报告理解MVC架构、JDBC/MyBatis数据访问、RESTful API、安全认证等关键知识点同时依据视频完成本地环境搭建与系统运行节省大量摸索时间。1. 基于 Java 的健康管理系统毕业设计项目包到底能学到什么大多数健康管理类的课程设计最后都死在同一个地方数据库连接串配错。这份基于 Java 的健康管理系统毕业设计包恰好把这一整套容易翻车的环节——SQL 脚本、JDBC 连接、Tomcat 部署、答辩材料——全部整理在一起。它不追求微服务和高并发而是用最直接的 JSP Servlet MySQL 组合把用户注册登录、健康档案录入、体检数据查询这些核心业务走通。适合正在做毕业设计、需要在一个月内拿出一套可演示项目的学生也适合想快速回顾 Java Web 经典分层开发的在职工程师。项目报告和答辩 PPT 里把需求分析、ER 图、测试用例都补齐了拿来改一改就能应对数据库课程设计的文档要求。2. 从需求到表结构MVC 架构与健康数据的 MySQL 建模2.1 为什么是 MVC把业务、界面和数据访问拆开健康管理系统最常见的功能边界是用户注册登录、维护个人档案、录入血压/血糖/心率等指标、查看历史趋势。如果全写在 JSP 里项目能跑但没法答辩——评审问一句“如果换数据库怎么办”就卡住。老实的做法是 MVCJSP 只做视图Servlet 负责接收请求和转发Service 层处理业务规则DAO 层用 JDBC 访问 MySQL。这种分层带来的直接好处是你可以单独测试 DAO 层而不用打开浏览器。对于课程设计MVC 还有一层现实意义开题报告里的“系统设计”一章有东西可写。把上面的关系画成结构图再配合 ER 图数据库课程设计里的概念模型就完整了。很多人的 ER 图画得混乱本质是没分清用户、健康档案、健康记录三者的关系。在健康管理场景里用户和健康记录就是经典的一对多关系不需要为了展示“高级”强行拆出中间表。2.2 用户表与健康记录表的字段设计设计表结构前先明确两个核心实体用户和健康记录。用户表保存登录账号和基本信息健康记录表保存每次测量的身体指标。字段类型要控制好体重用 DECIMAL 而不是 FLOAT避免精度漂移测量时间用 DATETIME查询区间时能走索引。字段名类型约束说明user_idINT主键自增用户IDusernameVARCHAR(50)唯一非空登录账号passwordVARCHAR(100)非空加密后的密码real_nameVARCHAR(50)非空姓名ageINT允许空年龄phoneVARCHAR(20)允许空手机号record_idINT主键自增记录IDuser_idINT外键关联用户heightDECIMAL(5,2)无身高(cm)weightDECIMAL(5,2)无体重(kg)blood_pressureVARCHAR(20)无血压如 120/80heart_rateINT无心率measure_timeDATETIME索引测量时间这里没有把健康档案单独拆表因为课程设计的数据量很小一张 t_health_record 表承载录入和查询足够。如果你想在答辩里展示“第三范式”的功课可以把年龄字段改成出生日期让年龄通过计算得出。这属于简单但有效的数据库设计优化也是 ER 图里实体划分的加分项。2.3 用 SQL 脚本初始化数据库项目包里的 database 目录通常放的是 .sql 脚本。我一般建议用 MySQL 5.7 或 8.0字符集统一 utf8mb4避免中文乱码。以下是建表和基础数据的常见做法CREATE DATABASE IF NOT EXISTS health_manage DEFAULT CHARACTER SET utf8mb4; USE health_manage; CREATE TABLE t_user ( user_id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(100) NOT NULL, real_name VARCHAR(50) NOT NULL, age INT, phone VARCHAR(20), create_time DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB; CREATE TABLE t_health_record ( record_id INT AUTO_INCREMENT PRIMARY KEY, user_id INT NOT NULL, height DECIMAL(5,2), weight DECIMAL(5,2), blood_pressure VARCHAR(20), heart_rate INT, measure_time DATETIME, CONSTRAINT fk_user FOREIGN KEY (user_id) REFERENCES t_user(user_id) ) ENGINEInnoDB; CREATE INDEX idx_measure_time ON t_health_record(measure_time);上述脚本里ENGINEInnoDB保证外键约束和事务支持这在批量导入健康记录时很重要。fk_user外键保证不会出现指向不存在用户的记录。idx_measure_time索引用于后面按日期范围查询历史数据数据量过万后性能差异会很明显。如果直接使用项目包里的数据库文件注意导入时先创建库再导入表否则会因为缺少数据库上下文报错。Navicat 或命令行mysql -u root -p health_manage health.sql都可以两种方式在部署视频里通常都有演示。3. 登录认证与健康数据 CRUDServlet/RESTful 接口落地实现3.1 Session 登录与密码加密登录是第一个要写对的模块。最常见的问题是密码明文存入数据库这在毕业设计答辩里会被直接扣分。合理做法是使用 MD5 加盐或 BCrypt。考虑到 Java 标准库不带 BCrypt我会选择 MD5 加盐虽然强度有限但课程设计足够代码也容易解释。工具类中保存盐值注册时生成密文。public class Md5Util { private static final String SALT health_2024; public static String encrypt(String password) { String value SALT password; for (int i 0; i 3; i) { value DigestUtils.md5Hex(value.getBytes(StandardCharsets.UTF_8)); } return value; } }DigestUtils.md5Hex来自 Apache Commons Codec项目包里通常已经引入 jar。这里的盐值不要硬编码实际部署时放在配置文件中。三次迭代只增加少量时间但能让彩虹表攻击的成本明显上升。登录 Servlet 的核心逻辑是取出表单参数调用 DAO 查询用户用同样的加密算法比对密文成功后把 user_id 和 username 放进 session。WebServlet(/login) public class LoginServlet extends HttpServlet { protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String username req.getParameter(username); String password Md5Util.encrypt(req.getParameter(password)); User user userDao.findByUsername(username); if (user ! null user.getPassword().equals(password)) { HttpSession session req.getSession(); session.setAttribute(userId, user.getUserId()); session.setAttribute(username, user.getUsername()); resp.sendRedirect(index.jsp); } else { req.setAttribute(error, 用户名或密码错误); req.getRequestDispatcher(login.jsp).forward(req, resp); } } }req.getParameter获取 HTTP 请求参数sendRedirect是重定向避免刷新页面重复提交登录。如果项目采用了前后端分离这里可以改为返回 JSON 状态码比如登录成功返回{code:200,token:...}。JWT 的实现我们放到第 5 章讲。3.2 健康记录录入的 Servlet 实现健康数据的录入涉及多个字段参数校验在 Service 层做而不是在 Servlet 里写一大堆 if。下面这个接口同时展示参数接收和插入动作WebServlet(/record/add) public class RecordAddServlet extends HttpServlet { protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding(utf-8); HealthRecord record new HealthRecord(); record.setUserId(Integer.parseInt(req.getParameter(userId))); record.setHeight(new BigDecimal(req.getParameter(height))); record.setWeight(new BigDecimal(req.getParameter(weight))); record.setBloodPressure(req.getParameter(bloodPressure)); record.setHeartRate(Integer.parseInt(req.getParameter(heartRate))); record.setMeasureTime(new Date()); HealthRecordService service new HealthRecordService(); boolean ok service.addRecord(record); if (ok) { resp.sendRedirect(record/list?userId record.getUserId()); } else { req.setAttribute(error, 保存失败); req.getRequestDispatcher(record/add.jsp).forward(req, resp); } } }注意req.setCharacterEncoding(utf-8)必须放在读取任何参数之前否则中文姓名或备注会乱码。BigDecimal接收 height 和 weight是因为数据库字段用 DECIMAL不是所有浏览器都会传合法数字Service 层还需要做非空和范围校验。3.3 查询接口与分页参数查询列表一般需要分页。小项目里常见做法是参数带上pageNum和pageSizeDAO 层用LIMIT #{offset}, #{pageSize}拼接查询。下面是一张常用的接口约定表接口路径方法参数说明/loginPOSTusername,password用户登录/user/registerPOSTusername,password,realName注册/record/addPOSTuserId,height,weight,bloodPressure,heartRate新增健康记录/record/listGETuserId,pageNum,pageSize分页查询记录/record/deleteGET/POSTrecordId删除一条记录分页查询的 Servlet 里把计算 offset 的逻辑放在 Service 层避免在 JSP 里写公式。下面是在 DAO 中执行查询的关键片段public ListHealthRecord findByUserId(int userId, int pageNum, int pageSize) { String sql SELECT * FROM t_health_record WHERE user_id ? ORDER BY measure_time DESC LIMIT ?, ?; int offset (pageNum - 1) * pageSize; // 使用 PreparedStatement 设置参数防止 SQL 注入 }PreparedStatement的参数占位符能避免拼接字符串导致的注入风险。很多毕业设计答辩必问“如何防止 SQL 注入”能讲清楚这一条基本就过关了。如果题目换成可以和 MySQL、Oracle 自由切换那就要引入 MyBatis 或 Hibernate 处理方言差异这也是项目包里为什么保留不同版本数据访问代码的原因。4. 页面渲染与 Tomcat 部署Bootstrap 前端、数据库初始化与配置检查4.1 JSP Bootstrap 表格模板前端页面用 JSP 加 Bootstrap能最快搭建出过得去的后台界面。资源包里大多数页面是这种风格顶部导航栏左侧菜单右侧内容区。健康记录列表页的关键在表格渲染和日期格式化。% page contentTypetext/html;charsetUTF-8 pageEncodingUTF-8 % % taglib prefixc urihttp://java.sun.com/jsp/jstl/core % table classtable table-bordered table-hover thead tr th身高(cm)/thth体重(kg)/thth血压/thth心率/thth测量时间/th /tr /thead tbody c:forEach items${recordList} varr tr td${r.height}/td td${r.weight}/td td${r.bloodPressure}/td td${r.heartRate}/td tdfmt:formatDate value${r.measureTime} patternyyyy-MM-dd HH:mm//td /tr /c:forEach /tbody /table${r.healthRecord}实际是 EL 表达式访问 JavaBean 的 getter。fmt:formatDate需要在 JSP 顶部引入 JSTL fmt 标签库否则日期会显示为默认的时间戳格式。很多同学把时间字段直接输出成2024-12-01 21:30:00.0就是遗漏了这个标签。4.2 Tomcat 部署前要检查的配置文件部署到 Tomcat 之前先确认三样东西JDK 版本、Tomcat 版本、MySQL 驱动。项目包里的部署视频一般会演示用 IntelliJ IDEA 2023 或 Eclipse 导入项目然后配置 Artifact。这里有一个高频错误MySQL 驱动 jar 没有放进WEB-INF/lib导致启动时找不到驱动类。检查项建议配置常见错误JDK8 或 11高版本 JDK 下 JSP 编译报错Tomcat8.5/9.x端口被占用MySQL5.7/8.0认证插件导致连接失败MySQL Connector/J5.1.49 或 8.0.x版本与 MySQL 不匹配如果是 MySQL 8.0驱动类名要写com.mysql.cj.jdbc.DriverURL 中需要加serverTimezoneAsia/Shanghai。我用的是下面这个 db.properties 模板jdbc.drivercom.mysql.cj.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/health_manage?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai jdbc.usernameroot jdbc.password1234564.3 部署视频里没细讲的常见坑第一个坑是数据库连接池未释放。有些示例代码在 DAO 里只用Connection不写finallyTomcat 跑半小时后连接池耗尽页面卡死。即使课程设计也要养成 try-with-resources 的习惯。第二个坑是 JSP 页面上的静态资源 404。Bootstrap 的 css 和 js 路径建议写成${pageContext.request.contextPath}拼 absolute path不要用相对路径否则从/login转发到index.jsp后样式全丢。第三个坑是端口冲突。Tomcat 默认 8080如果本机已占直接改conf/server.xml里的Connector port8080。查端口占用用netstat -ano | findstr 8080或lsof -i:8080不要反复重启 tomcat 浪费时间。5. 加分项JWT 无状态认证与健康预警规则改造5.1 把 Session 换成 JWT撑起架构话题答辩时如果只讲 JSP Servlet上限就是“代码完整、能跑”很难往架构方向展开。JWT 是一个安全的延伸点服务端不保存会话token 里直接携带用户信息适合扩展为真正的 RESTful 前后端分离。生成代码常用 jjwt 库以下片段可以直接接到登录接口后String token Jwts.builder() .setSubject(String.valueOf(user.getUserId())) .claim(username, user.getUsername()) .setExpiration(new Date(System.currentTimeMillis() 30 * 60 * 1000)) .signWith(SignatureAlgorithm.HS256, secretKey) .compact();setSubject存放用户主键claim放非敏感信息过期时间设置为 30 分钟。secretKey建议单独写进配置文件放在源码里会让整个认证形同虚设。前端拿到 token 后放进 HTTP 请求头拦截器里解析并校验签名这就是最简化的 JWT 登录流程。5.2 用规则表驱动健康预警另一个容易出彩的功能是健康预警。不要在每个 Servlet 里写死“心率大于 100 就报警”而是把阈值放到规则表。记录写入前Service 层读取规则并判断是否越界有异常则生成提醒消息。public boolean isAbnormal(HealthRecord record) { HealthRule rule ruleDao.findByRuleName(heart_rate); return record.getHeartRate() rule.getUpperValue(); }这样做的价值在于预警阈值调整不需要改代码和重新部署直接在数据库里更新t_health_rule表即可。配合项目报告里的“系统扩展”章节能说明白数据驱动业务规则的设计思路。在答辩演示时先跑普通录入再打开规则表把上限调低重新提交数据触发预警比口头解释直观得多。本文还有配套的精品资源点击获取