简介:这份资源是面向高校计算机相关专业学生与Java Web初学者的人事人力资源管理系统毕业设计完整项目包,基于JSP+MySQL+B/S架构开发,适合用作课程设计、毕业设计参考或项目实战练手。系统功能覆盖系统管理员、部门信息、员工信息、合同信息、绩效管理(含员工工资与奖惩记录)以及考勤管理等多个模块,业务逻辑较为完整。压缩包共116个文件,以69个JSP页面为主体,配合6个JS脚本、4个CSS样式表、15个GIF与5个JPG界面素材,另有6个JAR依赖包、1个SQL建库脚本及项目配置文件,整体约2.99MB,结构清晰便于二次开发。资源内附项目说明文档与操作录像,可帮助读者快速理解数据库设计、页面跳转逻辑与各模块实现思路,对照源码完成环境搭建与功能调试。目前已有58人学习下载,适合需要完整赛题方案与排错参考的读者。
1. 基于JSP的人事人力资源管理系统:从源码到跑通,一个毕业设计项目的完整落地路径
很多计算机毕业设计选题里,基于JSP的人事人力资源管理系统算是出现频率最高的一类。原因不复杂:业务逻辑直观,功能模块清晰,技术栈成熟,答辩时容易讲清楚。但真正拿到一份项目源码之后,能在本地跑通、能改出自己需要的样子、能在答辩时说出所以然的人,其实不多。我见过太多人卡在环境配置、数据库连接、Tomcat版本不匹配这些看似简单的地方,最后只能照搬别人的截图交差。这篇内容面向的是拿到类似项目源码后想真正跑通、理解并做二次开发的人,从环境搭建、数据库导入、核心模块拆解到常见报错排查,按可复现的路径走一遍。如果你正在做计算机毕业设计,选的又是JSP方向,这套流程可以直接抄作业。
2. 环境搭建与项目导入:把源码跑起来的第一步
2.1 JDK、Tomcat、MySQL的版本选择与安装顺序
拿到一个JSP项目源码,第一件事不是急着导入IDE,而是先把运行环境对齐。JSP项目对版本比较敏感,尤其是Tomcat和JDK的搭配。常见做法是:JDK用1.8,Tomcat用8.5或9.0,MySQL用5.7或8.0。为什么不用JDK 11以上?因为很多老项目的JSP页面里用了javax.servlet包,而Tomcat 10之后改成了jakarta.servlet,包名一变,项目直接报ClassNotFoundException。这是血泪经验,不是理论推测。
安装顺序建议:先装JDK,配好JAVA_HOME和Path;再装MySQL,设好root密码;最后解压Tomcat,不需要安装,解压即可用。IDE用Eclipse或IntelliJ IDEA都行,Eclipse对老JSP项目兼容性更好,IDEA的智能提示更强,看个人习惯。
验证环境是否就绪,打开命令行执行:
java -version # 应输出 java version "1.8.0_xxx" mysql --version # 应输出 mysql Ver 14.14 Distrib 5.7.xx 或 8.0.xx # Tomcat解压目录下执行 ./bin/startup.sh # Linux/Mac bin\startup.bat # Windows启动后浏览器访问http://localhost:8080,看到Tomcat默认页就说明容器没问题。这一步看起来简单,但很多人卡在端口占用上。8080被占用的概率很高,改conf/server.xml里的Connector端口即可。
2.2 数据库导入与连接配置的四个关键参数
项目源码里通常会带一个.sql文件,这就是数据库备份。导入之前先建库:
CREATE DATABASE hrms DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE hrms; SOURCE /path/to/hrms.sql;注意字符集用utf8mb4而不是utf8,因为员工姓名、备注字段里可能出现生僻字或特殊符号,utf8在三字节以上的字符会报错。导入完成后用SHOW TABLES;确认表都进去了。
接下来改项目里的数据库连接配置。JSP项目一般有两种方式:一种是在src目录下放db.properties或c3p0-config.xml,另一种是直接在Java类里硬编码。找到配置文件后,重点改四个参数:
| 参数 | 说明 | 常见值 |
|---|---|---|
| driver | JDBC驱动类名 | com.mysql.jdbc.Driver(5.x)或 com.mysql.cj.jdbc.Driver(8.x) |
| url | 连接地址 | jdbc:mysql://localhost:3306/hrms?useUnicode=true&characterEncoding=utf8 |
| username | 数据库用户名 | root |
| password | 数据库密码 | 你设置的密码 |
MySQL 8.0的驱动类名和URL参数跟5.x有区别,如果项目用的是5.x的驱动包,连8.0的数据库会报Unknown system variable 'query_cache_size'之类的错。解决办法是换驱动包,或者把数据库降级到5.7。我一般建议直接换驱动包,因为8.0的性能和安全性更好。
2.3 在Eclipse/IDEA中导入并部署到Tomcat
Eclipse导入步骤:File → Import → Existing Projects into Workspace → 选择项目根目录 → Finish。导入后如果项目图标上有红叉,大概率是JRE版本不对,右键项目 → Properties → Java Build Path → Libraries → 把JRE System Library改成1.8。
IDEA导入步骤:File → Open → 选择项目根目录 → 如果提示不是Maven项目就选“Import as Eclipse project”。然后在Project Structure里把SDK设成1.8,在Facets里确认Web模块的web.xml路径正确。
部署到Tomcat:Eclipse里右键项目 → Run As → Run on Server → 选择Tomcat实例。IDEA里在Run/Debug Configurations里加一个Tomcat Local,把Artifact加进去。启动后访问http://localhost:8080/项目名/,如果看到登录页,说明部署成功。
这一步最容易翻车的地方是web.xml版本和Servlet API不匹配。如果启动时报The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved,说明缺JSTL标签库的jar包,去下载jstl.jar和standard.jar放到WEB-INF/lib下即可。
3. 核心功能模块拆解:人事系统到底在管什么
3.1 员工信息CRUD:从表结构到JSP页面的数据流
人事人力资源管理系统的核心就是员工信息的增删改查。先看表结构,通常至少有这么几张表:employee(员工基本信息)、department(部门)、position(职位)、salary(薪资)、attendance(考勤)。employee表的关键字段包括:emp_id、emp_name、gender、birth_date、id_card、phone、email、dept_id、position_id、hire_date、status。
数据流是这样的:JSP页面表单提交 → Servlet接收请求 → 调用Service层 → DAO层执行SQL → 返回结果 → Servlet转发到JSP展示。以新增员工为例,Servlet里的核心代码:
// EmployeeServlet.java 中的 doPost 方法片段 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); // 防止中文乱码 String empName = request.getParameter("empName"); String gender = request.getParameter("gender"); String phone = request.getParameter("phone"); String deptId = request.getParameter("deptId"); Employee emp = new Employee(); emp.setEmpName(empName); emp.setGender(gender); emp.setPhone(phone); emp.setDeptId(Integer.parseInt(deptId)); EmployeeService service = new EmployeeServiceImpl(); boolean result = service.addEmployee(emp); if (result) { response.sendRedirect("employee?action=list"); // 重定向到列表页 } else { request.setAttribute("msg", "添加失败"); request.getRequestDispatcher("/error.jsp").forward(request, response); } }这段代码里有两个关键点:request.setCharacterEncoding("UTF-8")必须放在获取参数之前,否则中文姓名会乱码;sendRedirect和forward的区别要搞清楚,重定向会改变URL,转发不会。列表页用JSTL的<c:forEach>遍历:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <table> <tr><th>工号</th><th>姓名</th><th>部门</th><th>操作</th></tr> <c:forEach items="${empList}" var="emp"> <tr> <td>${emp.empId}</td> <td>${emp.empName}</td> <td>${emp.deptName}</td> <td> <a href="employee?action=edit&id=${emp.empId}">编辑</a> <a href="employee?action=delete&id=${emp.empId}" onclick="return confirm('确认删除?')">删除</a> </td> </tr> </c:forEach> </table><c:forEach>的items属性对应request或session里的集合,var是循环变量。删除操作加onclick确认框是基本操作,防止误删。
3.2 部门与职位管理:树形结构的表设计与递归查询
部门表通常是自关联的,dept_id是主键,parent_id指向上级部门。这种设计支持无限层级,但查询时需要递归。MySQL 8.0可以用CTE(公用表表达式)递归查询:
WITH RECURSIVE dept_tree AS ( SELECT dept_id, dept_name, parent_id, 1 AS level FROM department WHERE parent_id IS NULL UNION ALL SELECT d.dept_id, d.dept_name, d.parent_id, dt.level + 1 FROM department d INNER JOIN dept_tree dt ON d.parent_id = dt.dept_id ) SELECT * FROM dept_tree ORDER BY level, dept_id;MySQL 5.7不支持CTE,就得在Java层递归。常见做法是先把所有部门查出来放到List里,然后在Service层用递归方法组装成树形结构。这种写法在数据量不大时完全够用,几百个部门以内性能没问题。
JSP页面展示树形结构可以用递归JSP或者前端框架。如果项目里用了jQuery,可以用zTree插件,把后端返回的JSON数据直接渲染成树。如果不想引入额外插件,用嵌套的<ul>和<li>配合递归JSP片段也能实现,但代码会啰嗦一些。
3.3 考勤与薪资计算:定时任务与批量处理的实现思路
考勤模块通常需要每天定时统计,比如晚上12点跑一次批处理,把当天的打卡记录汇总。Java里可以用Timer或ScheduledExecutorService,但更规范的做法是用Quartz框架。如果项目里没引入Quartz,用ScheduledExecutorService也够:
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); scheduler.scheduleAtFixedRate(() -> { // 每天凌晨1点执行考勤汇总 AttendanceService service = new AttendanceServiceImpl(); service.summarizeDailyAttendance(); }, 0, 1, TimeUnit.DAYS);薪资计算涉及基本工资、绩效、扣款、社保等,通常是一个公式链。建议把计算逻辑抽到一个SalaryCalculator类里,每个组成部分单独一个方法,方便调试和修改。批量处理时注意事务边界,要么全部成功,要么全部回滚,否则会出现部分员工薪资算错的情况。
4. 避坑与排查:JSP项目最容易翻车的五个地方
4.1 中文乱码:从请求到响应到数据库的三层排查
现象:页面输入中文,保存后变成问号或乱码。原因通常有三层:请求编码、响应编码、数据库编码。解决步骤:第一,在Servlet里request.setCharacterEncoding("UTF-8");第二,在JSP页面顶部<%@ page contentType="text/html;charset=UTF-8" %>;第三,数据库连接URL加useUnicode=true&characterEncoding=utf8;第四,建库时用utf8mb4。四层都对齐了,乱码基本消失。
4.2 ClassNotFoundException:驱动包和Servlet API的版本冲突
现象:启动时报java.lang.ClassNotFoundException: com.mysql.jdbc.Driver。原因:驱动包没放到WEB-INF/lib下,或者MySQL 8.0用了旧驱动类名。解决:下载对应版本的mysql-connector-java.jar放到WEB-INF/lib,8.0用com.mysql.cj.jdbc.Driver。如果是javax.servlet相关的ClassNotFoundException,检查Tomcat版本是否与项目匹配。
4.3 数据库连接池耗尽:连接未关闭的典型表现
现象:系统运行一段时间后报Cannot get a connection, pool exhausted。原因:DAO层里Connection、Statement、ResultSet没有在finally块里关闭。解决:用try-with-resources写法,或者确保每个资源都在finally里close。如果项目用了C3P0或DBCP,检查maxPoolSize配置是否太小。
4.4 JSP页面修改不生效:Tomcat缓存与work目录
现象:改了JSP文件,刷新浏览器还是旧内容。原因:Tomcat会把JSP编译成Servlet放在work目录下缓存。解决:删除work/Catalina/localhost/项目名目录,重启Tomcat。或者在server.xml里把development设为true,让Tomcat自动检测JSP变化。
4.5 部署后404:上下文路径与web.xml配置检查
现象:访问http://localhost:8080/项目名/报404。原因:上下文路径不对,或者web.xml里<welcome-file>配置的首页不存在。解决:在Eclipse的Server配置里看Path是否正确,在web.xml里确认<welcome-file-list>里的文件名和实际文件一致。如果是IDEA,检查Artifact的Output Layout里WEB-INF和web.xml是否在正确位置。
5. 二次开发与答辩加分:让项目从“能跑”到“有亮点”
5.1 把JSP页面改成前后端分离的渐进式方案
如果想让项目看起来更现代,不用大改架构,可以渐进式地把部分JSP页面改成AJAX请求。比如员工列表页,保留JSP作为容器,但数据用fetch或jQuery.ajax从Servlet拿JSON,前端用模板引擎渲染。这样既保留了原有后端逻辑,又让页面交互更流畅。Servlet里返回JSON用Gson或Jackson:
// 返回JSON的Servlet片段 response.setContentType("application/json;charset=UTF-8"); PrintWriter out = response.getWriter(); Gson gson = new Gson(); out.print(gson.toJson(empList)); out.flush();前端用fetch:
fetch('employee?action=apiList') .then(res => res.json()) .then(data => { const tbody = document.querySelector('#empTable tbody'); tbody.innerHTML = data.map(emp => `<tr><td>${emp.empId}</td><td>${emp.empName}</td></tr>` ).join(''); });这种改法工作量小,但答辩时能讲出“前后端分离思想”,是个不错的加分项。
5.2 用拦截器做登录校验与权限控制
原始项目可能只在每个Servlet里手动判断session.getAttribute("user")是否为空。更好的做法是用Filter统一拦截:
public class AuthFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; String uri = request.getRequestURI(); // 放行登录页和静态资源 if (uri.contains("login.jsp") || uri.contains("LoginServlet") || uri.contains(".css") || uri.contains(".js")) { chain.doFilter(req, res); return; } if (request.getSession().getAttribute("user") == null) { response.sendRedirect("login.jsp"); return; } chain.doFilter(req, res); } }在web.xml里配置<filter-mapping>,拦截所有请求。这样权限控制集中在一处,代码干净,答辩时也能讲出“AOP思想”。
5.3 答辩演示的脚本准备与常见提问预演
答辩演示最怕现场翻车。建议提前准备好一个演示脚本:先登录,展示不同角色(管理员、普通员工)的权限差异;然后走一遍新增员工、修改部门、查看考勤的流程;最后展示数据库里的数据变化。常见提问包括:“你的系统怎么保证数据一致性?”“如果并发访问会有什么问题?”“为什么选JSP不选Spring Boot?”提前想好答案,比如数据一致性靠事务,并发问题可以提连接池和锁,选JSP是因为项目周期短、技术栈熟悉。
我自己的习惯是,答辩前把整个流程在本地跑三遍,每遍都从Tomcat重启开始,确保没有缓存依赖。另外准备一个“后悔药”方案:如果现场数据库连不上,提前导出一份SQLite版本或者用H2内存数据库兜底。希望帮到你。
本文还有配套的精品资源,点击获取