ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

JSP企业人事管理系统毕业设计:环境搭建到论文答辩全攻略

JSP企业人事管理系统毕业设计:环境搭建到论文答辩全攻略 简介基于JSP的毕业设计项目——企业人事管理系统包含完整源代码与配套论文面向计算机相关专业毕业生、Java Web学习者及需要快速完成类似课题的开发者。系统围绕员工信息、考勤、薪资等核心模块展开代码实现登录验证、数据维护、查询检索等基础功能论文则覆盖初步调查、需求分析、数据流程分析、系统总体结构设计、数据库设计、输入输出设计等关键环节可直接作为毕业设计说明书撰写参考。压缩包共140个文件、约2.21MB以52个JSP页面为主体辅以Java源码与class文件、CSS样式、JS脚本、GIF/JPG图片素材及Word版论文目录层次包含源码工程、文档资料和配置信息便于按模块对照阅读并部署运行。目前已有82人学习下载适合希望快速理解JSP人事管理系统完整实现思路的读者。1. 毕业设计选型为什么「JSP 企业人事管理系统」至今仍是稳妥答案如果你在 2025 年还要选一个 JavaWeb 方向的毕业设计题目打开知网和学长群大概率会看到两类东西一类是 Spring Boot Vue 的前后端分离项目另一类就是 JSP 的「古董」系统。很多人第一反应是 JSP 太老了企业里没人用了选它会不会显得没水平但我的看法正好相反——正是因为老它才是毕业设计里最不容易翻车的选题之一。企业人事管理系统这个业务域足够标准部门、员工、考勤、工资、公告、权限这些模块全是现成套路而 JSP 的 MVC 模型能让答辩老师一眼看穿你的分层能力。这套「源代码 论文」的压缩包本质上是把一套完整可运行的项目和配套文档打包给你。你需要的不只是把代码跑起来而是能讲清楚为什么这么设计、表结构为什么这么建、Session 权限控制为什么放在 Filter 里。接下来我会把这个项目的骨架拆开从环境搭建到核心模块实现再到论文怎么把代码变成文字最后把最常见的几个「坑」一次说透。适合三类人打算直接拿这套代码交差的、想二次开发加功能的、以及完全零基础但想搞明白 JSP 项目到底怎么运作的。2. 环境搭建与项目导入先把这套 JSP 人事系统跑起来2.1 JDK、Tomcat 与 Eclipse 的版本搭配这套系统既然是 JSP 写的那技术栈基本是固定的JDK 1.7 或 1.8、Tomcat 7 或 8.5、Eclipse IDE for Java EE 或者 MyEclipse。JSP 项目对版本极其敏感不是越新越好。很多人在 JDK 17 和 Tomcat 10 上跑老项目结果 servlet 包名从javax.servlet变成了jakarta.servlet直接编译报错第一关就卡住了。我一般建议用这套组合JDK 1.8长期维护版兼容性最好 Tomcat 8.5支持 Servlet 3.1JSP 2.3 Eclipse 2020 之后任意版本。如果你机器上已经装了新版 JDK不要急着卸载在 Eclipse 里单独配置一个 JRE 指向 JDK 1.8 的安装目录就行。Tomcat 解压版比安装版更省事环境变量配CATALINA_HOME指向解压目录JAVA_HOME指向 JDK 目录然后把下载好的 zip 里的项目文件夹导入 Eclipse。导入时有一个经典操作File - Import - General - Existing Projects into Workspace选择项目根目录确保 Eclipse 识别出.project文件。如果导入后项目没变成「带地球图标」的 Web 项目右键项目属性里找到Project Facets勾选Dynamic Web Module和Java再在Targeted Runtimes里选中 Tomcat 8.5。这一步做完项目才算和 Tomcat 关联上否则部署的时候根本看不到这个项目。2.2 数据库初始化与连接配置企业人事管理系统背后一定有一个 MySQL 数据库最常见的是 MySQL 5.7 或 8.0。压缩包里通常会附带一个.sql文件名字类似hrms.sql或personnel.sql。用 Navicat 或命令行执行这个脚本就能建好库和表。执行之前先看一眼 SQL 文件里的CREATE DATABASE语句——有些脚本会写死库名比如hrms而你的连接配置里如果写的是personnel_db那启动后所有表的查询都会报「Table doesnt exist」。连接信息集中在src下的db.properties或DBUtil.java里典型配置如下jdbc.drivercom.mysql.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/hrms?useUnicodetruecharacterEncodingutf8 jdbc.usernameroot jdbc.password123456对应到DBUtil.java里的加载逻辑static { try { Class.forName(com.mysql.jdbc.Driver); conn DriverManager.getConnection( jdbc:mysql://localhost:3306/hrms?useUnicodetruecharacterEncodingutf8, root, 123456 ); } catch (Exception e) { e.printStackTrace(); } }注意characterEncodingutf8这个参数如果数据库表和项目页面都是 UTF-8但这里不写中文插入后就是乱码。MySQL 8.0 需要把驱动类改成com.mysql.cj.jdbc.Driver同时 URL 里加上serverTimezoneAsia/Shanghai否则会报时区错误。这几乎是每个 JSP 项目部署的标配踩坑点后面避坑章节还会详细说。2.3 发布到 Tomcat 并验证登录流程项目右键Run As - Run on Server选择 Tomcat 8.5Eclipse 会自动把项目部署到wtpwebapps目录下。浏览器访问http://localhost:8080/项目名/如果看到的是登录页面说明环境这关过了。登录页通常长这样form actionlogin methodpost input typetext nameusername placeholder用户名 input typepassword namepassword placeholder密码 input typesubmit value登录 /form这个表单提交路径是关键。它走的是 Servlet 的WebServlet(/login)映射而不是 JSP 文件本身。也就是说登录验证是在LoginServlet的doPost()里做的通过后再重定向到main.jsp。如果你改成直接访问main.jsp会发现被拦截——因为项目里加了过滤器未登录状态访问任何页面都会跳回登录页。要验证登录流程是否正常可以先用 SQL 文件里预置的管理员账号一般是admin/admin123或者admin/123456。登录成功后看首页的导航栏有哪些菜单部门管理、员工管理、考勤管理、工资管理、公告管理、系统管理这六个模块基本就是这套人事系统的全部功能域。走到这一步项目已经能跑起来了接下来要搞明白的就是每个模块背后的代码逻辑以及论文里该怎么写。3. 系统架构与核心表结构从整体到明细拆解人事系统3.1 经典 MVC 分层JSP 在这个项目里到底扮演什么角色这套系统的代码结构通常是这样的src ├── com.hrms.servlet // 控制层登录、部门、员工等 Servlet ├── com.hrms.service // 业务层接口 实现类 ├── com.hrms.dao // 数据访问层JDBC 封装 ├── com.hrms.entity // 实体类部门、员工、考勤、工资等 ├── com.hrms.filter // 过滤器登录验证、字符编码 ├── com.hrms.util // 工具类DBUtil、分页工具 └── db.properties // 数据库连接配置WebRoot 或 WebContent 目录下放 JSP 文件、WEB-INF/web.xml、样式和前端资源。这是一套非常标准的 MVCJSP 只负责展示Servlet 接收请求并调用 ServiceService 调用 DAO 访问数据库DAO 返回实体类给 ServiceService 再传递给 JSP 渲染。这种分层在毕业设计答辩中非常好讲。老师问「你项目有没有分层」你直接把包结构打开给他看再补一句「JSP 里没有写一行 Java 访问数据库的代码所有数据都是从 Servlet 通过 request.setAttribute() 传过来的」这比你背十页 Spring 的原理更让人信服。JSP 页面内部通常配合 JSTLc:forEach和${}EL 表达式来遍历数据列表代码量少维护起来也直观。3.2 员工表与部门表的设计为什么外键不能乱加人事系统的核心是员工围绕员工衍生出部门、考勤、工资。最常见的表结构如下CREATE TABLE t_dept ( dept_id INT PRIMARY KEY AUTO_INCREMENT, dept_name VARCHAR(50) NOT NULL, dept_desc VARCHAR(200) ); CREATE TABLE t_employee ( emp_id INT PRIMARY KEY AUTO_INCREMENT, emp_no VARCHAR(20) UNIQUE NOT NULL, name VARCHAR(30) NOT NULL, gender CHAR(2), birth_date DATE, dept_id INT, position VARCHAR(50), hire_date DATE, phone VARCHAR(20), email VARCHAR(50), status TINYINT DEFAULT 1, FOREIGN KEY (dept_id) REFERENCES t_dept(dept_id) );这里有一个设计上的争议点dept_id是直接物理外键还是仅逻辑关联很多教程喜欢加FOREIGN KEY约束论文里也能写「保证了数据的参照完整性」。但实际项目中物理外键在删除部门时会造成麻烦——如果部门下有员工外键约束直接拒绝删除你就必须在程序里先判断「该部门下有没有人」有人的话给出友好提示。这其实是把数据库层面的错误转移成了业务逻辑代码写起来更绕。我建议物理外键可以不加只在 SQL 查询里用JOIN维护关联。答辩时老师问起来你可以这样答「学生认为人事系统的部门与员工是弱关联删除部门时业务上有处理逻辑所以用逻辑关联配合代码判断避免不必要的删除限制。」这套说辞在毕业答辩里很讨喜显得你真的想过这个问题。3.3 考勤和工资模块的数据冗余取舍考勤表是典型的每日一条记录设计CREATE TABLE t_attendance ( att_id INT PRIMARY KEY AUTO_INCREMENT, emp_id INT, att_date DATE, check_in TIME, check_out TIME, status TINYINT COMMENT 正常/迟到/早退/缺勤, UNIQUE KEY uk_emp_date (emp_id, att_date) );注意UNIQUE KEY uk_emp_date这个联合唯一索引——它保证同一个员工同一天只能有一条考勤记录如果代码里插入重复日期数据会直接报 Duplicate Entry而且数据库底层的这个报错比程序里的 if 判断可靠得多。工资表一般按月生成CREATE TABLE t_salary ( salary_id INT PRIMARY KEY AUTO_INCREMENT, emp_id INT, base_salary DECIMAL(10,2), bonus DECIMAL(10,2), deduction DECIMAL(10,2), social_security DECIMAL(10,2), month VARCHAR(7), actual_salary DECIMAL(10,2) );month字段存放类似2025-06这样的字符串按月份查询时直接WHERE month 2025-06不需要做日期换算写起来最省事。actual_salary是实际到手工资在代码里计算好后存进去不要写成base_salary bonus - deduction的表达式因为一旦前面某个字段被修改这个字段不会自动刷新。数据冗余在这里是值得的几张表的 JOIN 查询性能差距在这种小系统里根本感知不到。3.4 用一条列表查询串起整个后台链路的原理拿「员工列表页」来说从浏览器输入 URL 到页面渲染的完整链路是理解这套系统的钥匙。EmployeeListServlet的doGet()方法大致是这样protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding(utf-8); EmployeeService service new EmployeeServiceImpl(); ListEmployee list service.getAllEmployees(); request.setAttribute(list, list); request.getRequestDispatcher(employee_list.jsp).forward(request, response); }对应的 JSP 页面核心片段c:forEach items${list} varemp tr td${emp.empNo}/td td${emp.name}/td td${emp.deptName}/td td${emp.position}/td td a hrefEmployeeEditServlet?id${emp.empId}编辑/a a hrefEmployeeDeleteServlet?id${emp.empId} onclickreturn confirm(确定删除)删除/a /td /tr /c:forEachEL 表达式${emp.empNo}调用的其实是实体类Employee的getEmpNo()方法也就是说实体类里必须有无参构造方法每个属性都有 getter/setter。这是 JSP 里最容易出问题的地方——实体类字段写的是empNoJSP 里写${emp.empno}或${emp.empNo}都行但首字母大小写不规范容易编译报错。前端「编辑」按钮链接传到EmployeeEditServlet这个 Servlet 带一个id参数去数据库查出这条记录再转发到一个填好值的表单 JSP。整个 CRUD 就是这个模式看透一条链路六个模块全通了。4. 从零实现核心功能登录验证、增删改查和分页的完整代码4.1 登录过滤器与 Session 验证你的第一个安全防线人事系统里权限控制不能每个页面复制粘贴判断正确做法是写一个LoginFilter把未登录用户全部拦在门外。Filter 在 web.xml 里的配置filter filter-nameLoginFilter/filter-name filter-classcom.hrms.filter.LoginFilter/filter-class /filter filter-mapping filter-nameLoginFilter/filter-name url-pattern*.jsp/url-pattern /filter-mapping注意这里url-pattern是*.jsp只拦 JSP 页面。Servlet 路径要不要拦一般不建议拦因为要允许login这个 Servlet 直接访问。Filter 的 Java 代码核心逻辑是public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request (HttpServletRequest) req; HttpServletResponse response (HttpServletResponse) res; HttpSession session request.getSession(false); if (session ! null session.getAttribute(user) ! null) { chain.doFilter(req, res); } else { response.sendRedirect(request.getContextPath() /login.jsp); } }这段代码最关键的是request.getSession(false)里的false——它表示如果没有 session 就返回 null而不是新建一个。如果用getSession(true)或getSession()那每次未登录用户访问 JSP 都会创建空 sessionFilter 判断永远不为 null登录拦截就形同虚设这个细节在原理上能说道说道。会话超时时间在 web.xml 里还有一个配置session-config session-timeout30/session-timeout /session-config单位是分钟超时后 session 失效用户再次操作会被 Filter 踢回登录页。有人把判断写成只检查session ! null导致登录接口返回的 JSON 里带了 session但没存user属性这类代码即使页面看着是登录状态一刷新还是跳登录页问题就出在判断条件少了后半段。4.2 部门管理增删改查完整实现链部门管理是最标准的 CRUD把它写一遍其他模块就能照葫芦画瓢。先写实体类public class Dept { private int deptId; private String deptName; private String deptDesc; // getter/setter 省略 }DAO 层用 JDBC 查询public ListDept getAllDepts() { ListDept list new ArrayList(); String sql SELECT dept_id, dept_name, dept_desc FROM t_dept; try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql); ResultSet rs ps.executeQuery()) { while (rs.next()) { Dept d new Dept(); d.setDeptId(rs.getInt(dept_id)); d.setDeptName(rs.getString(dept_name)); d.setDeptDesc(rs.getString(dept_desc)); list.add(d); } } catch (SQLException e) { e.printStackTrace(); } return list; }这里用了 JDK 7 的 try-with-resources 语法Connection、PreparedStatement、ResultSet都实现了AutoCloseable接口代码执行完自动关闭连接不用在每个 finally 里手动 close。省下的代码量在小项目里不显眼但答辩时你可以特意提一句「我使用了自动资源管理避免连接泄漏」。删除部门时的业务判断是关键public void deleteDept(int deptId) throws SQLException { String countSql SELECT COUNT(*) FROM t_employee WHERE dept_id ?; String deleteSql DELETE FROM t_dept WHERE dept_id ?; try (Connection conn DBUtil.getConnection(); PreparedStatement ps1 conn.prepareStatement(countSql); PreparedStatement ps2 conn.prepareStatement(deleteSql)) { ps1.setInt(1, deptId); ResultSet rs ps1.executeQuery(); if (rs.next() rs.getInt(1) 0) { throw new SQLException(该部门下还有员工不能删除); } ps2.setInt(1, deptId); ps2.executeUpdate(); } }如果不在代码里做这个判断数据库层面加过外键的话会报外键约束错误没外键的话会把员工表的dept_id变成孤儿数据列表 JOIN 出来全是 null。两种方式代价都不小所以业务层的二次校验必须有。4.3 分页查询的两种降级方案小系统数据量涨到几千条后一次SELECT *全部渲染到页面上会明显变卡。两个方向可以改取决于原代码里有没有现成分页工具类。最直接的是 SQL 层的LIMITpublic ListEmployee getEmployeesByPage(int pageNum, int pageSize) { String sql SELECT e.*, d.dept_name FROM t_employee e LEFT JOIN t_dept d ON e.dept_id d.dept_id LIMIT ?, ?; try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setInt(1, (pageNum - 1) * pageSize); ps.setInt(2, pageSize); ResultSet rs ps.executeQuery(); // 遍历结果 } }页面上加两个超链接上一页、下一页URL 带pageNum参数a hrefEmployeeListServlet?pageNum${currentPage - 1}上一页/a span第 ${currentPage} / ${totalPage} 页/span a hrefEmployeeListServlet?pageNum${currentPage 1}下一页/aServlet 里还要查一次总数算总页数int totalCount employeeDao.countAll(); int totalPage (int) Math.ceil(totalCount / (double) pageSize); request.setAttribute(totalPage, totalPage);注意Math.ceil先把totalCount转成double再除否则totalCount / pageSize是整数除法10 条数据每页 5 条得到 2 没问题但 11 条数据得到的还是 2最后一页丢了。这是分页里最隐蔽的一个计算错误很多文章里都直接写整数除法实际跑起来边界数据才会发现少了一页。如果不想动 SQL第二种方案是页面用 JavaScript 分批渲染——把所有数据传给前端JS 每次只显示一部分。但这种方式数据量大时前端内存压力大JSP 里c:forEach渲染速度会下降只适合数据量几千条以内的情况。毕业设计阶段我推荐直接用 SQL 分页原理好写代码也好讲。4.4 模糊搜索和按条件筛选的组合人事系统里搜索框是刚需。员工列表页通常会提供三个条件姓名关键字、部门下拉框、状态。对应 SQL 不能写死要用动态拼接public ListEmployee searchEmployees(String keyword, Integer deptId, Integer status) { StringBuilder sql new StringBuilder(SELECT e.*, d.dept_name FROM t_employee e ); sql.append(LEFT JOIN t_dept d ON e.dept_id d.dept_id WHERE 1 1 ); if (keyword ! null !keyword.trim().isEmpty()) { sql.append(AND e.name LIKE ? ); } if (deptId ! null deptId 0) { sql.append(AND e.dept_id ? ); } if (status ! null) { sql.append(AND e.status ? ); } // 设置参数 }WHERE 1 1这个写法看起来很土但它避免了每个条件都要判断要不要在开头加WHERE或AND的逻辑动态 SQL 的常规技巧。传参顺序必须和append的顺序一致这是动态拼接 SQL 最容易翻车的地方——条件多了以后参数顺序错位数据查出来完全不对。前端表单里下拉框要保留上一次选中的状态select namedeptId option value0全部部门/option c:forEach items${deptList} vard option value${d.deptId} ${param.deptId d.deptId ? selected : }${d.deptName}/option /c:forEach /selectparam.deptId从 URL 参数里取当前值做回显。如果这里不加选择判断每点一次查询下拉框就弹回默认选项用户操作体验很差这个细节也值得在论文里写一笔。5. 论文写作与代码对应把压缩包里的代码变成能过查重的毕业设计5.1 论文目录结构与每个章节该写什么这套资源附带论文通常目录长这样第1章 绪论 1.1 课题背景与意义 1.2 国内外研究现状 1.3 主要工作 第2章 相关技术介绍 2.1 JSP 技术 2.2 Servlet 技术 2.3 MySQL 数据库 第3章 系统分析 3.1 可行性分析 3.2 需求分析 3.3 功能模块设计 第4章 系统设计 4.1 总体架构设计 4.2 数据库设计 第5章 系统实现 5.1 登录模块实现 5.2 部门管理模块实现 ... 第6章 系统测试 6.1 测试环境 6.2 功能测试 6.3 测试结论 第7章 总结与展望技术介绍那一章很多人的写法是去百度百科复制 JDK 定义然后被查重系统标红一大片。正确的做法是介绍 JSP 时重点写它在项目里的具体应用场景比如「本系统的员工列表页面使用 JSP JSTL 进行数据遍历展示通过 EL 表达式直接获取 request 域中的集合对象」你把自己系统的一行代码贴进去这段话就变成了你自己的理解查重率天然就低。5.2 需求分析到 ER 图的绘制需求分析里功能模块图用 Word 里的 SmartArt 画分层结构不要用截图工具从别人论文里截。ER 图可以用 DBDiagram 或者 Visio 画表结构要和第 3 章里的 SQL 建表脚本完全一致。这是答辩老师最喜欢查的点——论文里写的字段如果和代码里对不上一问就露馅。5.3 测试章节写什么才能充实篇幅系统测试章节不要只写「通过」。按软件工程的标准套路写用例表用例编号测试项操作步骤预期结果实际结果结论TC-001登录验证输入 admin/123456跳转到主页面符合预期通过TC-002登录失败输入 admin/111111提示用户名或密码错误符合预期通过TC-003删除部门删除存在员工的部门提示部门下仍有员工符合预期通过每张表放十行左右代码里能复现的都写进去。测试环境可以写操作系统版本、JDK 版本、Tomcat 版本、MySQL 版本这些字段凑起来也是一段有效文字。最后补一段「测试结论系统各模块功能正常满足设计需求」这一章就扎实了。5.4 查重降重与代码截图技巧降重的核心思路是把概念包装成「结合本系统的具体说明」。比如「JSP 是一种动态网页技术标准」这句话是概念改成「本系统使用 JSP 作为表现层技术在每个功能模块对应的 JSP 页面中通过 JSTL 标签库和 EL 表达式实现数据的遍历展示」就是结合系统。段落里的「本项目」「本文」一定要用足答辩老师辨认代码是不是你自己写的主要看你的系统里有没有那些只有亲手实现的人才会知道的小设计比如之前那个「删除部门时先检查员工表」的判断。代码截图建议用Highlight工具导出带行号的样式Word 里表格放不下的话截成图片。注意图片宽度统一表格里的代码取关键方法段就行不用整页贴。论文最后的「致谢」不要抄网上的模板「感谢我的指导老师不厌其烦地给予指导」这种通用句子查重率很高写两句自己实际的经历更安全。6. 避坑指南JSP 人事系统从部署到答辩的 5 个血泪经验6.1 MySQL 8.0 驱动与时区问题现象项目在 MySQL 5.7 上跑得好好的换到 MySQL 8.0 后启动直接报The server time zone value Öйú±ê׼ʱ¼ä is unrecognized数据库连接全部失败。原因MySQL 8.0 开始JDBC 驱动要求显式指定时区同时旧的com.mysql.jdbc.Driver在 8.x 里已经被标记为过时。中国时区的显示在 GBK 编码下变成乱码所以连协议握手都过不去。解决驱动换成com.mysql.cj.jdbc.DriverURL 里追加serverTimezoneAsia/ShanghaiuseUnicodetruecharacterEncodingutf8。注意是 XML 转义符在 web.xml 里配置数据源时要写成amp;在.properties文件里不用转义。6.2 Eclipse 部署不上项目现象项目在 Eclipse 里显示正常但Run on Server之后 Tomcat 的 webapps 目录里根本没有这个项目浏览器访问 404。原因Tomcat 的 Server Locations 设置为默认的「使用工作空间元数据」或项目未被标记为「Deployable」。另一个常见原因是 Tomcat 版本与项目 Dynamic Web Module 版本不一致。解决双击 Servers 视图里的 Tomcat 实例打开配置页把Server Locations改为「Use Tomcat installation」前提是 Tomcat 里没有部署其他项目。然后在项目属性里找到Deployment Assembly添加src对应的/WEB-INF/classes映射再检查Project Facets里的 Dynamic Web Module 是否勾选且版本匹配。6.3 JSP 页面中文全部变成问号现象登录页能显示但点进员工列表后所有中文姓名、部门名都变成???。原因三个环节至少有一个编码不对——页面编码、请求编码、数据库连接编码。JSP 页面顶部没有% page contentTypetext/html;charsetUTF-8 %或者 Filter 里没有设置request.setCharacterEncoding(UTF-8)数据库连接 URL 少了characterEncodingutf8。解决先统一所有 JSP 页面头部声明 UTF-8。然后在 Filter 的chain.doFilter(req, res)之前先执行request.setCharacterEncoding(UTF-8)这个方法只对 POST 请求的 body 生效GET 请求的 URL 参数乱码要靠 Tomcat 的URIEncodingUTF-8配置。三个地方一起改完刷新页面中文正常。查这个问题可以用浏览器开发者工具看响应头的Content-Type是不是text/html;charsetUTF-8这个字段能快速定位哪一层编码丢了。6.4 登录成功后刷新又跳回登录页现象登录成功跳转到主页面但按 F5 刷新后立刻被 Filter 拦截回到登录页。再次登录成功过十几分钟又跳登录页。原因登录 Servlet 里把登录成功的信息存进了 session但存的时候 key 和 Filter 里查的 key 不一致。比如登录时session.setAttribute(user, user)Filter 里却判断session.getAttribute(username) ! null自然永远为 null。另一种原因是 Tomcat 默认 session 超时时间是 30 分钟代码里某处调用了session.invalidate()。解决搜索结果页里搜setAttribute和getAttribute确认 key 完全一致。专业的做法是定义一个常量类比如SysConstants.SESSION_USER所有地方都用这个常量避免字符串拼写错误。如果你发现是超时导致只能在 web.xml 的session-timeout里调大毕业设计演示阶段临时调到 120 分钟能救急但不要写进论文作为正式配置。6.5 导出论文里的代码和压缩包代码对不上现象答辩老师打开项目源代码和论文第 5 章贴的代码不一样或者干脆论文里的方法和实际类名对不上。原因最常见的是改完代码没同步论文或者代码是从网上其他地方复制粘贴的时候张冠李戴。比如系统里员工类叫Employee论文里写的却是Staff这种一眼就能看出来是复制没改干净。解决论文写完第 5 章后把每个提到的类名、方法名、变量名都去 Eclipse 里搜一遍按类名逐个核对。更省事的做法是「先写代码后写论文」你的代码是最终版了论文完全照着最新代码写。论文里贴的核心方法不要超过十个贴完就在旁边标注「见代码 5-1」答辩老师要是现场打开看对不上就麻烦了。为了避免这个问题我自己做毕业设计时是先把每个模块的类名和核心方法名打了一张表写论文前对着表过一遍十分钟就能查完。7. 进阶玩法从「作业项目」升级成「能写进简历的项目」基础 CRUD 做完只算及格。要让它从一堆同样的毕设里脱颖而出有几个成本不高但收益明显的加装思路。第一给员工列表加一个导出 Excel 功能。用 Apache POI 的HSSFWorkbook生成.xls文件把 List 数据循环写入每行前端放一个「导出」按钮指向ExportEmployeeServlet响应头设置Content-Disposition为附件下载。这个功能只用几十行代码却是企业里真实存在的需求简历上写「实现了员工信息 Excel 导出」比「完成了增删改查」有说服力得多。第二把密码从明文存储改成 MD5 加盐。现在很多 JSP 系统还是直接存明文密码在登录模块里加一段MessageDigest.getInstance(MD5)对密码做摘要盐值可以用用户创建时间。改起来不复杂但能在论文里单独开一个小节写「系统安全性设计」毕业设计的评分档次立刻就上去了。这个方向千万不要搞成自以为是的东西就行不要随便引入什么阿里云短信验证码之类的外网依赖。第三工资模块加一个简单的统计图表。用 ECharts 的bar柱状图展示各部门平均工资Servlet 里写一条SELECT d.dept_name, AVG(s.actual_salary) FROM 部门 s GROUP BY d.dept_name把结果转成 JSON 返回给 JSP 中的echarts.init()渲染。注意 JSP 里引进 echarts.js 要在页面末尾否则 DOM 还没加载完初始化会拿到 null。这条 SQL 是分组聚合的经典写法答辩时讲数据统计也比讲 CRUD 更有技术含量。验证升级后的功能有没有破坏原有系统核心办法是回归测试把 6.2 节里的功能用例表重新跑一遍重点测新增导出按钮后原有列表分页是否正常、新增筛选条件后 URL 参数是否正确传递。跑完记下测试结果顺手更新论文测试章节的数据保持论文和系统始终是同一版本。这些进阶动作做完你手里的项目就从「能毕业」变成了「能写进简历项目列表」的水平。做毕设的时候多折腾这几个小时后面找实习面试能省下大把解释成本——面试官看到 JSP 项目通常不期待你说出什么新花样但你能主动说出「我为系统的导出和密码存储做了哪些改进」这本身就说明你是真动过手的。希望这些思路能帮到你少走一点我当年踩过的弯路。本文还有配套的精品资源点击获取
返回列表