JSP+Servlet人事管理系统源码实战:环境搭建、Model2原理与避坑指南
简介这是一套基于JSPServletTomcatMySQL技术栈实现的人事管理系统完整源码面向计算机、软件工程、电子信息等专业的学生与初级开发者可用于课程设计、期末大作业或毕业设计参考也适合作为Java Web入门到进阶的实战练习项目。压缩包共收录约2000个文件整体大小73.74MB其中以1294个JavaScript脚本与404个CSS样式文件为主配合75个HTML页面、42个JSP视图、49个Java后端类、2个SQL建表脚本及若干properties、xml配置文件完整覆盖前端界面、控制层、业务逻辑与数据库脚本目录结构清晰便于按模块阅读与二次开发。目前已有203人学习下载可作为理解Servlet请求流转、JSP页面渲染与MySQL数据持久化的参考范例帮助读者快速搭建可运行的人事管理环境并在此基础上自行调试与扩展功能。1. 从一份 JSPServlet 人事管理系统源码说起它到底能跑出什么很多人第一次拿到「基于jspservlettomcatmysql的人事管理系统源码.zip」这类压缩包时第一反应是解压、丢进 IDE、点运行然后被一连串 404、500 和中文乱码按在地上摩擦。这套技术栈是典型的 JavaWeb 原生组合JSP 负责页面渲染Servlet 承担控制器逻辑Tomcat 作为 Servlet 容器MySQL 存员工、部门、考勤、薪资这些数据。它没有 Spring 的自动装配也没有 MyBatis 的映射封装所有请求转发、数据库连接、事务提交都得自己写。正因为「裸」它反而是理解 JavaWeb 请求生命周期最直接的样本。这套系统适合两类人一是做课程设计或毕设、需要一套能讲清楚 Model2 分层的学生二是想从 Spring Boot 的「黑匣子」里退出来、搞明白 Servlet 到底怎么被容器调度的开发者。它能解决的核心问题是把人事管理里员工增删改查、部门维护、登录鉴权这些业务用最原始的 JDBC Servlet JSP 串起来。读完并动手跑通后你会对 web.xml 配置、请求参数编码、连接池、会话管理这些「老古董」有肌肉记忆级别的理解而这些恰恰是排查现代框架问题时最底层的参照系。2. 环境搭建JDK、Tomcat、MySQL 三件套怎么配才不翻车2.1 JDK 与 Tomcat 的版本匹配这套源码通常基于 Servlet 3.x 或 4.0 规范对应 Tomcat 8.5 或 9.0。别一上来就装 Tomcat 10因为 Tomcat 10 把javax.servlet包名改成了jakarta.servlet源码里的import javax.servlet.*会全部报红这是新手最容易踩的版本坑。JDK 选 8 或 11 都行JDK 17 以上配合老版本 Tomcat 偶尔会有反射相关的警告但不影响运行。安装 Tomcat 的常见做法是下载 zip 包解压配置CATALINA_HOME环境变量然后进bin目录执行启动脚本。Windows 下双击startup.batLinux 下执行./startup.sh。启动后访问http://localhost:8080看到 Tomcat 默认页就说明容器活了。如果 8080 被占用改conf/server.xml里的Connector port即可。# Linux 下启动 Tomcat 并查看日志 cd /opt/tomcat/bin ./startup.sh tail -f ../logs/catalina.outstartup.sh只是启动脚本真正的输出在logs/catalina.out。很多人启动后看不到报错就以为成功了其实异常都堆在日志里。tail -f实时跟踪日志是排查启动失败的第一手段。2.2 MySQL 8.0 安装与建库建表MySQL 建议用 8.0安装时记住 root 密码。安装完成后用命令行或 Workbench 连上去先建库再导表。源码里一般会带一个.sql文件直接 source 进去。-- 创建数据库字符集必须用 utf8mb4否则中文姓名会变问号 CREATE DATABASE hrms DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE hrms; -- 员工表结构示例字段按源码实际调整 CREATE TABLE employee ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50) NOT NULL, dept_id INT, salary DECIMAL(10,2) DEFAULT 0, hire_date DATE ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;字符集这里有个血泪经验如果建库时用了latin1或utf8MySQL 的 utf8 其实是 utf8mb3只支持 3 字节插入中文员工姓名时要么报错要么显示乱码。utf8mb4才是真正的 4 字节 UTF-8。另外salary字段设了DEFAULT 0避免插入时 null 导致前端计算报空指针。2.3 把源码导入 IDE 并配置 Tomcat源码导入 IDEA 或 Eclipse 后关键是配置 Artifact 和 Tomcat Server。IDEA 里在Run/Debug Configurations新增 Tomcat ServerDeployment 选项卡添加war exploded工件。war exploded支持热更新改 JSP 不用重启改 Java 代码才需要重启。数据库连接配置通常在src下的db.properties或某个DBUtil.java里。把 URL、用户名、密码改成你本地的jdbc.drivercom.mysql.cj.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/hrms?useUnicodetruecharacterEncodingutf8mb4serverTimezoneAsia/ShanghaiuseSSLfalse jdbc.usernameroot jdbc.password你的密码com.mysql.cj.jdbc.Driver是 MySQL 8.0 的新驱动类名老版本是com.mysql.jdbc.Driver写错会报ClassNotFoundException。serverTimezone不配的话连接时可能抛时区异常。useSSLfalse在本地开发时关掉 SSL 握手省去证书配置的麻烦。3. 请求是怎么走完一圈的Servlet 与 JSP 的 Model2 分工3.1 从浏览器到 Servlet 的完整链路Model2 的核心思想是「JSP 只做展示Servlet 只做控制」。浏览器发一个/employee?actionlist请求Tomcat 根据web.xml或注解把请求映射到EmployeeServlet。Servlet 里调用 Service 层Service 调 DAO 层查数据库拿到ListEmployee后塞进request.setAttribute再forward到employee_list.jsp。JSP 用 JSTL 或脚本片段把数据渲染成 HTML 返回浏览器。这条链路里forward是服务器内部跳转浏览器地址栏不变redirect是让浏览器重新发请求地址栏会变。登录成功后一般用redirect防止刷新重复提交查询列表用forward保持请求域数据。// EmployeeServlet 中处理列表查询的核心片段 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 统一设置编码必须在获取参数之前 request.setCharacterEncoding(UTF-8); response.setContentType(text/html;charsetUTF-8); String action request.getParameter(action); if (list.equals(action)) { ListEmployee list employeeService.findAll(); request.setAttribute(empList, list); // forward 到 JSP请求域数据可被 JSP 读取 request.getRequestDispatcher(/employee_list.jsp).forward(request, response); } }setCharacterEncoding必须放在getParameter之前否则 POST 中文参数已经按默认编码解析完了再设也没用。这是 JSP/Servlet 中文乱码最经典的根因。response.setContentType告诉浏览器用 UTF-8 解析页面避免页面本身乱码。3.2 JSP 页面里怎么安全地取数据JSP 里取request域数据推荐用 JSTL 的c:forEach而不是% %脚本片段。脚本片段虽然直观但把 Java 逻辑混进页面后期维护是灾难。% taglib prefixc urihttp://java.sun.com/jsp/jstl/core % table c:forEach items${empList} varemp tr td${emp.id}/td td${emp.name}/td td${emp.salary}/td /tr /c:forEach /table${emp.name}走的是 EL 表达式底层调用getName()。如果emp为 nullEL 会输出空字符串而不是抛异常这比脚本片段安全。c:forEach的items对应request域里的empListvar是循环变量名。用 JSTL 需要把jstl.jar和standard.jar放进WEB-INF/lib否则标签不解析。3.3 数据库连接池别每次请求都 DriverManager源码里如果每次请求都DriverManager.getConnection()并发一上来数据库连接数就爆了。正确做法是用连接池常见的是 Druid 或 C3P0。以 Druid 为例配一个DruidDataSource单例在ServletContextListener里初始化。public class DBUtil { private static DruidDataSource dataSource; static { dataSource new DruidDataSource(); dataSource.setUrl(jdbc:mysql://localhost:3306/hrms?useUnicodetruecharacterEncodingutf8mb4serverTimezoneAsia/ShanghaiuseSSLfalse); dataSource.setUsername(root); dataSource.setPassword(你的密码); dataSource.setInitialSize(5); // 初始连接数 dataSource.setMaxActive(20); // 最大活跃连接 dataSource.setMaxWait(3000); // 获取连接超时毫秒 } public static Connection getConnection() throws SQLException { return dataSource.getConnection(); } }initialSize是启动时预建的连接数maxActive是并发上限maxWait是拿不到连接时的等待时间。这三个参数要根据实际并发调设太小会频繁等待设太大数据库端max_connections可能不够。用连接池后close()不是真关连接而是归还池子所以 DAO 里照常try-with-resources即可。4. 避坑与排查这套老技术栈最容易翻车的五个地方4.1 现象页面中文全是问号或乱码原因JSP 页面pageEncoding、响应Content-Type、数据库字符集、连接 URL 的characterEncoding四处只要有一处不是 UTF-8中文就会断链。解决JSP 顶部写% page contentTypetext/html;charsetUTF-8 pageEncodingUTF-8 %Servlet 里request.setCharacterEncoding(UTF-8)和response.setContentType(text/html;charsetUTF-8)都加上数据库用utf8mb4URL 带characterEncodingutf8mb4。四处对齐后乱码基本消失。4.2 现象Tomcat 启动报ClassNotFoundException: com.mysql.cj.jdbc.Driver原因MySQL 驱动 jar 没放进WEB-INF/lib或者只加进了 IDE 的库但没随工件部署。解决把mysql-connector-java-8.x.jar复制到WEB-INF/lib目录在 IDEA 的 Project Structure 里确认 Artifact 的 Output Layout 包含这个 jar。用 Maven 的话mysql-connector-java的 scope 设成compile或runtime别设provided。4.3 现象访问 Servlet 报 404但 Tomcat 明明启动了原因web.xml里url-pattern和浏览器地址不匹配或者 Servlet 注解WebServlet(/employee)的路径写错又或者项目context path不是/。解决先看 Tomcat 日志里应用是否部署成功再确认访问地址是http://localhost:8080/项目名/employee还是http://localhost:8080/employee。IDEA 里 Application context 默认是/_war_exploded改成/更省事。4.4 现象登录后刷新页面就退出登录原因Session 超时时间太短或者每次请求都新建了 Session。解决在web.xml里配session-configsession-timeout30/session-timeout/session-config单位是分钟。另外检查登录逻辑里是不是每次request.getSession()后没复用正常应该request.getSession().setAttribute(user, user)后续请求用getSession(false)取。4.5 现象MySQL 报Public Key Retrieval is not allowed原因MySQL 8.0 默认用caching_sha2_password认证插件JDBC 连接时如果没开公钥检索会拒绝。解决在连接 URL 后面加allowPublicKeyRetrievaltrue或者把用户认证插件改成mysql_native_password。本地开发加参数最快生产环境建议改插件并配好 SSL。5. 进阶把这份源码改造成能讲清楚、能扩展的毕设底子跑通只是起点。如果你拿它做毕设答辩时老师一定会问「你这系统有什么技术含量」。这时候别慌把几个点做扎实就能撑住场面。第一把 DAO 层的 JDBC 裸写抽成泛型基类用反射做通用增删改查体现你对 JDBC 元数据的理解。第二加一个简单的权限过滤器Filter用WebFilter拦截未登录请求讲清楚 Filter 和 Servlet 的执行顺序。第三把连接池参数、Session 超时、字符集这些配置集中到一个application.properties用ServletContextListener加载体现配置与代码分离的意识。验证改造是否成功可以写一个简单的压测用ab或 JMeter 对员工列表接口发 200 个并发请求观察 Tomcat 日志有没有连接池等待超时maxActive调到多少时响应时间开始明显上升。这个数据在答辩时比任何形容词都有说服力。# 用 ab 对列表接口做 200 并发、共 1000 次请求的压测 ab -n 1000 -c 200 http://localhost:8080/employee?actionlist-n是总请求数-c是并发数。重点看Failed requests和Time per request两栏。如果失败数不为零多半是连接池maxActive太小或数据库max_connections被打满。根据结果反推参数再写进你的毕设文档这就是「调优」的实证。我自己踩过最深的坑是当年为了省事把数据库密码硬编码在DBUtil里结果换台机器演示时连不上现场改代码改到冒汗。后来养成习惯所有环境相关的配置一律外置代码里只留读取逻辑。这个习惯比任何框架都值钱。希望帮到你。本文还有配套的精品资源点击获取