ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

SSM人力资源管理系统实战:从环境部署到功能扩展

2026/9/12 12:58:52 拓冰建站 浏览量
SSM人力资源管理系统实战:从环境部署到功能扩展 简介这是一套面向计算机专业毕业设计及Java学习者的人力资源管理系统完整源码包基于SpringSpringMVCMyBatis框架和MySQL数据库实现涵盖部门、职位、员工、考勤、薪资、意见、个人管理等七大核心模块能够满足中小企业人力信息管理场景的需求。压缩包共3个文件包括项目源码压缩包、数据库脚本sql和项目说明文档txt整体大小约25.07MB解压后即可导入数据库并部署运行。系统分管理员与员工两种角色权限清晰界面简洁所有代码经过严格调试适合直接作为毕业设计项目也适合想熟悉SSM整合流程的开发者进行实战练习。当前已有2579人学习/下载说明其内容对同类需求有较好的参考价值。资源内提供的数据库脚本可快速初始化数据项目说明文件则能帮助使用者了解目录结构与部署要点节省搭建时间。1. 从毕设选题到能跑起来的SSM人力资源管理系统刚拿到“基于SSM的人力资源管理系统【项目源码数据库脚本】”的人多半会遇到同一个场景Eclipse里导入ems工程后Tomcat启动到一半报ClassNotFoundException或者登录页出来了但数据库里没有初始账号。这套系统是标准SSM三层结构Spring管理ServiceSpringMVC接管请求MyBatis负责SQL加上ems.sql数据库脚本把部门、职位、员工、考勤、薪资、意见、个人管理七个模块整整齐齐地摆在一起。对做毕设的人来说它最大的价值不是功能多而是能在短时间内跑通一个完整的Java Web项目。适合两类人一类是答辩前需要让系统在自己电脑上复现的毕业生另一类是刚学完框架基础、想看看SSM怎么串联的Java后端学习者。2. SSM人力资源管理系统技术选型与项目结构2.1 为什么SSM这套老组合在这个项目里依然能打Spring、SpringMVC、MyBatis在今天的简历上不算新但在毕业设计这种体量的系统里它反而是最合适的。Spring的IoC容器把Service层对象创建和依赖关系交给配置文件管理AOP则把事务、日志这类横切逻辑抽出来SpringMVC用前端控制器DispatcherServlet统一分发请求让页面跳转和接口响应变得规整MyBatis半自动化的SQL映射给开发者留出了写复杂SQL的空间人力系统中常见的多表关联查询正好需要这种自由度。表SSM各层在人力资源系统中的落地位置框架核心职责在这个项目里的对应物Spring管理Service层Bean、事务applicationContext.xmlSpringMVC请求映射、参数绑定、视图解析spring-mvc.xml、ControllerMyBatisSQL执行、结果集映射Mapper接口、resources/mapper/*.xml这套组合相比Spring Boot确实要写更多XML配置但代价换来的是对请求链路的可见性。用这个项目学东西你能清楚地看到一次员工信息查询从JSP页面发出到数据库返回经历了哪几层。等以后切到Spring Boot自动配置下面藏着的就是这一类规则的默认值。2.2 解压ems.zip后的目录结构与各层定位拿到ems.zip后解压会得到一个ems目录和一份ems.sql。ems目录内通常包含src源码目录、resources配置目录和WebContent或webapp目录。用命令行看一眼结构ems ├── src │ ├── com/ems/controller # 控制层接收请求并返回视图 │ ├── com/ems/service # 业务逻辑层 │ ├── com/ems/mapper # MyBatis Mapper接口 │ ├── com/ems/entity # 实体类对应数据库表 │ └── com/ems/vo # 视图对象用于多表查询 ├── resources │ ├── jdbc.properties # 数据库连接配置 │ ├── spring-mvc.xml # SpringMVC配置 │ ├── spring-mybatis.xml # Spring与MyBatis整合配置 │ └── mapper/*.xml # SQL语句文件 ├── WebContent │ ├── WEB-INF │ │ ├── web.xml # 项目入口配置 │ │ └── lib/*.jar # 依赖jar包 │ └── jsp # 页面文件 └── ems.sql # 数据库初始化脚本注意如果是非Maven项目所有依赖都会放在WEB-INF/lib下面包括spring-webmvc.jar、mybatis.jar、mysql-connector-java.jar等。如果解压后lib目录是空的说明对方把jar包单独压缩了或者项目实际是Maven结构但保留了.classpath和.project文件。我一般会先检查WEB-INF/lib里有没有spring-webmvc这个jar没有的话优先找同目录下的“软件工具”文件夹都找不到再去本地Maven仓库补依赖。src下的controller、service、mapper、entity分层比较直白重点看resources/mapper里面的SQL文件这是整个项目最值得读的部分后面第3章我会按一个查询链路把这里拆开讲。2.3 ems.sql七个模块的库表关系要先理顺ems.sql是开箱跑起来的关键。它里面建的库名一般是ems表至少包括department、position、employee、attendance、salary、opinion和用户表。表之间的核心关联是employee通过dept_id关联department通过position_id关联positionsalary表再通过emp_id关联employee。数据库导入最直接的命令是在命令行执行mysql -h127.0.0.1 -uroot -p -e CREATE DATABASE IF NOT EXISTS ems DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; mysql -h127.0.0.1 -uroot -p ems ems.sql这里的-h指定数据库主机地址-u指定用户名-p表示需要密码最后的把ems.sql文件内容重定向给mysql客户端执行。第二行命令等价于进入mysql后用SOURCE /绝对路径/ems.sql。如果ems.sql文件里已经写了CREATE DATABASE语句那第一行可以跳过直接执行第二行。导入结束后用下面这段SQL确认表数量是否正确SELECT COUNT(*) AS table_count FROM information_schema.tables WHERE table_schema ems;正常情况下应该能看到7张及以上表。如果数量对不上多半是脚本在导入中途报错退出常见原因是SQL文件中使用了DEFAULT CHARSETutf8而当前数据库版本默认排序规则不兼容或者原脚本里的中文注释在命令行下出现乱码。我个人建议建库时显式使用utf8mb4能兼容更多特殊字符后续页面传中文也不会出现编码错乱。3. 核心功能模块的实现与权限设计3.1 从建表SQL到Java Bean员工模块的映射细节员工管理是整个系统的中枢其他模块几乎都围着employee表转。一个典型的员工表脚本大致是这样CREATE TABLE employee ( id INT PRIMARY KEY AUTO_INCREMENT, emp_no VARCHAR(20) NOT NULL UNIQUE COMMENT 员工工号, emp_name VARCHAR(50) NOT NULL COMMENT 员工姓名, dept_id INT NOT NULL COMMENT 所属部门ID, position_id INT NOT NULL COMMENT 职位ID, salary_id INT COMMENT 薪资档位ID, entry_time DATE COMMENT 入职日期, status TINYINT DEFAULT 1 COMMENT 1正常 0离职, CONSTRAINT fk_emp_dept FOREIGN KEY (dept_id) REFERENCES department(id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;对应的实体类Employee字段为id、empNo、empName、deptId、positionId、salaryId、entryTime、status。这里有个看似小事但很关键的配置MyBatis默认只能把列名emp_no自动映射到属性empNo前提是开启了驼峰转换否则查询结果里empNo会一直为null。在resources下的MyBatis配置文件里加上settings setting namemapUnderscoreToCamelCase valuetrue/ /settings这个参数解决的是下划线命名和驼峰命名不一致的问题。很多新手在项目里查到了数据但Java对象拿不到值问题就出在这里。除了这个全局配置还可以通过resultMap的column属性逐列指定映射关系更灵活但代码量更大。3.2 Mapper接口和XML一条员工列表查询的完整链路员工列表在页面上往往需要显示部门名称而不是部门ID这时单表查询满足不了需求标准的做法是定义一个EmployeeVO把部门和职位名称也带出来。Mapper接口里写public interface EmployeeMapper { ListEmployeeVO selectEmployeesWithDept(); }对应的XML文件里用resultMap做多表查询结果的字段映射resultMap idEmployeeVOMap typecom.ems.vo.EmployeeVO id propertyid columnid/ result propertyempNo columnemp_no/ result propertyempName columnemp_name/ result propertydeptName columndept_name/ result propertypositionName columnposition_name/ /resultMap select idselectEmployeesWithDept resultMapEmployeeVOMap SELECT e.id, e.emp_no, e.emp_name, d.dept_name, p.position_name FROM employee e LEFT JOIN department d ON e.dept_id d.id LEFT JOIN position p ON e.position_id p.id WHERE e.status 1 ORDER BY e.id DESC /select这里使用LEFT JOIN是为了避免员工没有设置部门时整行数据被过滤掉。resultMap里的property对应Java对象的属性名column对应SQL返回的列名。如果只是字段数量少也可以直接给SQL列名起别名来匹配实体类属性但多表查询字段一旦增多resultMap的可读性会更好。关于SQL拼接MyBatis里#{}会生成PreparedStatement的占位符值由驱动转义能防SQL注入${}则是直接做字符串替换哪怕在人力系统这种内部项目里只要用${}拼参数就必须做白名单校验尤其不要用在like和order by以外的场景。3.3 管理员和员工的双角色权限控制拦截器怎么写系统分管理员和员工两种角色登录成功后通常会把当前用户放进session比如session.setAttribute(loginUser, user)。为了保证不是每个人都能直接访问后台页面需要在SpringMVC配置里注册一个权限拦截器。public class AuthInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HttpSession session request.getSession(); Object loginUser session.getAttribute(loginUser); if (loginUser null) { response.sendRedirect(request.getContextPath() /login.jsp); return false; } return true; } }关键逻辑在preHandle里面拿不到用户就重定向到登录页并且立即返回false不再继续往下执行Controller方法。HandlerInterceptor是SpringMVC提供的拦截器接口实现它并注册到配置里就能在请求到达Controller前做校验。在spring-mvc.xml里的注册方式mvc:interceptors mvc:interceptor mvc:mapping path/**/ mvc:exclude-mapping path/login/ mvc:exclude-mapping path/css/**/ mvc:exclude-mapping path/js/**/ mvc:exclude-mapping path/images/**/ mvc:interceptor classcom.ems.interceptor.AuthInterceptor/ /mvc:interceptor /mvc:interceptorspath/**表示拦截所有请求exclude-mapping则把登录接口和静态资源放行。如果只想限制部分功能可以把/**改成更精确的前缀比如/admin/**避免每个Controller里都写一遍权限判断。要做到管理员和员工操作权限不同可以在拦截器里根据loginUser的role字段做二次分流也可以定义两个不同前缀的URL规则分别注册不同拦截器后者的维护成本更低。3.4 考勤、薪资模块背后的统计逻辑考勤和薪资是人力系统里“看起来简单SQL最容易写错”的部分。考勤表通常以“员工ID 日期”作为一条记录状态字段记录正常、迟到、早退、请假等。薪资表的设计有两种常见方式一种是按月把每个员工的固定工资存成一条汇总记录另一种是只记录变动项基本工资从职位表或员工表关联取得。我一般会在薪资表里保留salary_month字段格式如2024-05方便按月汇总。查看月度工资总额的SQL可以这样写SELECT e.emp_no, e.emp_name, DATE_FORMAT(s.salary_month, %Y-%m) AS month, SUM(s.base_salary s.bonus - s.deduction) AS real_salary FROM salary s JOIN employee e ON s.emp_id e.id GROUP BY e.emp_no, DATE_FORMAT(s.salary_month, %Y-%m) ORDER BY month DESC;这里用DATE_FORMAT把日期统一成年月格式再用GROUP BY按员工和月份分组。注意GROUP BY里的列必须和SELECT中的非聚合列保持一致否则在ONLY_FULL_GROUP_BY模式下会直接报错。MySQL 8.0默认开启这个模式很多老脚本在上面跑不了就是这个原因。实际项目中salary_month字段最好建索引不然员工量起来之后按月份过滤的查询会全表扫描。4. 项目部署与Tomcat调试从构建到浏览器访问4.1 本地环境版本搭配与Eclipse导入在导入项目前先确认环境避免把时间花在无意义的报错上。我的建议是JDK 1.8、Tomcat 8.5、MySQL 5.7或8.0用Eclipse IDE for Java EE版本导入工程。如果是更高版本的Tomcat遇到“Unsupported major.minor version”报错就是因为编译使用的JDK版本高于运行环境支持的版本这时候要么降低Tomcat版本要么调整项目的Compiler compliance level。表推荐环境组合与检查方式组件推荐版本检查命令/方式JDK1.8java -versionTomcat8.5 / 9.0查看Eclipse Server面板MySQL5.7 / 8.0mysql --versionEclipse2019-06或更新Help About Eclipse IDE导入步骤打开Eclipse菜单File Import选择Existing Projects into Workspace把ems目录选进去。如果项目没有Eclipse的.project文件Eclipse会不认这时需要改成Maven方式导入或者手动创建项目再复制源码。导入后先检查Project Facets里的Dynamic Web Module版本和Java版本是否对齐不然Tomcat发布时会显示“cannot be deployed”。4.2 jdbc.properties切换MySQL驱动与时区参数数据库配置文件一般叫jdbc.properties核心是驱动类和连接地址。当前很多项目还在用旧版驱动连接MySQL 8.0时会出现时区报错所以要把配置改成这样jdbc.drivercom.mysql.cj.jdbc.Driver jdbc.urljdbc:mysql://127.0.0.1:3306/ems?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai jdbc.usernameroot jdbc.password你的密码driver这一行是MySQL 8.0的驱动类名如果项目lib里还是5.x的mysql-connector-java.jar就必须把com.mysql.cj.jdbc.Driver换回com.mysql.jdbc.Driver同时这个URL里的serverTimezone参数在5.x下根本识别不了。密码不要写root的弱口令至少要和本地数据库一致。改完配置后可以先用命令行确认账号和密码能连上库mysql -uroot -p -h127.0.0.1 -e USE ems; SELECT COUNT(*) FROM employee;如果这个命令能查出数字说明账号、密码、数据都正常问题大概率还在Web应用的依赖或部署上。4.3 Tomcat启动时的经典报错与定位方式把项目加到Tomcat之后启动时Console里出现的报错往往集中在几类。这里列一份我在调试中经常对照的排查表报错关键词真实原因处理方式ClassNotFoundException: ContextLoaderListenerspring-web的jar没发布到WEB-INF/lib检查Deployment Assembly确认lib目录被包含java.sql.SQLException: Access denied for userjdbc.properties密码错误用命令行验证数据库连接The server time zone value is unrecognizedMySQL 8.0时区问题URL加serverTimezoneAsia/ShanghaiPort 8080 was already in use端口被占用换端口或释放原进程Invalid bound statement (not found)Mapper接口和XML的namespace不对应检查mapper XML的namespace是否等于接口全限定名在这些问题里Invalid bound statement出现频率很高通常是Mapper接口和XML中的namespace不匹配。Spring整合MyBatis后接口代理通过namespace找到对应SQL任何一个字母对不上都会在运行时抛异常。检查的中心点是SQL文件里mapper namespacecom.ems.mapper.EmployeeMapper这行必须和接口的全限定名完全一致。项目启动成功后浏览器访问http://localhost:8080/ems/看到登录页说明应用部署成功。此时去user表查初始账号SELECT * FROM user WHERE role admin;如果表里字段名不是role是role_id之类的就用SHOW COLUMNS FROM user;先看结构。项目说明.txt里通常也会写明默认管理员和员工的账号密码建议拿到手后第一时间改掉避免答辩时被人登录进去捣乱。4.4 用项目说明.txt快速复核部署步骤解压包的“项目说明.txt”不是摆设里面一般记录了运行环境、数据库导入方式、默认账号和注意事项。我会按这个顺序做核对先看它要求的数据库版本和自己本机是否一致再看它提到的是否需要额外导入“软件工具”里的jar包最后看账号密码。很多时候项目跑不起来就是因为跳过了解压包里的说明直接去改代码。部署这种事优先级最高的不是读代码而是先把环境复现出来。环境复现成功后再去跟源码效率高很多。5. 进阶给SSM人力系统加员工分页与答辩验证5.1 用PageHelper给员工列表加分页参数七大模块中员工管理是答辩时最常见的演示入口几十条数据不分页看不出问题一旦数据量拉到几百条页面就会卡顿。MyBatis生态里做分页最常用的是PageHelper使用方式非常轻量。在MyBatis配置文件中注册插件plugins plugin interceptorcom.github.pagehelper.PageInterceptor property namehelperDialect valuemysql/ property namereasonable valuetrue/ /plugin /pluginsService方法里先调PageHelper.startPage再执行查询PageHelper.startPage(pageNum, pageSize); ListEmployeeVO employeeList employeeMapper.selectEmployeesWithDept(); PageInfoEmployeeVO pageInfo new PageInfo(employeeList); return pageInfo;startPage后面的第一条查询会被自动拼接limit语句PageInfo里封装了总条数、总页数、当前页数等数据。reasonable参数设置为true的意思是请求页码超过最大页时自动纠正到边界避免空列表。分页参数pageNum在Controller里通过RequestParam(defaultValue 1)接收关键是要保证调用startPage之后只执行一条SQL查询如果中间又调了其他Mapper方法分页会被第二句查询覆盖这是常见的坑。5.2 密码加密的简易升级很多SSM毕设项目的用户表密码是明文存储。如果不打算大改可以保留原登录逻辑写一个工具类把原有账号密码做一次加密迁移。用commons-codec的MD5加盐String salt emsFixedSalt; String encrypted DigestUtils.md5Hex(username salt password);登录时把用户输入的内容按同一规则加密后再对比数据库。这种方式虽然不如BCrypt正规但能在不改表结构的情况下明显提升答辩演示的安全性。注意盐值不要写死在代码里可以挪到jdbc.properties里读取。5.3 答辩现场验证清单功能验证比项目介绍更能留住答辩老师的注意力。演示时先展示部门管理里新增一个部门再到员工管理里选择该部门并添加员工这一步覆盖了跨模块的数据关联然后考勤模块录入两条打卡记录最后在薪资模块看到月度汇总。这几个操作串起来相当于把七大模块里最核心的几张表走了一遍。可以在演示前用Java写一个JUnit测试直接调用Mapper查询语句把输出结果和页面展示结果比对确保数据库脚本和代码一致。代码层面检查三件事登录状态是否由拦截器控制、员工查询是否用了预编译占位符、薪资统计SQL的GROUP BY结果是否能手动验证。把这几件事在答辩现场演示一遍比嘴上讲框架结构更有说服力。本文还有配套的精品资源点击获取