简介:本资源是一套面向计算机专业本科生的JSP毕业设计实战项目,聚焦企业级人事人力资源管理系统的完整实现,适用于课程设计、毕设选题与Java Web入门进阶学习。项目采用B/S架构,基于JSP+MySQL技术栈开发,涵盖系统管理员、部门管理、员工信息、合同管理、绩效(含工资与奖惩)、考勤六大核心模块,功能完整、结构清晰,具备实际业务映射能力。压缩包共116个文件,包含69个JSP页面(实现前后端交互与业务逻辑)、15个GIF动图(含登录、注册等界面素材)、6个JAR包(支撑运行依赖)、6个JS脚本(增强前端交互)、4个CSS样式文件(如CssAdmin.css等)及1个SQL建库脚本,整体体积仅2.99MB,轻量易部署。目前已有58人学习下载,配套提供详细说明文档与操作录屏,帮助读者快速理解系统流程、掌握MVC分层实践与数据库设计要点,是少有的集源码、文档、演示于一体的高复用毕设参考方案。
1. 这不是又一个“Hello World”JSP项目:它真能跑通员工考勤+绩效+合同全链路,适合Java初学者拿去改毕业设计、交课程设计、搭实训环境
你可能已经点开过十几个标着“JSP人事系统”的压缩包,解压后发现只有 login.jsp 和 index.html,连数据库建表语句都藏在截图里——这次不一样。这个【基于JSP的毕业设计】人事人力资源管理系统,是某高校计算机系近五年被复用率最高的课程设计基线版本:它不炫技,但功能闭环;没用 Spring Boot,却把 JSP + Servlet + JDBC + MySQL 的经典 B/S 架构跑得扎实;所有模块(管理员、部门、员工、合同、绩效、考勤)全部可登录、可增删、可查改,连工资计算逻辑和奖惩记录联动都写在 JavaBean 里。它不是教学演示玩具,而是某导师带学生做实训时真实部署在校内服务器上跑过一整个学期的可用系统。如果你正卡在“毕设选题没方向”“课程设计要交源码但不会写后台”“想练手 Web 开发又怕踩坑到答辩前一周还在调 Tomcat 端口”,这份资源就是为你准备的——它不承诺“零基础秒上线”,但承诺“照着 README 走三遍,你能独立改出自己学院的人事系统”。
2. 从解压到登录:五步走通本地部署全流程,含 Tomcat 9 兼容性适配与 MySQL 8 驱动替换实操
2.1 解压即得完整工程结构:识别核心目录与关键文件作用域
拿到【基于JSP的毕业设计】人事人力资源管理系统(项目源码+说明+录像).zip后,先别急着导入 IDE。用任意解压工具打开,你会看到如下典型 JSP Web 工程结构:
HRMS/ ├── WebContent/ ← JSP、CSS、JS、图片等前端资源根目录 │ ├── css/ ← 包含 style.css、CssAdmin.css、css.css、StyleSheet.css 四个样式表 │ ├── images/ ← 存放 userreg.gif、login.gif、1-1_01_01_01.gif 等界面图标 │ ├── js/ ← (虽未在正文列出,但实际存在)含表单验证、日期控件等 JS 文件 │ ├── WEB-INF/ ← 核心配置与 Java 类存放区 │ │ ├── web.xml ← Servlet 映射、过滤器、欢迎页定义 │ │ ├── classes/ ← 编译后的 .class 文件(含 db.class —— 数据库连接封装类) │ │ └── lib/ ← jar 包目录(重点:mysql-connector-java-5.1.38-bin.jar) │ ├── login.jsp ← 登录入口 │ ├── admin/ ← 管理员模块 JSP 页面集合 │ ├── dept/ ← 部门信息模块 │ ├── emp/ ← 员工信息模块 │ ├── contract/ ← 合同管理模块 │ ├── performance/ ← 绩效管理(含 salary.jsp、reward_punish.jsp) │ └── attendance/ ← 考勤管理 ├── src/ ← (若提供)原始 Java 源码(通常对应 WEB-INF/classes 下的 class) ├── db.sql ← 数据库建表与初始化脚本(关键!必须执行) ├── 项目说明文档.docx ← 功能列表、用户角色、操作流程(非 PDF,是可编辑 Word) └── 操作录像.mp4 ← 实际登录、添加员工、生成考勤报表的全过程录屏(含鼠标轨迹)提示:
db.class是本项目最核心的 JavaBean,封装了getConnection()、executeUpdate()、executeQuery()三个静态方法,所有 DAO 层调用均依赖它。它不是 Spring 的 JdbcTemplate,但胜在轻量、无依赖、可直接阅读源码理解 JDBC 流程。
2.2 数据库准备:MySQL 5.7 兼容建库脚本 + MySQL 8 手动适配要点
项目附带的db.sql是标准 SQL 脚本,内容包含:
- 创建
hrms_db数据库(字符集utf8mb4,排序规则utf8mb4_unicode_ci) - 创建 7 张表:
admin_user(系统管理员)、department(部门)、employee(员工)、contract(合同)、salary(工资)、reward_punish(奖惩)、attendance(考勤) - 插入初始管理员账号:
username='admin',password='123456'(明文存储,仅用于教学)
MySQL 8 用户必做两处修改(否则启动报错):
修改
db.sql中admin_user表的password字段类型
原脚本为VARCHAR(20)→ 改为VARCHAR(100)
原因:MySQL 8 默认认证插件改为caching_sha2_password,密码哈希值更长;而本项目虽用明文,但预留字段长度不足会导致插入失败。替换
WEB-INF/lib/mysql-connector-java-5.1.38-bin.jar为 8.0+ 驱动
下载mysql-connector-java-8.0.33.jar(官方最新稳定版),删除旧 jar,放入lib/目录。
注意:驱动类名已从com.mysql.jdbc.Driver变更为com.mysql.cj.jdbc.Driver,需同步修改db.class中的DRIVER_NAME常量(见 2.3 节)。
2.3 Tomcat 9 部署:解决java.lang.ClassNotFoundException: com.mysql.jdbc.Driver经典报错
这是本项目部署阶段最高频翻车点。现象是:Tomcat 启动成功,但访问login.jsp报 500 错误,日志末尾显示ClassNotFoundException。
根本原因:db.class中硬编码了旧版驱动类名,且未处理 MySQL 8 认证协议变更。
修复步骤(三行代码搞定):
// 打开 WEB-INF/classes/db.class(或 src/db.java,重新编译) // 修改以下三处: private static final String DRIVER_NAME = "com.mysql.cj.jdbc.Driver"; // ← ① 更新驱动类名 private static final String URL = "jdbc:mysql://localhost:3306/hrms_db?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true"; // ← ② 补全连接参数 private static final String USER = "root"; // ← ③ 确认数据库用户名(默认 root) private static final String PASSWORD = "your_mysql8_root_password"; // ← ④ 更新密码(非 '123456'!)逻辑说明:
useSSL=false关闭 SSL(开发环境省事);serverTimezone=Asia/Shanghai解决时区报错;allowPublicKeyRetrieval=true是 MySQL 8.0.23+ 必加参数,否则连接抛Public Key Retrieval is not allowed。这三参数缺一不可,是血泪经验换来的固定模板。
2.4 Eclipse / IDEA 导入与运行:Web Project 配置关键三步
本项目是传统 Dynamic Web Project,非 Maven 工程,导入时需手动指定目标运行时。
Eclipse 操作路径:
File → Import → Web → Existing Web Project → 选择解压后的HRMS/目录 → Next →
✅ 勾选 “Copy project into workspace”(避免路径污染)
✅ 在 “Target runtime” 下拉框中选择已配置的 Tomcat v9.0
→ Finish
IDEA 操作路径:
File → New → Project from Existing Sources → 选择HRMS/→
选择 “Import project as: Web application” → Next →
✅ 在 “Web Application Settings” 中,设置 “Web resource directory” 为WebContent/
✅ 设置 “Web application archive (WAR) name” 为hrms.war
✅ 在 “Libraries” 页签,点击 “+” 添加WEB-INF/lib/下所有 jar(尤其新 mysql-connector)
→ Finish
参数说明:
WebContent/是 JSP 项目的事实标准 WebRoot,IDEA 若误设为src/或根目录,会导致 CSS/JS 404;WEB-INF/lib/必须显式添加,IDEA 不会自动扫描子目录 jar。
2.5 首次登录验证:绕过前端校验直击后端逻辑链
不要只信login.jsp的表单提交。为快速验证后端是否真正联通,建议用 Postman 或 curl 直接调用登录 Servlet:
curl -X POST "http://localhost:8080/hrms/loginCheck" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "username=admin" \ -d "password=123456"预期返回:HTTP 302 重定向到admin/index.jsp(说明loginCheckServlet 成功执行,数据库查询命中)。
若返回 500,则检查db.class的URL是否拼写错误、MySQL 服务是否运行、hrms_db是否已创建。
注意:
loginCheck是web.xml中定义的 Servlet 映射名,对应LoginServlet.java(位于src/或WEB-INF/classes/),其核心逻辑是调用db.class.executeQuery("SELECT * FROM admin_user WHERE username=? AND password=?")—— 这就是本项目最朴实也最可靠的 JDBC 实战范例。
3. 功能模块拆解:六个业务域如何用 JSP+JavaBean 实现数据联动,含绩效工资计算与考勤状态机逻辑
3.1 系统管理员模块:权限控制的朴素实现与安全边界
本项目未引入 Shiro 或 Spring Security,权限靠 Session + URL 拦截实现:
- 所有
/admin/*、/dept/*等路径的 JSP 页面顶部均有统一校验:<% if(session.getAttribute("admin") == null) { response.sendRedirect("../login.jsp"); return; } %> LoginServlet登录成功后,将管理员对象存入 Session:session.setAttribute("admin", admin); // admin 是 AdminUser 类实例- 注销逻辑在
logout.jsp中:session.invalidate(); response.sendRedirect("login.jsp");
提示:这种 Session 校验方式简单有效,但存在会话劫持风险。课程设计阶段足够,毕设答辩时可补充说明“后续可升级为 Token 认证”,体现演进思维。
3.2 部门与员工信息模块:一对多关系的 JSP 表单绑定实践
dept/list.jsp展示部门列表,每行有“编辑”“删除”按钮,点击后跳转dept/edit.jsp?id=1。关键点在于:
edit.jsp使用<%= request.getParameter("id") %>获取 ID,再调用db.class.executeQuery("SELECT * FROM department WHERE id=" + id)查询详情;- 表单
<form action="DeptServlet" method="post">提交到DeptServlet,其doPost()方法根据request.getParameter("action")判断是add、update还是delete; - 员工信息模块 (
emp/) 同理,但增加外键约束:employee.dept_id关联department.id,在emp/add.jsp的部门下拉框中,动态生成:<select name="deptId"> <% ResultSet rs = db.executeQuery("SELECT id, dept_name FROM department"); while(rs.next()) { %> <option value="<%= rs.getInt("id") %>"><%= rs.getString("dept_name") %></option> <% } %> </select>
注意:此处未使用 EL 表达式或 JSTL,纯 JSP Scriptlet,符合 Java Web 初级教学定位。
rs.getInt("id")直接输出整型,避免字符串拼接 SQL 注入——这是本项目少有的安全意识体现。
3.3 合同信息管理:时间范围校验与状态字段设计
contract/模块包含start_date、end_date、status(0=待生效,1=履行中,2=已终止)三个关键字段。其业务逻辑体现在ContractServlet中:
- 新增合同时,强制校验
start_date <= end_date,否则request.setAttribute("error", "结束日期不能早于开始日期")并转发回add.jsp; - 状态变更由定时任务或人工触发(本项目为人工),
updateStatus.jsp提供按钮调用ContractServlet?action=updateStatus&id=123&status=1; list.jsp中用颜色区分状态:<td> <% String status = rs.getString("status"); String color = "gray"; if("1".equals(status)) color = "green"; if("2".equals(status)) color = "red"; %> <span style="color:<%= color %>"><%= "0".equals(status)?"待生效":"1".equals(status)?"履行中":"已终止" %></span> </td>
提示:
status字段用数字而非字符串,节省存储且便于程序判断;颜色标记是 UI 层增强,不侵入业务逻辑,符合分层思想。
3.4 绩效管理:工资计算公式与奖惩记录的双向联动
绩效模块是本项目技术亮点,包含两个子模块:
| 子模块 | 核心逻辑 | 关键文件 |
|---|---|---|
工资管理(salary/) | 基础工资 + 绩效奖金 + 补贴 - 扣款 = 实发工资;绩效奖金取自performance_score字段 | salary/list.jsp,SalaryServlet.java |
奖惩记录(reward_punish/) | 每条记录关联employee_id,type=1为奖励,type=2为惩罚;amount字段影响当月工资 | reward_punish/add.jsp,RewardPunishServlet.java |
联动机制:SalaryServlet在计算salary表时,会执行:
SELECT SUM(CASE WHEN type=1 THEN amount ELSE 0 END) AS reward_total, SUM(CASE WHEN type=2 THEN amount ELSE 0 END) AS punish_total FROM reward_punish WHERE employee_id = ? AND month = ?然后将reward_total - punish_total加入绩效奖金项。
注意:此设计将奖惩作为工资计算的输入因子,而非独立报表,体现业务耦合性。若需解耦,可将
reward_punish表的amount字段改为points(积分制),再通过规则引擎映射为金额——这是进阶改造点。
3.5 考勤管理:状态机驱动的每日打卡与异常标记
attendance/模块采用“日期+员工ID”复合主键,每条记录代表某员工某日的考勤状态:
| 字段 | 类型 | 说明 |
|---|---|---|
date | DATE | 考勤日期(如 '2023-09-01') |
emp_id | INT | 员工 ID |
status | TINYINT | 0=缺勤,1=正常,2=迟到,3=早退,4=请假,5=出差 |
remark | VARCHAR(200) | 请假/出差事由 |
AttendanceServlet的checkIn()方法逻辑:
String today = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); String sql = "INSERT INTO attendance (date, emp_id, status, remark) VALUES (?, ?, ?, ?) " + "ON DUPLICATE KEY UPDATE status = VALUES(status), remark = VALUES(remark)"; // 使用 INSERT ... ON DUPLICATE KEY UPDATE 避免重复打卡报错提示:
ON DUPLICATE KEY UPDATE是 MySQL 特有语法,替代了先查后插的繁琐逻辑,是本项目少有的高级 SQL 实践。status字段用整型枚举,前端用 switch 渲染中文,保持数据一致性。
4. 避坑指南:五个真实部署与调试场景中的致命陷阱,含 Tomcat 日志定位法与 JSP 编译错误速查
4.1 现象:页面中文乱码(如“管理员”显示为“管ç†å”)
原因:JSP 页面未声明字符集,且 Tomcat 默认 ISO-8859-1 解析请求参数。
解决:
① 所有 JSP 顶部添加<%@ page contentType="text/html;charset=UTF-8" %>;
②web.xml中添加过滤器(若未提供,手动新建CharacterEncodingFilter.java):
<filter> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>注意:即使不用 Spring,也可手写简易 Filter,但本项目为简化,推荐直接在每个 Servlet 的
doPost()开头加request.setCharacterEncoding("UTF-8")。
4.2 现象:登录后跳转admin/index.jsp显示 404
原因:web.xml中<welcome-file-list>未配置index.jsp,或admin/目录下无index.jsp。
解决:
① 检查WebContent/admin/目录是否存在index.jsp(本项目有);
② 检查web.xml是否有:
<welcome-file-list> <welcome-file>login.jsp</welcome-file> </welcome-file-list>→ 此配置仅影响根路径访问,不影响重定向。真正关键的是LoginServlet中的response.sendRedirect("admin/index.jsp"),路径必须与实际文件位置严格一致(区分大小写!)。
4.3 现象:添加员工时报java.sql.SQLException: Field 'xxx' doesn't have a default value
原因:MySQL 严格模式(STRICT_TRANS_TABLES)启用,而employee表中entry_date、phone等字段设为NOT NULL但未提供默认值,且表单未提交这些字段。
解决:
① 临时关闭严格模式(开发环境):在 MySQL 配置文件my.cnf的[mysqld]下添加sql_mode=NO_ENGINE_SUBSTITUTION;
② 或修改建表语句,为非空字段加默认值:
ALTER TABLE employee MODIFY entry_date DATE DEFAULT '1970-01-01'; ALTER TABLE employee MODIFY phone VARCHAR(20) DEFAULT '';4.4 现象:db.class编译报错cannot find symbol: variable rs
原因:db.class是编译后的字节码,无法直接编辑。你看到的db.class是反编译产物,缺少源码注释与结构。
解决:
① 删除WEB-INF/classes/db.class;
② 用记事本新建src/db.java,粘贴反编译出的 Java 代码(网上搜 “java decompiler online” 上传 class 文件即可);
③ 按 2.3 节修改驱动类名与 URL;
④ 在 IDE 中编译src/db.java,生成新db.class放入classes/。
血泪经验:永远保留
src/目录,.class文件只是中间产物。本项目未提供src/是最大短板,必须自行补全。
4.5 现象:Tomcat 启动后控制台疯狂刷SEVERE: Error filterStart
原因:web.xml中某个<filter>的filter-class类路径错误,或该类依赖的 jar 缺失。
排查法:
① 查看 Tomcatlogs/catalina.out,找到Caused by:后的第一行异常;
② 若是ClassNotFoundException: com.xxx.FilterClass,检查WEB-INF/lib/是否有对应 jar;
③ 若是NoClassDefFoundError: javax/servlet/Filter,说明 Tomcat 版本与 Servlet API 不匹配(本项目需 Servlet 3.1,Tomcat 8+ 满足)。
提示:
SEVERE: Error filterStart是 Tomcat 7+ 的经典报错,99% 源于配置错误,而非代码 bug。
5. 毕设级改造技巧:三处低成本高价值优化,让答辩老师眼前一亮
5.1 将明文密码升级为 BCrypt 加密:两小时完成的安全加固
当前系统密码明文存储(admin_user.password = '123456'),答辩时老师必问安全性。升级为 BCrypt 只需四步:
Step 1:引入 BCrypt 依赖
下载bcrypt-3.1.jar,放入WEB-INF/lib/。
Step 2:修改LoginServlet.java登录逻辑
// 原逻辑(明文比对): // if(password.equals(dbPassword)) { ... } // 新逻辑(BCrypt 验证): if(BCrypt.checkpw(password, dbPassword)) { // dbPassword 从数据库读出的 $2a$10$... 字符串 session.setAttribute("admin", admin); response.sendRedirect("admin/index.jsp"); } else { request.setAttribute("error", "用户名或密码错误"); request.getRequestDispatcher("../login.jsp").forward(request, response); }Step 3:修改AdminServlet.java注册/修改密码逻辑
String hashedPassword = BCrypt.hashpw(newPassword, BCrypt.gensalt(10)); // 执行 UPDATE admin_user SET password = ? WHERE id = ?Step 4:批量加密现有密码
写一个临时 JSP(如encrypt.jsp),循环查询admin_user,对每条记录执行BCrypt.hashpw(oldPass, BCrypt.gensalt(10)),再 UPDATE 回库。
价值点:BCrypt 是行业标准密码哈希算法,
gensalt(10)表示 2^10 次哈希迭代,答辩时可解释“为何不用 MD5/SHA1”,展现安全意识。全程无需改数据库字段类型(BCrypt 输出固定 60 字符),兼容性完美。
5.2 为考勤模块添加月度统计报表:用原生 JDBC 实现聚合查询
attendance/当前只有明细列表,缺乏管理视图。新增attendance/monthlyReport.jsp,展示某部门某月出勤率:
<!-- 月份选择表单 --> <form action="MonthlyReportServlet" method="post"> <select name="deptId"> <!-- 动态加载部门 --> </select> <input type="month" name="month" value="2023-09"> <button type="submit">生成报表</button> </form> <!-- 报表表格 --> <table> <tr><th>员工姓名</th><th>应出勤天数</th><th>实际出勤天数</th><th>出勤率</th></tr> <% ResultSet rs = db.executeQuery( "SELECT e.name, " + " COUNT(*) as total_days, " + " SUM(CASE WHEN a.status IN (1,2,3) THEN 1 ELSE 0 END) as present_days " + "FROM employee e " + "LEFT JOIN attendance a ON e.id = a.emp_id AND a.date LIKE ? " + "WHERE e.dept_id = ? " + "GROUP BY e.id, e.name" ); while(rs.next()) { int total = rs.getInt("total_days"); int present = rs.getInt("present_days"); double rate = total > 0 ? (double) present / total * 100 : 0; %> <tr> <td><%= rs.getString("name") %></td> <td><%= total %></td> <td><%= present %></td> <td><%= String.format("%.1f%%", rate) %></td> </tr> <% } %> </table>关键点:
a.date LIKE ?参数传入"2023-09%",利用 MySQL 的字符串匹配替代日期函数,降低学习成本;LEFT JOIN确保无考勤记录的员工也出现在报表中(total_days=0),体现数据完整性思维。
5.3 录像剪辑与文档重写:让毕设材料具备“交付物”质感
很多同学交毕设只扔一个 ZIP,老师第一印象就扣分。我一般会强制做三件事:
录像剪辑:用免费软件(如 Shotcut)裁掉操作录像中 3 秒以上的停顿、误操作重来片段,保留“登录 → 添加部门 → 添加员工 → 生成考勤报表”主线,总时长压到 3 分钟内,开头加文字标题:“XX大学计算机系毕设:基于JSP的人力资源管理系统演示”。
文档重写:将原
项目说明文档.docx重构为三部分:- 第一章 系统概述:用 Mermaid 画一个极简架构图(文字描述即可:“浏览器 → JSP/Servlet → db.class → MySQL”);
- 第二章 功能清单:表格化,列“模块名|子功能|技术实现要点|截图位置(录像时间戳)”;
- 第三章 部署手册:精确到命令行,如“1. 解压至 D:\HRMS;2. 执行 db.sql 创建数据库;3. 修改 db.class 第12行 URL;4. Eclipse 导入时 Runtime 选 Tomcat v9.0”。
源码注释补全:在
db.class、LoginServlet.java等关键类顶部,用/** */写明作者、版本、用途,例如:/** * db.class: 数据库连接工具类(v1.2) * 作者:某高校计算机系课程设计基线版本 * 功能:封装 getConnection()、executeQuery()、executeUpdate() 三个静态方法 * 注意:MySQL 8+ 需修改 DRIVER_NAME 与 URL 参数 */
从那以后我每次交毕设,都强制走一遍这三步——不是为了应付,而是让三年后回头看,能清晰还原当时的技术决策链条。希望帮到你。
本文还有配套的精品资源,点击获取