基于JSP+Servlet的在线人力资源管理系统 - 源码深度解析

JavaJavaScriptHTMLCSSMySQLJSP+Servlet
2026-02-116 浏览

文章摘要

本项目是一款基于JSP+Servlet技术栈构建的在线人力资源管理系统,旨在将传统繁琐的人事管理工作流程化、电子化与集中化。其核心业务价值在于解决中小企业或部门在人事信息记录、流程审批及数据统计方面长期依赖纸质文件和Excel表格带来的效率低下、数据易出错、信息孤岛及历史档案难追溯等痛点。系统通过统...

在企业数字化转型浪潮中,人事管理作为企业运营的核心环节,其效率与准确性直接影响到组织效能。传统依赖纸质档案和分散电子表格的人事管理方式,普遍存在数据冗余、流程滞后、信息孤岛等问题。针对这一痛点,我们设计并实现了一套轻量级企业人事管理平台,该系统采用经典的JSP+Servlet架构,将人事管理的各个环节进行系统化整合,为中小企业提供了一套完整的人事信息化解决方案。

系统架构与技术栈

该平台采用典型的三层架构模式,展现层使用JSP技术实现动态页面渲染,业务逻辑层通过Servlet控制器处理各类请求,数据持久层基于JDBC实现与MySQL数据库的交互。这种分层架构确保了代码的清晰性和可维护性。

核心配置文件示例:

<!-- web.xml中Servlet配置 -->
<servlet>
    <servlet-name>EmployeeServlet</servlet-name>
    <servlet-class>com.hr.controller.EmployeeServlet</servlet>
</servlet>
<servlet-mapping>
    <servlet-name>EmployeeServlet</servlet-name>
    <url-pattern>/employee/*</url-pattern>
</servlet-mapping>

数据库连接采用连接池技术优化性能:

// 数据库连接工具类
public class DBUtil {
    private static DataSource dataSource;
    
    static {
        try {
            Context context = new InitialContext();
            dataSource = (DataSource) context.lookup("java:comp/env/jdbc/hrDB");
        } catch (NamingException e) {
            e.printStackTrace();
        }
    }
    
    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }
}

数据库设计亮点分析

组织架构表的树形结构设计

t_organization表采用经典的父ID设计实现组织层级管理:

CREATE TABLE `t_organization` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '组织ID',
  `name` varchar(55) DEFAULT NULL COMMENT '组织名称',
  `description` varchar(50) DEFAULT NULL COMMENT '描述',
  `p_id` int(11) DEFAULT NULL COMMENT '父级ID',
  `del` varchar(50) DEFAULT NULL COMMENT '删除标记',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=38 DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci COMMENT='组织表'

设计优势分析:

  • 层级管理:通过p_id字段实现无限级次的部门树形结构,支持大型企业的复杂组织架构
  • 软删除机制del字段采用标记删除而非物理删除,确保历史数据的完整性
  • 索引优化:主键ID自增设计提高插入性能,同时为p_id字段建立索引优化查询效率

请假申请表的业务流程设计

t_qingjiashenqing表完整记录了请假审批流程:

CREATE TABLE `t_qingjiashenqing` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '请假申请ID',
  `kaishishijian` varchar(50) DEFAULT NULL COMMENT '开始时间',
  `jieshushijian` varchar(50) DEFAULT NULL COMMENT '结束时间',
  `beizhu` varchar(5000) DEFAULT NULL COMMENT '备注',
  `yuangong_id` int(11) DEFAULT NULL COMMENT '员工ID',
  `shenhezhuangtai` varchar(50) DEFAULT NULL COMMENT '审核状态',
  `huifuxinxi` varchar(50) DEFAULT NULL COMMENT '回复信息',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci COMMENT='请假申请表'

业务流程完整性:

  • 状态跟踪shenhezhuangtai字段记录审批流程的各个状态(待审批、已批准、已拒绝)
  • 反馈机制huifuxinxi字段存储审批人的处理意见,形成完整的流程闭环
  • 大文本支持beizhu字段采用5000字符长度,满足详细请假事由的描述需求

请假申请界面

核心功能实现详解

员工信息管理模块

员工信息管理作为系统基础模块,实现了完整的CRUD操作:

// EmployeeServlet中的添加员工方法
public void addEmployee(HttpServletRequest request, HttpServletResponse response) 
        throws ServletException, IOException {
    try {
        Employee employee = new Employee();
        employee.setName(request.getParameter("name"));
        employee.setGender(request.getParameter("gender"));
        employee.setAge(Integer.parseInt(request.getParameter("age")));
        employee.setPosition(request.getParameter("position"));
        employee.setDepartmentId(Integer.parseInt(request.getParameter("departmentId")));
        
        EmployeeDAO dao = new EmployeeDAO();
        boolean success = dao.addEmployee(employee);
        
        if (success) {
            request.setAttribute("message", "员工添加成功");
        } else {
            request.setAttribute("error", "员工添加失败");
        }
        request.getRequestDispatcher("/employee_list.jsp").forward(request, response);
    } catch (Exception e) {
        e.printStackTrace();
        response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    }
}

// 分页查询员工列表
public void listEmployees(HttpServletRequest request, HttpServletResponse response) 
        throws ServletException, IOException {
    int page = 1;
    int pageSize = 10;
    
    if (request.getParameter("page") != null) {
        page = Integer.parseInt(request.getParameter("page"));
    }
    
    EmployeeDAO dao = new EmployeeDAO();
    List<Employee> employees = dao.getEmployeesByPage(page, pageSize);
    int totalCount = dao.getEmployeeCount();
    int totalPages = (int) Math.ceil((double) totalCount / pageSize);
    
    request.setAttribute("employees", employees);
    request.setAttribute("currentPage", page);
    request.setAttribute("totalPages", totalPages);
    request.getRequestDispatcher("/employee_list.jsp").forward(request, response);
}

员工信息管理界面

工资管理业务流程

工资管理模块实现了工资记录的创建、修改和查询功能:

// 工资计算业务逻辑
public class SalaryService {
    private SalaryDAO salaryDAO = new SalaryDAO();
    private AttendanceDAO attendanceDAO = new AttendanceDAO();
    
    public boolean calculateSalary(int employeeId, String month, int baseSalary) {
        try {
            // 获取该月出勤天数
            Attendance attendance = attendanceDAO.getAttendance(employeeId, month);
            if (attendance == null) {
                return false;
            }
            
            // 计算实际工资(基础工资/22 * 实际出勤天数)
            int actualSalary = baseSalary / 22 * attendance.getDays();
            
            Salary salary = new Salary();
            salary.setEmployeeId(employeeId);
            salary.setMonth(month);
            salary.setAmount(actualSalary);
            
            return salaryDAO.addSalary(salary);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
}

// 工资DAO数据访问层
public class SalaryDAO {
    public boolean addSalary(Salary salary) throws SQLException {
        String sql = "INSERT INTO t_gongzi (yuefen, jine, yuangong_id) VALUES (?, ?, ?)";
        
        try (Connection conn = DBUtil.getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            
            pstmt.setString(1, salary.getMonth());
            pstmt.setInt(2, salary.getAmount());
            pstmt.setInt(3, salary.getEmployeeId());
            
            return pstmt.executeUpdate() > 0;
        }
    }
    
    public List<Salary> getSalariesByEmployee(int employeeId) throws SQLException {
        String sql = "SELECT g.*, e.name as employee_name FROM t_gongzi g " +
                    "JOIN t_employee e ON g.yuangong_id = e.id WHERE g.yuangong_id = ?";
        
        List<Salary> salaries = new ArrayList<>();
        
        try (Connection conn = DBUtil.getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            
            pstmt.setInt(1, employeeId);
            ResultSet rs = pstmt.executeQuery();
            
            while (rs.next()) {
                Salary salary = new Salary();
                salary.setId(rs.getInt("id"));
                salary.setMonth(rs.getString("yuefen"));
                salary.setAmount(rs.getInt("jine"));
                salary.setEmployeeName(rs.getString("employee_name"));
                salaries.add(salary);
            }
        }
        return salaries;
    }
}

工资管理界面

请假审批工作流

请假审批模块实现了完整的业务流程管理:

// 请假审批Servlet
public class LeaveServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        
        String action = request.getParameter("action");
        
        switch (action) {
            case "apply":
                applyLeave(request, response);
                break;
            case "approve":
                approveLeave(request, response);
                break;
            case "reject":
                rejectLeave(request, response);
                break;
        }
    }
    
    private void applyLeave(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        try {
            LeaveApplication leave = new LeaveApplication();
            leave.setEmployeeId(Integer.parseInt(request.getParameter("employeeId")));
            leave.setStartTime(request.getParameter("kaishishijian"));
            leave.setEndTime(request.getParameter("jieshushijian"));
            leave.setRemark(request.getParameter("beizhu"));
            leave.setStatus("pending");
            
            LeaveDAO dao = new LeaveDAO();
            boolean success = dao.applyLeave(leave);
            
            if (success) {
                request.setAttribute("message", "请假申请提交成功,等待审批");
            } else {
                request.setAttribute("error", "请假申请提交失败");
            }
            request.getRequestDispatcher("/leave_result.jsp").forward(request, response);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    private void approveLeave(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        int leaveId = Integer.parseInt(request.getParameter("leaveId"));
        String reply = request.getParameter("huifuxinxi");
        
        LeaveDAO dao = new LeaveDAO();
        boolean success = dao.updateLeaveStatus(leaveId, "approved", reply);
        
        // 发送通知邮件或消息
        sendApprovalNotification(leaveId);
        
        response.sendRedirect("leave_management.jsp?message=审批完成");
    }
}

请假审批界面

考勤数据管理

考勤管理模块实现出勤记录的统计和分析:

// 考勤服务类
public class AttendanceService {
    public boolean recordAttendance(int employeeId, String month, int days) {
        String sql = "INSERT INTO t_chuqin (yuefen, tianshu, yuangong_id) VALUES (?, ?, ?) " +
                    "ON DUPLICATE KEY UPDATE tianshu = ?";
        
        try (Connection conn = DBUtil.getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            
            pstmt.setString(1, month);
            pstmt.setInt(2, days);
            pstmt.setInt(3, employeeId);
            pstmt.setInt(4, days);
            
            return pstmt.executeUpdate() > 0;
        } catch (SQLException e) {
            e.printStackTrace();
            return false;
        }
    }
    
    public Map<String, Object> getAttendanceReport(String department, String month) {
        Map<String, Object> report = new HashMap<>();
        
        String sql = "SELECT e.name, e.position, c.tianshu " +
                    "FROM t_chuqin c " +
                    "JOIN t_employee e ON c.yuangong_id = e.id " +
                    "JOIN t_organization o ON e.department_id = o.id " +
                    "WHERE o.name = ? AND c.yuefen = ?";
        
        try (Connection conn = DBUtil.getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            
            pstmt.setString(1, department);
            pstmt.setString(2, month);
            
            ResultSet rs = pstmt.executeQuery();
            List<Map<String, Object>> data = new ArrayList<>();
            int totalDays = 0;
            int employeeCount = 0;
            
            while (rs.next()) {
                Map<String, Object> record = new HashMap<>();
                record.put("name", rs.getString("name"));
                record.put("position", rs.getString("position"));
                record.put("days", rs.getInt("tianshu"));
                data.add(record);
                
                totalDays += rs.getInt("tianshu");
                employeeCount++;
            }
            
            report.put("data", data);
            report.put("averageDays", employeeCount > 0 ? totalDays / employeeCount : 0);
            report.put("totalEmployees", employeeCount);
            
        } catch (SQLException e) {
            e.printStackTrace();
        }
        
        return report;
    }
}

考勤管理界面

实体模型设计

系统采用标准的JavaBean设计模式,每个实体类都对应数据库中的表结构:

// 员工实体类
public class Employee {
    private int id;
    private String name;
    private String gender;
    private int age;
    private String position;
    private int departmentId;
    private String departmentName;
    private Date createTime;
    
    // 无参构造函数
    public Employee() {}
    
    // 带参构造函数
    public Employee(int id, String name, String gender, int age, 
                   String position, int departmentId) {
        this.id = id;
        this.name = name;
        this.gender = gender;
        this.age = age;
        this.position = position;
        this.departmentId = departmentId;
    }
    
    // Getter和Setter方法
    public int getId() { return id; }
    public void setId(int id) { this.id = id; }
    
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    
    // 其他getter/setter方法...
    
    @Override
    public String toString() {
        return "Employee{id=" + id + ", name='" + name + "', position='" + position + "'}";
    }
}

// 工资实体类
public class Salary {
    private int id;
    private String month;
    private int amount;
    private int employeeId;
    private String employeeName;
    
    // 构造函数和方法...
    public Salary() {}
    
    public Salary(int id, String month, int amount, int employeeId) {
        this.id = id;
        this.month = month;
        this.amount = amount;
        this.employeeId = employeeId;
    }
    
    // Getter和Setter方法...
}

功能展望与优化方向

1. 性能优化与缓存集成

当前系统在数据查询方面存在优化空间,建议引入Redis缓存层:

// 缓存优化示例
@Service
public class CachedEmployeeService {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    private static final String EMPLOYEE_CACHE_KEY = "employee:";
    private static final long CACHE_EXPIRE_HOURS = 24;
    
    public Employee getEmployeeWithCache(int employeeId) {
        String cacheKey = EMPLOYEE_CACHE_KEY + employeeId;
        
        // 先从缓存获取
        Employee employee = (Employee) redisTemplate.opsForValue().get(cacheKey);
        if (employee != null) {
            return employee;
        }
        
        // 缓存未命中,查询数据库
        employee = employeeDAO.getEmployeeById(employeeId);
        if (employee != null) {
            redisTemplate.opsForValue().set(cacheKey, employee, 
                CACHE_EXPIRE_HOURS, TimeUnit.HOURS);
        }
        
        return employee;
    }
}

2. 微服务架构改造

将单体应用拆分为微服务架构,提升系统可扩展性:

  • 人事核心服务:处理员工信息、组织架构等基础数据
  • 考勤服务:独立处理考勤数据和统计
  • 薪酬服务:专门负责工资计算和发放
  • 审批流服务:统一处理各类审批流程

3. 移动端适配与响应式设计

增加移动端支持,采用响应式前端框架:

<!-- 响应式页面示例 -->
<div class="container-fluid">
    <div class="row">
        <div class="col-12 col-md-6 col-lg-4">
            <div class="card employee-card">
                <div class="card-body">
                    <h5 class="card-title" th:text="${employee.name}"></h5>
                    <p class="card-text" th:text="${employee.position}"></p>
                </div>
            </div>
        </div>
    </div>
</div>

4. 大数据分析与报表增强

集成数据分析工具,提供更深入的HR数据分析:

  • 员工离职率预测分析
  • 薪酬结构合理性评估
  • 绩效考核趋势分析
  • 人力成本优化建议

5. 安全增强与审计日志

加强系统安全性,完善操作审计:

// 审计日志切面
@Aspect
@Component
public class AuditLogAspect {
    
    @Autowired
    private AuditLogService auditLogService;
    
    @Around("@annotation(RequiresAudit)")
    public Object auditMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object result = joinPoint.proceed();
        long endTime = System.currentTimeMillis();
        
        AuditLog log = new AuditLog();
        log.setOperation(joinPoint.getSignature().getName());
        log.setDuration(endTime - startTime);
        log.setOperator(getCurrentUser());
        log.setTimestamp(new Date());
        
        auditLogService.recordLog(log);
        
        return result;
    }
}

该人事管理平台通过系统化的功能设计和稳健的技术实现,为企业提供了完整的人

本文关键词
JSPServlet人力资源管理系统源码解析数据库设计

上下篇

上一篇
没有更多文章
下一篇
没有更多文章