简介:这份资源是面向计算机专业学生与Java Web开发者的企业人事管理系统完整项目包,基于JSP技术与SSM(Spring、SpringMVC、MyBatis)框架实现,覆盖人事信息录入、查询、修改、删除以及考勤、薪资管理等核心业务,可作为毕业设计参考或企业级开发入门案例。压缩包共987个文件,约11.32MB,其中96个java源文件与46个jsp页面构成系统主体,125个css、242个js及大量png、gif、jpg等图片资源支撑前端界面,另有17个xml配置、2个sql脚本及doc论文文档,便于快速搭建数据库与理解模块划分。目前已有23人学习下载。资源包含完整源码、db.sql数据库结构、说明文档与论文,读者可据此掌握需求分析、系统设计、编码实现到测试的完整流程,理解员工信息管理、考勤记录、薪酬计算等模块的具体实现方式,并借鉴规范代码提升JSP与SSM框架的实际应用能力。
1. 从一份 SSM+JSP 人事系统压缩包说起:谁需要它,能解决什么
如果你手里正躺着一个名为ssm158企业人事管理系统的设计与实现+jsp(文档+源码)_kaic.zip的压缩包,或者你正在为课程设计、毕业设计找一个能跑通、能讲清楚、能改得动的企业人事管理系统,那这篇笔记就是写给你的。SSM 指的是 Spring + SpringMVC + MyBatis 这套经典组合,JSP 负责视图层渲染,企业人事管理系统则是把员工档案、部门岗位、考勤请假、薪资合同这些 HR 日常事务搬到 Web 端。它不追求高并发微服务,核心价值在于业务闭环完整、代码结构清晰、部署门槛低,一台普通笔记本就能跑起来。适合三类人:一是需要交付毕设或课设的学生,二是想拿一个真实业务练手 SSM 的初级开发者,三是小团队想快速搭一个内部人事台账的负责人。接下来我会按「先跑通、再拆解、后避坑」的顺序,把这份压缩包背后的技术选型、落地步骤和常见翻车点讲透。
2. 环境搭建与项目导入:把压缩包变成能访问的登录页
拿到压缩包后第一件事不是急着看代码,而是先把运行环境对齐。SSM+JSP 项目对版本比较敏感,尤其是 JDK、Tomcat 和 MySQL 三者的搭配,选错了会在启动阶段直接报错,连登录页都看不到。这一章的目标很明确:让你在本地把项目跑起来,浏览器能打开登录界面,并且能用管理员账号登进去。
2.1 JDK、Tomcat、MySQL 的版本搭配与安装顺序
我一般推荐的组合是 JDK 8、Tomcat 8.5、MySQL 5.7。原因很实际:SSM 项目里大量使用javax.servlet包,Tomcat 9 之后部分 API 有调整,JSP 页面里的隐式对象处理偶尔会出兼容问题;MySQL 8 的驱动类名和连接串参数与 5.7 不同,如果项目里的jdbc.properties没同步改,启动就会报Communications link failure。安装顺序建议先 JDK,再 MySQL,最后 Tomcat,因为 Tomcat 启动时会去连数据库,数据库没准备好会拖慢排查节奏。
安装完成后做三件事验证:命令行执行java -version确认是 1.8;MySQL 用mysql -u root -p能登录;Tomcat 的bin目录下执行startup.bat(Windows)或startup.sh(Linux),浏览器访问http://localhost:8080能看到 Tomcat 默认页。这三步都过了,再动项目。
2.2 数据库导入与 jdbc.properties 的四个必改参数
压缩包里通常有一个sql文件夹,里面是建库建表的.sql文件。导入命令如下:
# 登录 MySQL 后执行,先建库再导入 mysql -u root -p CREATE DATABASE hrms DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE hrms; SOURCE /path/to/your_project/sql/hrms.sql;导入完成后,找到项目src/main/resources下的jdbc.properties,重点改四个参数:
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/hrms?useUnicode=true&characterEncoding=utf8&useSSL=false jdbc.username=root jdbc.password=你的数据库密码jdbc.driver如果是 MySQL 8 要改成com.mysql.cj.jdbc.Driver;jdbc.url里的hrms必须和建库名一致,useSSL=false在本地环境建议保留,否则会有安全警告拖慢连接;username和password填你本机 MySQL 的真实账号。改完这四个参数,数据库层基本就通了。
2.3 IDEA 导入项目与 Tomcat 部署的完整操作
用 IDEA 导入时选择File -> Open,指向解压后的项目根目录,不要选成里面的子文件夹。导入后等待 Maven 依赖下载完成,如果pom.xml里有红色报错,先检查 Maven 仓库镜像是否配置了国内源。依赖拉完后配置 Tomcat:
第一步,Run -> Edit Configurations,点左上角+选Tomcat Server -> Local。 第二步,在Server标签页确认Application server指向你安装的 Tomcat 目录。 第三步,在Deployment标签页点+选Artifact,添加项目名:war exploded。 第四步,把Application context改成/或者/hrms,这个路径决定你访问时的 URL。
启动后如果控制台没有报错,浏览器访问http://localhost:8080/(或你设置的 context),应该能看到登录页。默认管理员账号一般在sql文件里有注释,常见的是admin/123456或admin/admin,登进去之后先别急着改代码,把员工列表、部门管理这几个页面点一遍,确认数据能正常增删改查。
3. SSM 三层架构在人事系统里的真实分工
项目跑通之后,很多人会直接扎进 JSP 页面改样式,结果改着改着发现数据不对,又回头找 Controller,效率很低。这一章把 SSM 三层在人事系统里的职责边界讲清楚,让你知道改一个功能应该动哪几个文件。企业人事管理系统的业务相对规整,员工、部门、岗位、考勤、薪资这几块基本都是「Controller 收请求 → Service 处理逻辑 → Mapper 操作数据库 → JSP 渲染结果」的链路。
3.1 Controller 层:请求映射与参数接收的常见写法
以员工查询为例,Controller 里通常是这样:
@Controller @RequestMapping("/employee") public class EmployeeController { @Autowired private EmployeeService employeeService; // 分页查询员工列表,page 和 limit 由前端表格组件传入 @RequestMapping("/list") @ResponseBody public Map<String, Object> list(@RequestParam(defaultValue = "1") Integer page, @RequestParam(defaultValue = "10") Integer limit, String keyword) { Map<String, Object> result = new HashMap<>(); List<Employee> list = employeeService.queryPage(page, limit, keyword); int total = employeeService.queryCount(keyword); result.put("code", 0); result.put("msg", "success"); result.put("count", total); result.put("data", list); return result; } }这段代码的关键点有三个:@RequestMapping("/list")决定了前端请求路径是/employee/list;@RequestParam的defaultValue保证不传参时也有默认值,避免空指针;返回的 Map 结构里code、msg、count、data是 Layui 表格组件约定的格式,如果你换了前端框架,这四个字段名要跟着改。参数说明上,page是当前页码,limit是每页条数,keyword是模糊搜索关键词,对应员工姓名或工号。
3.2 Service 与 Mapper 层:事务边界和 SQL 映射文件的位置
Service 层负责业务逻辑和事务控制,比如新增员工时要同时写入员工基本信息和入职记录,这两步必须在一个事务里:
@Service @Transactional public class EmployeeServiceImpl implements EmployeeService { @Autowired private EmployeeMapper employeeMapper; @Override public void addEmployee(Employee employee) { // 先插入员工主表 employeeMapper.insert(employee); // 再插入入职记录,employee.getId() 由 MyBatis 主键回填拿到 employeeMapper.insertEntryRecord(employee.getId(), employee.getEntryDate()); } }@Transactional加在类上表示所有 public 方法都纳入事务,如果只想给特定方法加,就移到方法上。Mapper 层对应的是resources/mapper下的 XML 文件,比如EmployeeMapper.xml,里面的namespace必须和 Java 接口的全限定名一致,id必须和方法名一致,这两处写错会在启动时报Invalid bound statement。
3.3 JSP 页面如何拿到后端数据并渲染表格
JSP 里取数据主要靠 EL 表达式和 JSTL 标签。如果是同步渲染,Controller 返回ModelAndView或往Model里塞数据,JSP 里直接${employee.name}就能取到。但人事系统里表格通常用异步加载,JSP 只负责提供容器:
<table id="employeeTable" lay-filter="employeeTable"></table> <script> layui.use(['table'], function () { var table = layui.table; table.render({ elem: '#employeeTable', url: '/employee/list', // 对应 Controller 的 @RequestMapping page: true, cols: [[ {field: 'id', title: 'ID', width: 60}, {field: 'name', title: '姓名', width: 100}, {field: 'deptName', title: '部门', width: 120}, {field: 'position', title: '岗位', width: 120}, {field: 'entryDate', title: '入职日期', width: 120} ]] }); }); </script>这里url必须和 Controller 的映射路径完全对应,cols里的field要和后端返回的 JSON 字段名一致。如果表格一直显示「数据接口请求异常」,先打开浏览器 F12 看 Network 里/employee/list的返回内容,多半是后端抛了异常或者返回格式不对。
4. 员工信息与图片上传:JSP 个人信息展示页面的落地细节
人事系统里员工头像、身份证扫描件、合同附件这些都属于图片上传场景。热搜里提到的「jsp个人信息展示页面」和「jsp图片如何对坐标定位」,本质上是在问两件事:图片怎么存、怎么在页面上按位置显示。这一章把上传、存储、展示、定位这条链路拆开讲。
4.1 头像上传的 Controller 写法与存储路径规划
上传接口一般放在FileController或EmployeeController里:
@RequestMapping("/upload") @ResponseBody public Map<String, Object> upload(@RequestParam("file") MultipartFile file, HttpServletRequest request) throws IOException { Map<String, Object> result = new HashMap<>(); if (file.isEmpty()) { result.put("code", 1); result.put("msg", "文件为空"); return result; } // 获取项目部署的真实路径,拼上 upload 目录 String realPath = request.getServletContext().getRealPath("/upload"); File dir = new File(realPath); if (!dir.exists()) { dir.mkdirs(); } // 用时间戳防止文件名冲突 String fileName = System.currentTimeMillis() + "_" + file.getOriginalFilename(); file.transferTo(new File(dir, fileName)); result.put("code", 0); result.put("msg", "上传成功"); result.put("url", request.getContextPath() + "/upload/" + fileName); return result; }参数说明:MultipartFile由 SpringMVC 自动封装,前提是配置文件里配了MultipartResolver;realPath拿到的是 Tomcat 工作目录下的真实路径,项目重新部署后这个目录可能被清空,生产环境建议改成外部固定目录。返回的url是相对路径,前端拿到后直接赋给img的src即可。
4.2 图片坐标定位的两种实现:CSS 绝对定位与 canvas 标注
「jsp图片如何对坐标定位」这个需求,通常出现在员工证件照裁剪或者合同签署位置标注场景。第一种做法是 CSS 绝对定位,把图片放在一个position: relative的容器里,标注点用position: absolute加left、top控制:
<div style="position: relative; display: inline-block;"> <img src="/upload/contract.jpg" style="width: 600px;"> <span style="position: absolute; left: 120px; top: 80px; color: red;">签名处</span> </div>第二种做法是 canvas 绘制,适合需要保存坐标数据的场景。点击 canvas 时用getBoundingClientRect计算相对坐标:
var canvas = document.getElementById('markCanvas'); canvas.addEventListener('click', function (e) { var rect = canvas.getBoundingClientRect(); var x = e.clientX - rect.left; // 相对 canvas 左上角的 x var y = e.clientY - rect.top; // 相对 canvas 左上角的 y console.log('标注坐标:', x, y); });两种方式的差别在于:CSS 定位适合静态展示,坐标写死在页面里;canvas 适合交互标注,坐标可以存进数据库,下次打开时再画出来。选哪种取决于你的业务是否需要「记住」这些坐标。
4.3 个人信息展示页面的字段拼装与权限过滤
个人信息展示页面不是简单把数据库字段全铺上去,要做两件事:字段拼装和权限过滤。字段拼装是指把部门 ID 转成部门名称、把状态码转成中文描述,这些通常在 Service 层用 Map 或 VO 对象组装好再返回。权限过滤是指普通员工只能看自己的信息,HR 能看所有人的,实现方式一般是在 Controller 里从 session 取当前用户角色:
@RequestMapping("/info") public String info(Model model, HttpSession session) { User user = (User) session.getAttribute("loginUser"); Employee emp; if ("admin".equals(user.getRole())) { emp = employeeService.getById(user.getEmpId()); } else { emp = employeeService.getById(user.getEmpId()); } model.addAttribute("emp", emp); return "employee/info"; }这里session里的loginUser是登录时存进去的,如果没做登录拦截,直接访问/employee/info会空指针。所以配套的拦截器或过滤器不能少,否则权限过滤就是空谈。
5. 避坑与排查:SSM+JSP 人事系统最常见的五类翻车
这一章记录的是我在部署和调试这类项目时反复遇到的坑,每一条都按「现象 → 原因 → 解决」写,你遇到问题时可以直接对号入座。
5.1 启动报 404:路径对了但页面就是不出来
现象:Tomcat 启动无报错,访问http://localhost:8080/显示 404。 原因:多半是Application context设置和访问路径不匹配,或者web.xml里DispatcherServlet的url-pattern配成了/但spring-mvc.xml没扫描到 Controller 包。 解决:先看 IDEA 控制台 Deployment 标签页的Application context值,如果是/hrms就要访问/hrms;再检查spring-mvc.xml里的<context:component-scan base-package="com.xxx.controller"/>包名是否和实际一致。
5.2 数据库连接失败:Communications link failure
现象:启动时控制台刷Communications link failure或Access denied for user。 原因:jdbc.properties里的账号密码不对,或者 MySQL 服务没启动,或者 MySQL 8 用了旧驱动类名。 解决:命令行先mysql -u root -p确认能登录;再看jdbc.url的端口是不是 3306;MySQL 8 把jdbc.driver改成com.mysql.cj.jdbc.Driver,并在 URL 后加&serverTimezone=Asia/Shanghai。
5.3 中文乱码:员工姓名存进去变成问号
现象:新增员工后,列表里姓名显示???。 原因:数据库建库时字符集不是utf8mb4,或者 JSP 页面pageEncoding没设对,或者连接串没加characterEncoding=utf8。 解决:建库语句用DEFAULT CHARACTER SET utf8mb4;JSP 头部加<%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %>;jdbc.url里保留useUnicode=true&characterEncoding=utf8。
5.4 图片上传后访问 404:文件存了但浏览器拿不到
现象:上传接口返回成功,但img的src打开是 404。 原因:文件存到了 Tomcat 工作目录,但项目重新部署后目录被清空;或者存到了项目外部目录但 Tomcat 没有配置虚拟路径映射。 解决:开发阶段可以存在getRealPath("/upload")下,但每次重新部署要重新上传;更稳妥的做法是在 Tomcat 的server.xml里配<Context docBase="外部目录" path="/upload"/>,或者用 SpringMVC 的<mvc:resources>映射外部路径。
5.5 事务不生效:新增员工成功但入职记录没写进去
现象:调用新增员工接口,员工表有数据,入职记录表为空,且没有报错。 原因:@Transactional加在了 Controller 上而不是 Service 上,或者 Service 类没有被 Spring 扫描到,或者异常被 catch 了没抛出去。 解决:确认@Transactional在 Service 实现类上;确认spring-service.xml里开启了<tx:annotation-driven/>;如果方法里用了 try-catch,要在 catch 里throw new RuntimeException(e)才能触发回滚。
6. 从能跑到好用:三个让这套系统更抗造的进阶习惯
项目跑通、功能点完,很多人就停在这里了。但如果你要把这套 SSM+JSP 人事系统拿去答辩、交付或者真正给团队用,还有三个习惯值得养成。第一个是给关键操作加日志,尤其是登录、新增、删除这三类,用log4j或slf4j在 Service 层打点,出问题时不用靠猜。第二个是把jdbc.properties里的明文密码换成加密串,配合PropertyPlaceholderConfigurer解密,避免源码泄露时数据库直接裸奔。第三个是给列表查询加索引,员工表的name、dept_id、entry_date这三个字段在数据量过万后查询会明显变慢,建联合索引能救回来。
验证方法很简单:用EXPLAIN看查询计划,如果type是ALL就说明走了全表扫描,加索引后应该变成ref或range。我自己的习惯是每次改完 Mapper 的 SQL,都顺手EXPLAIN一下,这个动作花不了十秒,但能避免上线后被慢查询拖垮。另外,JSP 页面里的<script>块尽量抽到单独的.js文件,一来浏览器能缓存,二来改样式时不会误伤 Java 代码。这套系统本身不复杂,真正拉开差距的是这些收尾的细节。希望帮到你。
本文还有配套的精品资源,点击获取