JSP人事人力资源管理系统毕业设计:从部署到答辩的全流程指南
2026/9/17 1:51:33 网站建设 项目流程

简介:基于JSP的人事人力资源管理系统毕业设计项目,适合计算机相关专业学生用于课程设计或毕业设计参考,也可作为Java Web入门者的实战练习素材。项目采用JSP+MySQL+B/S架构,覆盖系统管理员、部门信息、员工信息、合同管理、绩效管理(含员工工资与奖惩记录)以及考勤管理等核心模块,能够帮助读者完整理解企业人事业务的后台开发流程。压缩包共116个文件,包含69个JSP页面、JAR依赖库、JS/CSS样式脚本、SQL数据库脚本以及说明文档和操作录像,整体大小约2.99MB,目录结构清晰,便于直接导入开发工具运行调试。目前已有58人学习下载,适合需要快速搭建人事系统或准备毕设答辩的开发者。除完整源码外,还附带项目说明与操作录像,可对照配置环境、了解功能操作并梳理设计思路,有效节省从零开发与排错的时间。

1. 为什么JSP毕业设计还能做人事人力资源管理系统

JSP在互联网岗位里已经不算热门,但放在毕业设计市场上,人事人力资源管理系统依然是每年重复出现的选题。原因不是技术新,而是课程还在教、老师好验收、学生能在短时间里把 JSP、Servlet、JDBC 这套 Web 基础知识串成一个完整闭环:登录、部门维护、员工档案、考勤与工资查询。拿到这类 zip 包,需要的不只是解压后能打开项目,而是要搞清楚部署步骤、数据库脚本放在哪、改哪个文件能调页面样式,以及答辩时哪些点最容易被追问。下面这套路径是按做这类项目最稳妥的方式走的:先搭技术骨架,再部署跑通,补分页和导出功能,最后给几个现场演示的细节。适合第一次做 JSP 系统的学生,也适合在旧项目上快速二次开发的工程师。

2. 人事人力资源系统的最小骨架:JSP+Servlet+JDBC怎么搭

别被“人事人力资源管理系统”这个完整名称吓住,它落到代码上不过三张表和两套页面:用户登录、员工档案增删改查、部门列表,最多再加考勤和工资的简单记录。技术选型上,JSP 负责页面展示,Servlet 负责接收请求和跳转,JDBC 负责操作 MySQL。这是一套能在 Tomcat 上直接跑起来的最小 Web 应用结构,也是很多毕业设计源码包里最常见的分层方式。把它拆明白了,后面改功能、做答辩都非常顺。

2.1 先分清JSP、Servlet、JDBC各自干哪层活

JSP 的本质是一个会被 Tomcat 编译成 Servlet 的模板文件,但不意味着所有逻辑都能写进 JSP。常见做法是分三层:JSP 放在 WebContent 根目录做表单和列表展示;Servlet 放在 controller 包下接收参数、调用 service、再转发或重定向;JDBC 工具类放在 dao 包下负责查询和增删改。如果 JSP 页面里的<% ... %>脚本块中写了大段 SQL,项目一旦上线会非常难调,答辩时也容易被问住。人事人力资源管理系统最忌讳的就是把数据库连接和业务判断全部堆在页面里。

目录结构一般按这样组织:src/main/java下有entity/dao/service/controller/utilWebContentsrc/main/webapp下有WEB-INF/web.xmlcss/jsjsp页面。以员工模块为例,entity里有Employee.javaDepartment.javaUser.javadao里有EmployeeDAO.java,里面只写 SQL 和结果集处理;controller里有EmployeeServlet.java,负责把请求参数转成 Employee 对象再调用 DAO。JSP 层只做展示和表单提交,不要在页面里直接 new Connection。

为了不重复写注册驱动和获取连接,我一般会写一个DBUtil.java放在 util 包。下面是这套系统里最常见的写法:

package util; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; public class DBUtil { private static final String DRIVER = "com.mysql.cj.jdbc.Driver"; private static final String URL = "jdbc:mysql://localhost:3306/hrms?useUnicode=true&characterEncoding=utf8"; private static final String USER = "root"; private static final String PASSWORD = "123456"; static { try { Class.forName(DRIVER); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public static Connection getConnection() throws Exception { return DriverManager.getConnection(URL, USER, PASSWORD); } public static void close(ResultSet rs, Statement stmt, Connection conn) { try { if (rs != null) rs.close(); } catch (Exception e) {} try { if (stmt != null) stmt.close(); } catch (Exception e) {} try { if (conn != null) conn.close(); } catch (Exception e) {} } }

这段代码里三个参数要特别留意。URL 中的useUnicode=true&characterEncoding=utf8决定中文能不能正常写入和读出;MySQL 8 以上驱动类名必须写com.mysql.cj.jdbc.Driver,MySQL 5.7 用com.mysql.jdbc.Driver也能跑;MySQL 8 不配置serverTimezone时,连接会报时区错误,需要补成serverTimezone=Asia/Shanghai。数据库名默认为hrms,如果压缩包里的 SQL 脚本用了别的库名,要同步改这里,否则程序一启动就报数据库不存在。密码也不要直接写成123456就结束,答辩前把数据库密码和 DBUtil 里的密码核对一遍,很多部署失败都发生在这一行。

2.2 三张核心表和最小SQL脚本

人事人力资源管理系统一般不需要设计过于复杂的表。常见设计是t_user存登录账号,t_department存部门信息,t_employee存员工档案。下面这种结构能覆盖大部分演示需求:

表名关键字段说明
t_userid, username, password登录账号,密码建议MD5后存储
t_departmentid, dept_name, manager部门名称和负责人
t_employeeid, emp_no, name, dept_id, phone, hire_date员工编号关联部门,方便按部门筛选

初始化脚本里至少要有这三张表。毕业设计更推荐用 MySQL,因为答辩环境最常遇到的就是 MySQL 5.7 或 8.0。建表顺序要注意:先建没有外键依赖的t_usert_department,再建带dept_idt_employee,否则导入时会报外键不存在。压缩包自带的 SQL 文件用 Navicat 或命令行导入前,先打开看一下是否有 CREATE DATABASE,避免重复建库。如果源码包里没有 SQL 文件,用下面的语句手动建表也能撑住演示:

CREATE DATABASE hrms DEFAULT CHARACTER SET utf8mb4; USE hrms; CREATE TABLE t_user ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL, password VARCHAR(64) NOT NULL ); CREATE TABLE t_department ( id INT PRIMARY KEY AUTO_INCREMENT, dept_name VARCHAR(50) NOT NULL, manager VARCHAR(30) ); CREATE TABLE t_employee ( id INT PRIMARY KEY AUTO_INCREMENT, emp_no VARCHAR(20) NOT NULL, name VARCHAR(30) NOT NULL, dept_id INT, phone VARCHAR(20), hire_date DATE );

这里有一个常见坑:t_employee里如果冗余了dept_name字段,修改部门名称后,员工表里的旧名称不会自动更新。建议显示部门名称时用SELECT e.*, d.dept_name FROM t_employee e LEFT JOIN t_department d ON e.dept_id = d.id,不要在 employee 表里冗余存部门名,这样答辩时也更容易说清楚表设计。写完数据库工具类之后,最好先用一个最简单的UserServlet做登录验证,而不是直接写员工管理。登录流程能同时验证 JSP 表单提交、Servlet 获取参数、DAO 查询结果、Session 保存用户信息这几条链路,只有登录通了,后面的增删改查才不至于分不清是数据库错了还是页面错了。

3. 从zip源码到Tomcat能跑的JSP项目:部署与数据库初始化

解压毕业设计 zip 包看起来简单,但最容易卡住人的不是代码,而是环境。手里这个包一般会包含项目源码、说明文档和演示录像,说明文档里写“导入IDEA即可运行”不代表真的能一键跑通。我一般会先确认三件事:JDK 版本、Tomcat 版本、MySQL 版本。JSP 项目在 JDK 8 和 JDK 11 下的兼容性不同,Tomcat 8.5 和 9.0 对 Servlet 4.0 的支持也有差异,所以部署前不要直接双击 startup.bat,先看压缩包里的说明文档或 web.xml 头部的版本号。最稳妥的组合是 JDK 8 配 Tomcat 9.0,JDK 11 配 Tomcat 9.0 也可以,只要项目里没有用太多废弃 API。

环境组合可用性常见问题
JDK 8 + Tomcat 8.5 + MySQL 5.7兼容性最好基本无需额外配置
JDK 8 + Tomcat 9.0 + MySQL 8.0最常见的毕设组合需要处理时区参数
JDK 11 + Tomcat 9.0 + MySQL 8.0需要确认编译目标Servlet API 可能不兼容

3.1 zip解压时先解决中文编码问题

很多 Windows 上压缩的 zip 包用 GBK 编码保存文件名,到了 Linux 或 macOS 下直接unzip,会出现中文目录名变成乱码,导致项目名和 web.xml 里的 context 路径对不上。现在的压缩工具默认可能用 UTF-8,但毕业设计包里的情况比较杂。常见解决方案不是改系统 locale,而是用带指定编码的方式解压。

mkdir hrms cd hrms unzip -O GBK ../人事人力资源管理系统.zip

-O GBK是告诉 unzip 将压缩包内的文件名按 GBK 解释。如果解压出来还是乱码,可以在项目文件不多的情况下回 Windows 重新压缩,或者用 7-Zip 打开压缩包时手动选择字符集。要注意的是,网上那些“zip密码移除”工具尽量不要碰,这类工具容易破坏压缩包结构,而且解压出来损坏的 class 文件比文件名乱码更难处理。解压后第一件事是看目录下有没有.sql文件、WEB-INF/web.xml以及srcWebContent。只要这三样齐全,项目基本可导入;缺 sql 文件时,用上一章给的最小建表语句补上也能做演示。

3.2 数据库脚本导入和配置文件改动

找到.sql脚本后用命令行导入最稳定。在 MySQL 中先确认账号权限,再执行:

mysql -uroot -p123456 -h127.0.0.1 < hrms.sql

如果脚本里没有 create database,需要先手动建库,然后执行 source。导入后立刻查三张表的行数,确认 SQL 脚本和数据是完整的,SELECT COUNT(*) FROM t_employee;至少要有几条测试数据,否则演示时新增员工的页面没有参考数据,观感会差很多。很多源码包里自带的 SQL 是旧版本导出的,可能没有 utf8mb4 字符集设置,遇到中文乱码时,在连接 URL 里加上characterEncoding=utf8还不够,还要确认数据表本身的 charset 不是 latin1。

配置文件一般叫db.propertiesjdbc.properties,放在src目录下,部署后会被复制到 classes 目录。修改db.properties后不重新编译不重启,连接池会一直保留旧连接,这就是“我改了配置为什么没生效”的高频原因。有人习惯直接把 JDBC 参数写在 DBUtil 类里,那样也可以,但改配置后要重新编译整个项目。源码包里如果是 WebContent 结构,没有 Maven 管理,那就直接用 Eclipse 或 IDEA 的 Tomcat 集成功能,把项目添加到 Server 的 Deploy 列表,由 IDE 控制编译和发布目录,这样比手动复制 webapps 更容易排错。

3.3 在Tomcat里确认JSP编译class文件的位置

把整个 WebContent 目录直接丢进 Tomcat 的webapps下也能运行,但更好的方式是在 IDE 里配置一个 Tomcat Server,让源码改完自动热部署。Tomcat 会把 JSP 编译成.java.class文件,默认位置是tomcat/work/Catalina/localhost/<项目名>/org/apache/jsp。明白这个位置后,排错会有方向:比如 JSP 改了不生效,先看这个目录下的index_jsp.java生成时间是不是最新;如果时间没更新,说明 Tomcat 没有重新编译页面。

rm -rf /opt/tomcat/work/Catalina/localhost/hrms

清掉整个项目对应的 work 目录再重启,Tomcat 会在第一次访问 JSP 时强制编译。这个操作比反复点 IDE 里的“重新部署”更可靠,特别适合修改 JSP 后浏览器还是老页面的情况。Tomcat 的 context 路径默认是目录名,如果访问http://localhost:8080/hrms/login.jsp返回 404,先检查 webapps 下实际目录名是否是hrms,再检查 zip 解压后是否多了一层目录,比如人事人力资源管理系统/hrms。多一层目录时把里面的内容上移一级就好。

4. JSP页面不写死数据:分页、JSON接口与Excel导出

人事人力资源管理系统的演示重点一般有两个:一是员工列表能不能流畅分页,二是列表数据能不能导出 Excel。这两块做好了,答辩时有内容可讲,也是这个标题在搜索引擎里最常被搜到的“jsp jsonarray import”和“jsp实现数据导出为excel”对应的需求来源。JSP 页面不能直接把几十条数据全部循环打印一遍就算完,因为大列表打印没问题,但部门筛选和薪酬统计出现多个条件时,页面脚本就会乱成一团,维护成本也高。

4.1 员工列表分页的Servlet实现

分页最直接的写法是前端传 pageNum 和 pageSize,Servlet 接收后拼 SQL 的 LIMIT 子句。有人会把分页做成在 JSP 里循环整个 ResultSet,只在显示时跳过前 N 条,这在数据量小的时候看不出问题,但员工表超过 200 条后会明显变慢。下面这段代码把分页逻辑放在 service 层,先用单参数接收页码,避免 Servlet 里到处出现魔法数字:

public List<Employee> listByPage(int pageNum, int pageSize) { String sql = "SELECT e.*, d.dept_name FROM t_employee e " + "LEFT JOIN t_department d ON e.dept_id = d.id " + "ORDER BY e.id DESC LIMIT ?, ?"; try (PreparedStatement ps = DBUtil.getConnection().prepareStatement(sql)) { ps.setInt(1, (pageNum - 1) * pageSize); ps.setInt(2, pageSize); try (ResultSet rs = ps.executeQuery()) { List<Employee> list = new ArrayList<>(); while (rs.next()) { list.add(mapRow(rs)); } return list; } } catch (Exception e) { e.printStackTrace(); return Collections.emptyList(); } }

LIMIT ?, ?的两个参数分别是偏移量和每页条数,顺序不能反。pageNum 从 1 开始,在 Servlet 里要做默认值校验,比如pageNum == null || "".equals(pageNum)时默认pageNum = 1。如果查询条件带部门筛选,SQL 要再加WHERE d.dept_id = ?,这时 LIMIT 参数位置要靠后,传参顺序容易写错。建议把筛选参数单独放在方法签名里,不要和分页参数混在一起,否则后期加搜索条件时,改一行 SQL 要连带改好几处参数。

JSP 底部的分页条,我一般只显示第一页、上一页、下一页和总页数,不显示中间所有页码,因为毕业设计演示不需要太复杂的分页组件。总页数用total % pageSize == 0 ? total / pageSize : total / pageSize + 1计算,注意 total 要用 long 类型,避免员工数量超过 int 上限。页码链接直接用employee?action=list&pageNum=2,不要在 JSP 里拼接乱码参数,中文部门名需要 URLEncoder.encode 后再拼,否则第一次点下一页就会变成问号。

4.2 JSON数组接口和JSP页面的import陷阱

员工信息的下拉联动和异步搜索,常见做法是让 Servlet 返回 JSON 数组,JSP 页面再用原生 fetch 或 jQuery 的 ajax 接收。很多人一开始以为在 JSP 顶部写<%@ page import="com.alibaba.fastjson.JSONArray" %>就能把 JSON 写在页面里。实际上 JSONArray 是在 Servlet 里拼好,再通过response.getWriter().print(jsonArray.toString())输出的,JSP 页面只负责接收结果。在页面里 import JSONArray 本身没错,但只要在 JSP 中直接 new JSONArray 并放业务数据,访问时会同时触发页面编译和序列化,出错后很难定位。

response.setContentType("application/json;charset=utf-8"); JSONArray arr = new JSONArray(); for (Department d : deptList) { JSONObject obj = new JSONObject(); obj.put("id", d.getId()); obj.put("name", d.getDeptName()); arr.add(obj); } response.getWriter().print(arr.toJSONString());

这段代码用 fastjson 生成部门下拉选项。前端如果收到数据后提示中文乱码,检查响应头里的charset=utf-8,同时检查 IDE 里 Java 文件本身是不是 UTF-8 编码。fastjson 的版本建议用稳定版,老版本自动类型转换时可能把整数变成字符串,所以建议在 Servlet 端直接对 id 做Long.parseLong再放进对象里。如果不想引入 fastjson,也可以手写 JSON 字符串,但字段多时容易漏引号和逗号,还是用库更安全。

参数建议值作用
Content-Typeapplication/json;charset=utf-8告诉浏览器返回的是 JSON 文本
JSONArrayfastjson 1.2.83生成数组比手写字符串稳定
字符编码UTF-8防止中文姓名变成乱码

4.3 用POI把员工列表导出为Excel

很多项目里的“导出”是在 JSP 里直接输出一段逗号分隔文本,扩展名写成 .xls,用 Excel 打开会提示格式损坏。我用 Apache POI 的方式是单独写一个 ExportServlet,请求路径比如/exportEmployee,响应内容类型设好之后写HSSFWorkbook再输出。示例核心片段:

response.setContentType("application/vnd.ms-excel;charset=utf-8"); response.setHeader("Content-Disposition", "attachment;filename=employees.xls"); HSSFWorkbook workbook = new HSSFWorkbook(); HSSFSheet sheet = workbook.createSheet("员工"); HSSFRow header = sheet.createRow(0); header.createCell(0).setCellValue("工号"); header.createCell(1).setCellValue("姓名");

Content-Disposition里如果不加filename=employees.xls,浏览器会把响应当普通页面打开,用户看不到下载提示。输出到响应流之后,不要再执行out.println或 JSP 页面跳转,否则 xls 文件会混入 HTML 内容,导致下载下来的文件打不开。POI 的版本选择要看页面里有没有合并单元格和日期格式,只需要基础数据的话用 4.1.2 就行;导出前要先把请求里的筛选参数取出来,防止导出的是没过滤的全量数据。如果想在 JSP 中触发导出,用<a href="exportEmployee?deptId=1">导出Excel</a>最简单,不需要写 JavaScript 表单提交。

5. 答辩前把JSP项目调到能演示的几个细节

演示现场最怕的不是功能没做,而是点完按钮后卡在浏览器里的报错页。我建议在答辩前把整条演示路径在浏览器无痕窗口里走一遍:从登录页输入错误密码看提示,到新增员工后列表刷新,再到导出 Excel 检查文件能打开。任何一步出现 500 或 404,都先用日志定位再继续演示,不要一边点一边改代码。重点检查两个地方:Tomcat 的日志输出和数据库里的测试数据。测试数据要多样,中文姓名、数字工号、边界日期都要有一条,否则现场演示时看不出表格展示效果。

5.1 用一条命令验证接口是否活着

后台已经启动时,可以先用 curl 检查登录页和登录提交接口:

curl -i http://localhost:8080/hrms/login.jsp curl -s -X POST http://localhost:8080/hrms/user/login -d "username=admin&password=123456"

-i能看到 HTTP 状态码和Set-Cookie字段,如果返回 200 但页面内容为空,多半是 JSP 编译异常后被 Tomcat 吞掉,直接去work/Catalina/localhost/hrmslogin_jsp.java,看最底部有没有编译报错。-X POST的登录请求返回体如果是 JSON,再用浏览器地址栏打开带 pageNum 参数的查询地址,验证分页是否正常。这样能在上台前把所有接口都过一遍,不用点开每个页面。

5.2 JSP改不生效时清掉work目录

JSP 和 Servlet 的改动在 IDE 里保存后,Tomcat 有时不会立刻重新编译,特别是只改了 JSP 中的一行 HTML 时。遇到页面没变化,先按Ctrl+Shift+R强制刷新浏览器,再不行就执行清空 work 目录的命令。顺序是:先停掉 Tomcat,再删除tomcat/work/Catalina/localhost/hrms目录,最后启动并访问一次对应的 JSP。如果在运行中直接删除,Tomcat 缓存的部分 class 文件被占用,删除可能失败。这个操作和 JSP 编译 class 文件的默认位置直接相关,把路径记住,排错能快很多。

演示机上的 JDK 和 Tomcat 版本最好和开发机保持一致。答辩前把项目打成 zip 后,最好在另一台干净机器上按 README 重新走一遍部署流程,重点执行下面的启动命令:

catalina.sh run

catalina.sh run会把 Tomcat 日志直接输出到终端,看到Server startup in之后再走 HTML 操作流程。日志里如果出现ClassNotFoundException,优先检查 lib 目录下有没有 mysql-connector-java.jar 和 jstl.jar;出现SQLSyntaxErrorException时回数据库里核对三张表的字段名是否和 SQL 一致。

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询