简介这是面向Java开发学习者与初、中级程序员的考勤管理系统完整源码资源覆盖员工管理、考勤打卡、审批申请、会议与固定资产管理等常见业务模块。压缩包共2000个文件、大小55MB其中67个Java源文件对应核心业务逻辑与接口实现500个JavaScript配合HTML负责前端交互1336个Markdown文档可用于逐文件阅读和项目理解其余JSON、XML、YAML、SQL主要承担配置管理、数据交换与数据库初始化任务。已有170人学习浏览或下载适合用来练习企业级Java项目结构、领会MVC分层与前后端协作方式。资源内包含CheckService、EmployeeService、TaskService等关键类以及Controller层接口和实体定义可帮助快速定位业务代码借助SQL文件即可搭建本地运行环境是课程设计或毕业设计环节比较实用的参考资料。1. 这个Java考勤管理系统源码包先判断值不值得跑再谈怎么跑很多人下载了「Java项目考勤管理系统」源码包解压之后发现并不是开箱即用而是一堆看不懂的目录和连续报错。这类zip大概率是一个SSM或Servlet/JSP结构的传统Web项目附带数据库脚本和JSP页面解决的是公司或学校日常打卡、请假、统计的问题。它适合三类人做课设的学生、需要快速搭后台的初级开发者、想从零学一个完整Java Web项目的人。这篇笔记会告诉你先看哪三个文件、怎么把数据库和Tomcat对齐、核心业务逻辑卡在哪儿以及最容易翻车的五个位置。目标只有一个让你拿到zip后能判断它能不能跑并且真的把它跑起来。2. 拿到zip之后先看清技术栈和文件结构再决定环境怎么配源码包最让人头疼的不是代码本身而是你根本不知道它基于什么技术栈写的。JDK版本、Tomcat版本、数据库版本全由技术栈决定所以解压之后别急着打开IDE先花十分钟确认项目形态。2.1 用pom.xml判断技术栈SSM还是SSH决定JDK版本先到命令行里看一眼根目录。老考勤系统源码包通常有两种形态Maven工程和非Maven工程。Maven工程根目录有pom.xml非Maven工程有.classpath和.project。第一步先确认形态因为后续所有命令都依赖它走错路线会浪费很多时间。# 解压后第一件事看清楚根目录结构 ls -la # 如果存在 pom.xml这是 Maven 工程 # 如果存在 .classpath 和 .project这是 Eclipse 传统工程ls -la能看到隐藏文件防止漏判。拿到Maven工程后面可以用mvn命令一键打包拿到传统工程就要靠IDE的Export War功能这两条路线完全不同。我一般会优先把传统工程转成Maven工程不是必须但后续依赖管理省事很多。!-- pom.xml 里面搜这几个关键依赖判断是 SSM 还是 SSH -- dependency groupIdorg.springframework/groupId artifactIdspring-webmvc/artifactId version4.3.18.RELEASE/version /dependency dependency groupIdorg.mybatis/groupId artifactIdmybatis/artifactId version3.4.6/version /dependency看到spring-webmvc加mybatis就是SSM这是考勤类源码包里最常见的组合如果看到struts2-core和hibernate就是SSH如果只有javax.servlet和jsp-api就是纯Servlet/JSP项目。版本号不用背但要注意Spring 4.x要求JDK 8Spring 5.x可以配JDK 11。很多人翻车是因为电脑装的是JDK 17老项目直接启动报错所以第一个结论是JDK版本跟着Spring走别跟着自己习惯走。2.2 典型的源码包目录每个文件夹是干什么的考勤系统的目录结构大同小异先认识目录再动手改代码比在IDE里乱点高效得多。下面这棵树是这类源码包里最常见的组织方式你的zip里可能略有差异但核心分层基本一致。src/main/java/com/company/attendance ├── controller # 前端请求入口返回页面或JSON ├── service # 业务逻辑打卡、统计都在这层 ├── dao # MyBatis的Mapper接口只定义方法 ├── entity # 实体类和数据库表字段一一对应 └── util # 工具类日期处理、MD5加密、Excel导出 src/main/resources ├── mapper # MyBatis的XML文件真正的SQL写在这里 ├── jdbc.properties └── spring-mvc.xml / spring-mybatis.xml src/main/webapp ├── WEB-INF/jsp # JSP页面登录页、打卡页、管理页 └── static # JS、CSS、图片 考勤.sql # 数据库初始化脚本通常放在项目根目录或sql目录先找src/main/resources里的jdbc.properties和根目录的考勤.sql这两个文件决定系统能不能连上数据库。如果源码包是Eclipse传统工程目录可能是src和WebContent作用对应上面的src/main/java和src/main/webapp。实体类、Mapper、Service的三层结构是通用套路后面改业务逻辑时按controller到service到dao到mapper XML的顺序找代码不要从JSP页面倒推。2.3 环境版本怎么配一张表对齐JDK、MySQL、Tomcat环境版本配错系统连启动都到不了。下面这张表是我处理这类老项目时常用的基准配置能避开大多数兼容性问题。组件推荐版本理由JDK1.8老源码基于JDK8避免新版本API删改MySQL5.7最稳8.0要额外改驱动和时区Maven3.6.x和JDK8兼容性最好Tomcat8.5Spring 4.x最配8.59.0也能用IDEIDEA 2020以上跑老项目比Eclipse省心这不是绝对的但按这个表配能避开大多数环境问题。我的一般做法是先打开pom.xml看spring版本4.x直接JDK8加Tomcat8.55.x可以用JDK11加Tomcat9。如果电脑已经装了MySQL 8.0也不用重装后面改JDBC驱动和URL参数就能兼容具体写法在第四章。还要注意一点源码包里如果用了c3p0或druid连接池配置文件的键名不一样优先看spring-mybatis.xml里引用了哪个properties文件别改错地方。3. 核心业务拆解登录、打卡、统计这三段代码改了才算会环境跑通只是开始考勤系统的核心价值在三段逻辑登录怎么区分角色、打卡怎么判迟到早退、统计怎么聚合出报表。把这三段读懂简历上就能写「独立完成考勤模块改造」而不是「运行了别人的项目」。3.1 登录与角色一个用户表字段决定员工和管理员用户表是整套系统的地基。看表结构就能明白所谓管理员和员工在数据库层面只是role字段不同页面权限靠登录后存的Session判断。CREATE TABLE t_user ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(32) NOT NULL, password VARCHAR(64) NOT NULL, role TINYINT NOT NULL DEFAULT 0, dept_id INT, real_name VARCHAR(32) );role字段是关键0代表员工1代表管理员。很多源码包还会加一个status字段控制账号是否禁用修改密码后强制重新登录就是靠它。看表结构时顺便看看有没有dept_id如果存在部门字段说明系统还带了部门管理页面改动范围比预期更大。// 登录校验的常见写法查库、比密码、写Session public User login(String username, String password) { User user userDao.findByUsername(username); if (user null) { return null; } // 老项目普遍用MD5因为当年没有Bcrypt String md5 DigestUtils.md5DigestAsHex(password.getBytes()); if (user.getPassword().equals(md5)) { session.setAttribute(loginUser, user); return user; } return null; }这段逻辑里没有盐值是历史遗留问题。改造时建议把MD5换成BCrypt但要注意换加密方式前必须先迁移现有账号否则老用户全部登录失败。Session的key建议改成LOGIN_USER这样的常量避免前端和后端拼写不一致。真正控制权限的代码通常不在login方法里而在一个LoginInterceptor过滤器里它拦截所有请求判断Session是否为空这是看代码时最容易漏掉的部分。3.2 打卡逻辑上班时间写在配置里别写死在代码中打卡表记录每次上下班的结果。这张表设计的关键是work_date按天一条记录check_in和check_out是当天两次打卡时间。很多老系统坑在同一人同一天可能插多条记录导致统计翻倍。CREATE TABLE t_attendance ( id INT PRIMARY KEY AUTO_INCREMENT, user_id INT, work_date DATE, check_in DATETIME, check_out DATETIME, status TINYINT DEFAULT 0 );status字段是打卡结果0正常、1迟到、2早退、3缺卡。如果表里已经建了(user_id, work_date)的唯一索引说明原作者考虑过重复打卡问题如果没有插入前要先用findByUserIdAndDate判断当天是否已有记录。// 打卡记录的生成先查当天有没有没有再插入 Attendance existing attendanceDao.findByUserIdAndDate(userId, LocalDate.now()); if (existing null) { Attendance record new Attendance(); record.setUserId(userId); record.setWorkDate(LocalDate.now()); // 上班时间从配置文件读取方便不同公司调整 String startTime config.getProperty(work.start.time, 09:00); if (LocalTime.now().isAfter(LocalTime.parse(startTime))) { record.setStatus(1); // 迟到 } else { record.setStatus(0); // 正常 } attendanceDao.insert(record); }work.start.time是核心参数常见值有09:00和08:30放在config.properties里比写死在Java里好维护。这段代码只处理了上班打卡下班打卡需要另写一段update逻辑判断是否早退通常用check_out当前时间和公司规定的下班时间work.end.time比较。跨天加班是传统考勤系统的老大难源码包一般直接记当天时间不处理凌晨下班这一点在答辩或复盘时要能讲得清楚。3.3 考勤统计一条SQL出月报再用POI导出Excel统计模块是考勤系统的门面领导看得最多。月报的核心是一条聚合SQL把每个人当月迟到、早退、缺卡次数算出来。SELECT u.real_name, COUNT(a.id) AS should_days, SUM(CASE WHEN a.status 1 THEN 1 ELSE 0 END) AS late_days, SUM(CASE WHEN a.status 2 THEN 1 ELSE 0 END) AS leave_early_days, SUM(CASE WHEN a.status 3 THEN 1 ELSE 0 END) AS missing_days FROM t_user u LEFT JOIN t_attendance a ON u.id a.user_id AND a.work_date BETWEEN #{startDate} AND #{endDate} GROUP BY u.id, u.real_nameLEFT JOIN保证没打过卡的人也能出现CASE WHEN把status转成计数列。should_days用COUNT(a.id)统计实际有记录的天数如果要算应出勤天数需要排除周末和节假日那是另一个复杂话题源码包一般不做。参数startDate和endDate在调用时传当月第一天和最后一天注意MyBatis里BETWEEN是闭区间传参时别把边界算错。// 导出Excel老项目常用HSSFWorkbook支持.xls HSSFWorkbook workbook new HSSFWorkbook(); HSSFSheet sheet workbook.createSheet(考勤月报); Row header sheet.createRow(0); header.createCell(0).setCellValue(姓名); // 省略填充数据的循环 response.setContentType(application/vnd.ms-excel;charsetutf-8); response.setHeader(Content-Disposition, attachment;filename URLEncoder.encode(考勤月报.xls, UTF-8)); workbook.write(response.getOutputStream());HSSFWorkbook只能生成.xls一张表超过65535行会报错考勤系统一般不会达到这个量。如果源码包用了POI 4.0以上版本推荐换成XSSFWorkbook生成.xlsx。中文文件名统一用URLEncoder.encode处理否则浏览器下载时显示乱码。这段代码里response.getOutputStream()用完不需要手动关容器会管理但workbook建议放在finally块里调用close()。4. 部署运行数据库、打包、Tomcat三步把页面点亮到这一步我们把「源码」变成「能访问的系统」。常见做法分三步改数据库配置、打包、部署到Tomcat。每一步都有参数要交代清楚漏一个就起不来。4.1 数据库连接配置文件driver、url、用户名密码逐项说数据库配置集中在jdbc.properties或application.properties里具体看spring-mybatis.xml引用了哪个文件。先改这里其他代码都不用动。# jdbc.properties 中最关键的四个配置 jdbc.drivercom.mysql.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/attendance?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai jdbc.usernameroot jdbc.password123456四个配置里最容易被坑的是driver和url。MySQL 5.7用com.mysql.jdbc.DriverMySQL 8.0必须改com.mysql.cj.jdbc.Driver。url里的serverTimezoneAsia/Shanghai是8.0的硬性要求不加直接报时区错误useSSLfalse是为了省掉SSL握手警告。数据库名是attendance如果建库时用了别的名字这里要同步改。如果源码包里同时存在多个properties文件比如jdbc.properties和db.properties先看spring-mybatis.xml里context:property-placeholder指向哪个以它为准。4.2 Maven打包与Tomcat部署两条路线选一条打包部署有两条路Maven工程走命令行非Maven工程走IDE导出。我一般优先走命令行因为日志看得清楚出问题也容易定位。# 路线一Maven工程命令行打包 mvn clean package -DskipTests ls target/attendance.war # 把war包丢到Tomcat的webapps目录 cp target/attendance.war /opt/tomcat/webapps/ /opt/tomcat/bin/startup.sh # 查看启动日志 tail -f /opt/tomcat/logs/catalina.out-DskipTests跳过测试老项目测试代码经常有问题先跳过能省时间。war包名决定访问路径attendance.war对应http://localhost:8080/attendance/。如果IDE里直接配Tomcat运行就不用手动拷贝war但要保证Artifact是war exploded模式否则改JSP要重新打包。启动后必须看catalina.out不是看IDE的Console很多后台异常只写在日志里。Windows下路径类似cp换成copystartup.sh换成startup.bat。4.3 初始化数据库与默认账号SQL脚本不是双击运行就完事源码包自带的考勤.sql通常只负责建表和插数据不自动建库。很多人直接双击导入结果一堆Unknown database报错。# 先建库再导入脚本顺序错了会报错 mysql -uroot -p -e CREATE DATABASE attendance DEFAULT CHARACTER SET utf8mb4; mysql -uroot -p attendance 考勤.sql # 查看默认用户 mysql -uroot -p -e SELECT id, username, role FROM attendance.t_user;用utf8mb4而不是utf8否则插入生僻字或特殊符号会报错。导入后查一下用户表默认账号普遍是admin密码是admin或123456偶尔也有admin/admin888。这里有个建议跑通后立刻改密码防止演示时被别人登进去改数据。改密码的命令是UPDATE t_user SET password MD5(新密码) WHERE username admin;注意老系统的密码字段存的就是MD5值直接UPDATE字符串会登录失败。5. 避坑指南跑通考勤系统的五个典型翻车点跑通这个项目花在调试环境上的时间往往比读代码还多。下面是几个我帮人排查时反复遇到的坑每一条都按现象、原因、解决三段写遇到直接对号入座。5.1 数据库连不上Access denied和时区报错现象Tomcat启动时日志里出现Access denied for user rootlocalhost或者Communications link failure应用直接起不来。原因前者是用户名密码对不上或者密码里带了看不见的空格后者常见于MySQL 8.0没加serverTimezone参数以及com.mysql.jdbc.Driver这个老驱动不识别新的认证方式。解决先到命令行执行mysql -uroot -p确认root密码真实可用然后把驱动改为com.mysql.cj.jdbc.DriverURL加上serverTimezoneAsia/Shanghai。最后检查项目里是否有多个配置文件同时存在漏改其中一个就会连错库。遇到过有人改了jdbc.properties但spring-mybatis.xml里硬编码了连接参数根本没引用properties文件这种要直接改XML里的值。5.2 打卡时间错乱新打卡记录的时间比实际晚8小时现象早上9点打卡数据库check_in却存成了17:00或者前一天21:00月报统计全部失误。原因JVM默认时区、MySQL连接时区、操作系统时区三者不一致。老项目写日期时用new Date()如果服务器系统时区是UTCMySQL的serverTimezone又没指定就会差8小时。解决JDBC URL加serverTimezoneAsia/ShanghaiTomcat启动脚本catalina.sh里加一行JAVA_OPTS$JAVA_OPTS -Duser.timezoneGMT08最后确认数据库SELECT NOW()输出的是北京时间。改完记得重连数据库并重启Tomcat。如果旧数据已经错乱写一条UPDATE按小时差批量修正别手动一条条改。5.3 导出Excel乱码文件名问号加内容乱码现象点击「导出月报」下载的xls文件文件名是????.xls打开后中文列名全是乱码。原因response.setContentType和Content-Disposition里没有处理编码POI写中文时也没有统一字符集。老代码里直接用filename考勤月报.xls浏览器按UTF-8解码失败。解决设置Header时用URLEncoder.encode(考勤月报.xls, UTF-8)Content-Type指定为application/vnd.ms-excel;charsetutf-8。如果乱码出现在单元格内容而不是文件名检查JSP页面pageEncoding是否为UTF-8以及连接数据库的URL里characterEncodingutf8是否生效。还有一个小坑encode之后文件名里的空格会变成最好再把加号替换成%20两种浏览器行为不同。5.4 页面404或样式全丢DispatcherServlet拦截了静态资源现象访问登录页能出HTML但页面没有CSS所有按钮光秃秃或者直接访问某个JSP返回404。原因Spring MVC的DispatcherServlet把请求都接管了spring-mvc.xml里没有配置mvc:resources放行/static/**导致JS、CSS全部被拦截。另一个常见原因是war包名和访问路径不一致你用/attendance/访问但部署上下文是/ROOT路径自然不对。解决在spring-mvc.xml里加mvc:resources mapping/static/** location/static//同时确认浏览器F12看到的资源请求前缀和当前应用上下文一致。如果是IDE部署检查Tomcat配置里Application context是不是/attendance多一个斜杠少一个斜杠都404。还有种情况是JSP文件直接放在webapp根目录而不是WEB-INF/jsp下访问路径要跟着调整。5.5 改了代码不生效Tomcat热部署失效和浏览器缓存现象改了JSP页面或者Java代码刷新页面还是旧内容甚至重启Tomcat也没变。原因IDEA里只做了「编译」没做「重新构建」或者Tomcat部署的是war包而不是exploded目录浏览器对静态资源有强缓存CSS和JS改了但文件名没变刷新也不拉新内容。解决Java代码改动后在IDEA里执行Build - Rebuild Project确保target/classes更新了JSP改动直接刷新页面即可但CSS和JS改动需要按CtrlF5硬刷新或者在浏览器开发者工具的Network面板勾选Disable cache。最稳的调试方式是把部署方式改成war explodedJava和资源都不用手动重新打包IDE会自动同步到Tomcat。6. 进阶玩法让这套考勤系统在简历上站得住6.1 加一个加班审批闭环只做一个打卡系统太单薄我一般建议补一个加班审批流程。新增t_overtime表包含用户ID、申请日期、开始时间、结束时间、状态字段0申请中、1通过、2拒绝。后端复用现有的用户体系和Session判断角色员工提交申请时插入一条记录管理员审批时把状态从0改成1考勤统计SQL里再加一段LEFT JOIN t_overtime就能把加班时长算进汇总。代码量不大但把整个系统的故事讲圆了打卡是记录审批是流程统计是结果。6.2 交付前一套自查清单检查项验证方式数据库时区SELECT NOW()输出是否为北京时间默认账号登录后Session里role是否为1打卡唯一性同一用户同一天是否只有一条记录Excel导出用两个不同表格软件打开验证静态资源F12看CSS请求是否全部200这套清单是我每次交付前都会过一遍的。跑通老项目的最后一步不是看到登录页而是把上面的验证表走完把每个坑的解决方案记在项目的README里。我吃过不少亏比如以为连上数据库就万事大吉结果导出Excel在对方电脑上乱码现场改了半天。后来养成的习惯是任何环境相关的坑解决完立刻写进README下次换电脑部署时照着做十分钟就能跑起来。希望帮到你。本文还有配套的精品资源点击获取