☰
JSP+Servlet+MySQL教务系统:源码解读、避坑指南与简历级改造
2026/10/1 12:21:21 网站建设 项目流程

简介:这是一套面向高校教务管理场景的Java完整项目,适合计算机相关专业学生、Java学习者及毕业设计开发者参考。项目以教务信息管理系统为核心,覆盖学生、课程、教师、成绩、教室安排与系统设置等典型业务模块,整体采用MVC分层架构,业务逻辑、数据模型与用户界面分离,便于理解系统设计思路与前后端协作方式。压缩包共1255个文件,大小约60.32MB,其中包含146个class编译文件、73个java源文件、48个jsp页面、46个js脚本、32个css样式,以及SQL数据库脚本、jar依赖库和配套开发文档;同时附带系统安装配置与操作演示视频,可帮助快速搭建运行环境并熟悉各功能流程。已有1289人学习下载,覆盖从源码阅读、数据库设计到部署演示的完整链路,既能提升Java编程与SQL实践能力,也能为教育管理信息系统的二次开发提供可靠参照。

1. 教务信息管理系统是课设标配,但多数人把它用成了截图工具

每年期末都有同一个画面:拿到教务信息管理系统(JAVA源码+sql+文档+视频)的同学,把代码往 IDE 里一导,跑通,截图,写报告,然后封存。等真正面试被问一句“登录接口怎么防 sql 注入”“选课并发下数据怎么保证一致”,就答不上来。这套系统本质是一个典型的 JSP+Servlet+MySQL 管理后台,带管理员、教师、学生三个角色,覆盖登录认证、选课、成绩录入、课程管理几个闭环功能。它不是一个只能跑一遍交差的作业——花两天把代码读完,你收获的不只是一门课的分,还能得到能写进简历的第一份全栈 demo。这篇文章就按“选型→跑通→改模块→避坑→升级”的顺序把它拆完,新手能照着复现,熟手可以跳过基础步骤直接看最后一章改造成简历项目的方法。

2. 先看懂系统架构:为什么是 JSP+Servlet+MySQL,而不是 Spring Boot

动手导代码之前,先花半小时把目录结构和调用链读明白。这一步省掉的时间,远比你在报错堆里翻答案要多。这类教务系统源码包的通用结构,决定了它怎么配 JDK、怎么改数据库、怎么调连接池,所以我把选型和目录放在最前面讲。

2.1 选型背景:JSP+Servlet 为什么是这类源码包的标配

常见做法是,教务信息管理系统用 JSP 写页面、Servlet 做控制层、DAO 用原生 JDBC、数据库用 MySQL。这个组合在课程设计里出现频率最高,原因很实在:Tomcat 天然支持 JSP,不需要额外装配件;老师的评分标准里“能跑通 + 有分层 + 有文档”就够,不追框架;配套视频也按这个组合录的,照着敲最快。

相比之下 Spring Boot 是面试和简历里的热门词,但老课设包用它的少。不是因为 JSP 优于 Spring Boot,而是改造成本高:Spring Boot 内嵌 Tomcat,默认不支持 JSP 打包成 jar,要单独调;TypeHandler、MyBatis 配置、事务注解这些也不是一个晚上能补完的。如果你的目的是把这份源码变成讲得出原理的项目,那 JSP+Servlet 反而更适合当教材——每个请求走了哪个类、哪张表,肉眼可见。想清楚这点,你就不会一上来就喊“我要改成 Spring Boot”,然后改到一半翻车。

2.2 数据库设计:学生、教师、课程、成绩四张核心表怎么关联

先把库表结构理清。我见过不少同学把学生、老师、管理员全塞进一张 user 表,再用 type 字段区分,最后权限控制写成一团乱麻。正规且好改的做法是分表,权责清晰。

表名关键字段说明
tb_adminano, aname, password管理员账号,通常只有 1-2 条数据
tb_studentsno, sname, dept, major, password学生主表,sno 做学号业务主键
tb_teachertno, tname, dept, password教师主表
tb_coursecno, cname, credit, teacher_tno, capacity, selected课程表,selected 是已选人数
tb_scid, sno, cno, semester, score选课成绩表,多对多关系的中间表

建表语句里最值得抄的是这两张:

create table tb_course ( cno varchar(10) primary key, cname varchar(50) not null, credit decimal(3,1) default 2.0, teacher_tno varchar(10), capacity int default 60, selected int default 0, semester varchar(20), index idx_course_teacher (teacher_tno) ); create table tb_sc ( id int auto_increment primary key, sno varchar(10) not null, cno varchar(10) not null, semester varchar(20) default '2025-1', score decimal(5,1) null, unique key uk_sc_sno_cno (sno, cno), index idx_sc_cno (cno) );

逻辑说明:tb_sc 是学生和课程之间的桥梁表,唯一键 uk_sc_sno_cno 能保证同一个学生不能重复选同一门课,这个约束写在数据库里比写在 Java 里可靠得多。selected 字段维护在 tb_course 上,选课成功就 +1,退课 -1,避免每次统计都 count 一遍 tb_sc。这是很多人容易漏的优化点:如果成绩单查询每次都跨三张表 join,数据量一涨就变慢 sql,加这个冗余字段反而能扛住演示场景。

参数说明:credit 用 decimal(3,1) 而不是 float,事务和余额类字段都别用浮点,二进制浮点会产生 0.1+0.2≠0.3 的精度问题;score 允许空值,因为选课后不一定马上有成绩;capacity 和 selected 默认值放在 DDL 层,Java 代码少写一行。

2.3 代码目录:实体类、DAO、Servlet、JSP 之间的调用链

导入源码后,先看目录,不要急着点 run。典型结构长这样:

course-manage/ ├─ src/ │ └─ com/example/ │ ├─ entity/ # Student.java Teacher.java Course.java │ ├─ dao/ # BaseDao.java StudentDao.java CourseDao.java │ ├─ filter/ # AuthFilter.java 登录过滤器 │ ├─ servlet/ # LoginServlet.java StudentServlet.java │ └─ util/ # DBUtil.java MD5Util.java ├─ WebRoot/ │ ├─ admin/ # 管理员页面 │ ├─ teacher/ # 教师页面 │ ├─ student/ # 学生页面 │ ├─ common/ # 公共 jsp 片段 │ ├─ login.jsp │ └─ WEB-INF/ │ ├─ lib/ # mysql-connector-java 等 jar 包 │ └─ web.xml └─ db.sql

逻辑说明:这套结构是“实体类 → DAO → Servlet → JSP”的单向调用。JSP 里 form 提交到 LoginServlet 的 doPost,LoginServlet 调 StudentDao 的查询方法,DAO 通过 DBUtil 拿 Connection,结果返回 Servlet,Servlet 把数据塞进 session 或 request,再转发或重定向到下一个 JSP。把这个链条背下来,答辩和面试的第一问就稳了。

参数说明:WEB-INF/lib 下的 jar 数量和版本决定你会不会 ClassNotFound。老包里常带 mysql-connector-java 5.1.x,如果你换 MySQL 8.0,驱动类名和 URL 参数都得改,具体在第三章第三小节展开。web.xml 里一般配了 servlet 映射和 encodingFilter,动手前先 Ctrl+F 搜一下这两个配置,能少踩一半坑。

3. 把源码跑通:JDK、Tomcat、MySQL 版本匹配和导入步骤

这一章专门解决“怎么让它在我电脑上跑起来”。教务信息管理系统这类课设包对环境挑剔程度不高,但有几个版本雷区,踩一个就白折腾半天。

3.1 版本匹配:JDK 8 + Tomcat 8.5 + MySQL 5.7

组件推荐版本原因
JDK1.8九成源码包按 1.7/1.8 编译,高版本可能遇到 jsp 编译不兼容
Tomcat8.5还走 javax 命名空间,老代码直接兼容;Tomcat 10 换 jakarta,必炸
MySQL5.7驱动 5.1.x 配 5.7 最省事,数据导入字符集不容易乱
MySQL8.0(可选)需要 mysql-connector-java 8.x,并在 URL 加 allowPublicKeyRetrieval=true

很多人一上来装 Tomcat 10,启动日志报 java.lang.NoClassDefFoundError: javax/servlet/ServletContext,然后以为是代码问题。实际上 Tomcat 10 把 javax 迁移到了 jakarta,老包里的 servlet 相关 import 全部失效。这是最容易翻车的版本坑,先说破。同理,JDK 11 以上跑老 Java 项目偶尔会遇到模块访问限制,比如 java.xml.bind 缺失,课设包里通常没用到,但连带你编译时仍可能报错。

动手前先把环境版本落实:

# Windows 命令行窗口执行 java -version mvn -v 2>nul & echo Maven 可不装,课设一般是直接引 jar # 查看本机 Tomcat 版本 cd C:\apache-tomcat-8.5.100\bin && catalina version

参数说明:第二行检查 Maven 是可选的,多数 JSP 课设不配 Maven,而是把 jar 直接塞在 WebRoot/WEB-INF/lib 下。如果你不熟悉 Maven,不必为了这个项目单独装。Tomcat 版本以 bin 目录下实际文件为准,网上查再多不如敲这一行命令。

3.2 导入 Eclipse / IDEA:编码和部署路径是两个重灾区

第一步:源码包解压到纯英文路径。很多下载包来自中文 Windows 环境,文件名带“教务系统”四个字,解压后路径里也有中文,Tomcat 部署时偶尔会出现 resource 读取失败或 JSP 编译乱码。常见做法是解压到 D:\code\jwxt 这类路径:

mkdir D:\code\jwxt # 把 zip 解压到这里,确保路径不含中文和空格

逻辑说明:这一步不是玄学,是老项目对文件编码和路径解析双敏感。空格和中文在 URL 中会被转义,JSP 的 include 指令偶尔因此失效;虽然现代 IDE 有所容忍,但没必要赌。

第二步:Eclipse 老用户选择 File → Import → Existing Projects into Workspace,选中解压目录即可。导入后立刻检查三处:项目编码、编译器级别、部署目录。Eclipse 里右键项目 → Properties:

# 项目属性里需要核对,不是命令行 Resource → Text file encoding → 设为 UTF-8 Java Compiler → Compiler compliance level → 选 1.8

逻辑说明:旧源码包经常是 GBK 编码存的中文注释,Eclipse 默认可能按系统编码读,导致页面输出乱码。把编码强制成 UTF-8,再配合后文第四节的字符集 Filter,才能一次通过。

第三步:IDEA 用户不要直接 File → Open,建议也走 Import Project 或 Open with Eclipse 兼容模式。IDEA 对老 Eclipe Web 项目的支持有限,导入后常遇到“Artifact 没配”“lib 没有引用”。正确姿势是:

# IDEA 里按顺序走这些菜单 File -> New -> Project from Existing Sources 选择源码包根目录 -> 勾选 Eclipse 项目格式 Project Structure -> Modules -> 确保 Dependencies 里有 WEB-INF/lib Project Structure -> Artifacts -> 新建 Web Application Exploded,配置 WebRoot 目录

逻辑说明:这一步是 IDEA 跑老项目最麻烦的地方。IDEA 不知道 WebRoot 是你的 web 根目录,需要手动指定;如果不建 Exploded 部署包,Run 面板里连 Tomcat 都加不上。配好后老项目也能正常断点调试,不用急着转 Maven。

3.3 导入 SQL 脚本:三条命令搞定,注意字符集

数据库导入前先建一个库,再把 db.sql 导进去。常见做法是命令行直导:

mysql -u root -p create database if not exists jwxt default character set utf8mb4; use jwxt; set names utf8mb4; source D:/code/jwxt/db.sql;

逻辑说明:source 是 mysql 客户端的内部命令,路径用正斜杠,不然 Windows 下会把反斜杠当转义符处理。先 set names utf8mb4,再执行脚本,py 务段中文注释和 default 值才不会乱码;如果建库时没指定 charset,后面页面一查中文就全是问号。utf8mb4 比 utf8 多支持 emoji 和生僻字,课设字库里未必用得到,但统一成 utf8mb4 没有坏处。

导完库确认一下数据:

mysql -u root -p use jwxt; show tables; select * from tb_admin limit 3;

参数说明:show tables 能看到表清单就说明建库成功;tb_admin 表里一般预置了 admin/123 之类的初始账号,记录下这个账号,后面登录要用。如果报 Unknown database,说明 db.sql 里带了 window 语句或你自己建的库名和代码里不一致——不用慌,看看代码里的 DBUtil 连接串用的是哪个库名,按那个库名建库即可。

然后打开数据库配置文件改连接参数:

jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/jwxt?useUnicode=true&characterEncoding=utf8 jdbc.username=root jdbc.password=123456

逻辑说明:密码 root 的密码一定要改成你本机实际的,这是导入后第一个必改点。url 里 useUnicode=true&characterEncoding=utf8 是网页不乱码的另一半功劳,第五章会展开。如果你的 MySQL 是 8.0,驱动类名要换成 com.mysql.cj.jdbc.Driver,并追加 allowPublicKeyRetrieval=true&useSSL=false,否则启动后连库必报 Public Key Retrieval is not allowed。

4. 核心功能怎么改:登录、选课、成绩录入的代码逻辑

跑通只是开始。真正能让你在答辩和面试里加分的,是能改这三处代码并说出为什么。

4.1 登录模块:PreparedStatement 防 sql 注入,角色写进 session

登录是整个系统的主入口,也最常被面试官问。常见写法是 LoginServlet 先查库做密码比对,再把登录成功的人写进 session:

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); String account = request.getParameter("username").trim(); String password = MD5Util.md5(request.getParameter("password")); User user = userDao.findByAccount(account); if (user == null || !user.getPassword().equals(password)) { request.setAttribute("msg", "账号或密码错误"); request.getRequestDispatcher("login.jsp").forward(request, response); return; } HttpSession session = request.getSession(); session.setAttribute("loginUser", user); session.setAttribute("role", user.getRole()); // 按角色跳转,管理员去 admin/index.jsp,学生去 student/index.jsp response.sendRedirect(request.getContextPath() + "/" + user.getRole() + "/index.jsp"); }

逻辑说明:这里有两个细节。一是密码先过 MD5 再比对,db.sql 里存的也是 MD5 值,明文密码不进数据库。二是 role 写进 session 而不是查表,后续过滤器做权限判断直接取值,少一次数据库往返。

UserDao 里的查询必须用 PreparedStatement:

public User findByAccount(String account) { String sql = "select * from tb_user where account = ?"; try (PreparedStatement ps = conn.prepareStatement(sql)) { ps.setString(1, account); try (ResultSet rs = ps.executeQuery()) { if (rs.next()) { return new User(rs.getString("account"), rs.getString("password"), rs.getString("role")); } } } catch (SQLException e) { e.printStackTrace(); } return null; }

参数说明:? 占位符由驱动转义,避免 sql 注入万能密码。这一点是 java 面试题高频考点:字符串拼接会让人输入' or '1'='1绕过校验,PreparedStatement 则把整个输入当参数,不参与 SQL 语法解析。你可以在登录框里试一下万能密码,正常系统应该返回“账号或密码错误”,而不是直接进场。

4.2 选课模块:先查容量再插入,事务保证一致性

选课的逻辑是“学生选课 → 课程已选人数 +1”。看起来简单,但并发点击时会有超卖问题。先说清楚正确逻辑,再贴代码。教务系统常见实现是两步:先查 capacity 和 selected,判定还有名额,再插入 tb_sc 并更新 tb_course 的 selected 字段。

public boolean selectCourse(String sno, String cno, String semester) { String checkSql = "select capacity, selected from tb_course where cno = ?"; String insertSql = "insert into tb_sc(sno, cno, semester) values(?,?,?)"; String updateSql = "update tb_course set selected = selected + 1 where cno = ?"; Connection conn = null; try { conn = DBUtil.getConnection(); conn.setAutoCommit(false); PreparedStatement pst = conn.prepareStatement(checkSql); pst.setString(1, cno); // 省略 rs 读取:selected < capacity 才继续 PreparedStatement pst2 = conn.prepareStatement(insertSql); pst2.setString(1, sno); pst2.setString(2, cno); pst2.setString(3, semester); pst2.executeUpdate(); PreparedStatement pst3 = conn.prepareStatement(updateSql); pst3.setString(1, cno); pst3.executeUpdate(); conn.commit(); return true; } catch (SQLException e) { // 回滚后还能把已插入的 tb_sc 清掉 if (conn != null) { try { conn.rollback(); } catch (SQLException ex) { e.printStackTrace(); } } return false; } finally { DBUtil.close(conn); } }

逻辑说明:conn.setAutoCommit(false) 和 conn.commit() 搭配,保证 insert 与 update 要么都成功,要么都失败。如果课表插进去了但课程表人数没加,会出现“选了课但人数不对”的数据不一致。这是 java 怎么保证数据一致性的标准答案起点,哪怕你现在写的代码不如 Spring 事务优雅,也要让阅卷人看到你在处理这个场景。

参数说明:并发更高的场景,检查名额外加 for update 锁行,或把 update 条件改成 where cno=? and selected<capacity,让数据库决定是否更新成功。课设做到第一步就够,但你在文档里多写一句“生产环境需要行锁或乐观锁”,一句顶十个特性。

4.3 成绩录入与权限控制:三种角色的菜单怎么藏

教务系统里管理员能管用户,老师能录成绩,学生只能查。这种联动权限如果只靠“菜单里不显示”来实现,遇到懂点技术的人绕过 URL 就能进。正确做法是双保险:页面禁入口 + 过滤器禁路径。

最重要的过滤器写在 filter 包里:

public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) resp; HttpSession session = request.getSession(false); String path = request.getRequestURI().substring(request.getContextPath().length()); if (session == null || session.getAttribute("loginUser") == null) { if (path.endsWith("login.jsp")) { chain.doFilter(request, response); } else { response.sendRedirect(request.getContextPath() + "/login.jsp"); } return; } String role = (String) session.getAttribute("role"); if (path.startsWith("/admin/") && !"admin".equals(role)) { response.sendError(403); return; } chain.doFilter(request, response); }

逻辑说明:这段代码在访问所有页面之前先验证是否登录,没登录的除 login.jsp 外一律重定向。之后再按路径前缀判断角色:访问 /admin/ 开头页面但角色不是 admin,直接 403,不给页面渲染机会。这个过滤器是你能拿出手的亮点,很多课设因为没写这层,评阅老师都能说“不够安全”。

参数说明:注意 request.getSession(false),false 表示不自动创建 session,否则没登录的请求会被你一手凭空造出 session,过滤器判空就失效。path 用 substring 去掉 contextPath,是为了兼容部署在根路径和子路径两种情况。

5. 教务信息管理系统避坑指南:五个跑不通的典型现场与解法

这一章是血泪经验汇总。这些坑不会全踩,但踩任何一个都容易让人怀疑人生。按“现象 → 原因 → 解决”三条线列清楚,你排错时直接对照。

5.1 坑一:Tomcat 启动报 ClassNotFoundException 或页面 404

现象:启动日志看到java.lang.ClassNotFoundException: com.mysql.jdbc.Driver,或者是登录页能开但表单提交后 404。

原因:jar 包没进部署目录。Eclipse 里导入了源码,但 jar 只在构建路径里,没有发布到 Tomcat 的 WEB-INF/lib;或者 lib 下的 jar 版本和代码里 import 的类对不上。404 则是 servlet 没被 web.xml 正确映射,或项目没部署到正确 context。

解决:右键项目 → Properties → Deployment Assembly,把 WEB-INF/lib 加进部署清单;确认 web.xml 里 servlet-mapping 的 url-pattern 和 JSP form 的 action 一致。Eclipse 层面顺手 Clean 一次再重启 Tomcat,很多诡异的 404 是增量发布导致旧 class 没被清理。

5.2 坑二:数据库连不上 Communications link failure

现象:启动能起,但打开任何需要查库的页面,控制台报Communications link failure或Public Key Retrieval is not allowed。

原因:MySQL 服务没启动,端口不是 3306,驱动版本和 MySQL 版本不匹配。MySQL 8 默认启用 caching_sha2_password,老驱动 5.1.x 不支持,报错经常是 Public Key Retrieval。

解决:先确认 MySQL 进程在跑,然后用 MySQL 8 必须改三处。驱动 jar 换成 8.x,连接串驱动类名写成 com.mysql.cj.jdbc.Driver,同时补上 useSSL=false&allowPublicKeyRetrieval=true。改完 db.properties 后重启 Tomcat,不要只刷新页面,Java 程序不会热加载文件。

5.3 坑三:页面中文乱码,插入的数据变成问号

现象:JSP 页面上的中文标题正常,但数据库里查出来的中文全是问号;或反过来,库里正常,页面上全是乱码。

原因:三层编码没对齐。一是 JSP 文件本身是 GBK 编码;二是 Servlet 没做 request.setCharacterEncoding;三是 MySQL 表是 latin1 字符集。三层只要一层不对,中文字符就变形。

解决:统一走 UTF-8。JSP 文件头保留 pageEncoding="UTF-8",项目属性里把编码设成 UTF-8 重刷一次;在 web.xml 里配置 CharacterEncodingFilter,把所有请求先解一遍:

<filter> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>

逻辑说明:这把过滤器放在所有 Servlet 之前,相当于全局设置 request.setCharacterEncoding("UTF-8"),比每个 Servlet 自己写一行省事得多。如果项目是纯 JSP+Servlet 没有 Spring 依赖,把这个 filter 类换成自己手写一个几行的小 Filter 也是一样效果。数据库层则把表和字段的 collation 改成 utf8mb4_general_ci,改完重新导入 db.sql 确保从源头写入就是 UTF-8。

5.4 坑四:登录成功后跳回登录页,或页面反复 302

现象:账号密码输入正确,登录后一闪又回到 login.jsp,有时地址栏出现一连串 redirect。

原因:过滤器把登录成功的请求也拦了,或者把静态资源和登录页本身拦了。最常见的是 filter 的 url-pattern 写成 /*,却没在 doFilter 里放行 login.jsp,登录请求根本到不了 LoginServlet,形成死循环。

解决:在 doFilter 里加路径放行判断,login.jsp、loginServlet、静态 css/js/images 全放行。前面 4.3 的代码已经体现了这个逻辑;再补一句,respond.sendRedirect 的地址要带 contextPath,否则部署在非根路径时跳转错乱,这也是 302 循环的来源之一。

5.5 坑五:Eclipse 能跑的包拿到 IDEA 里废了

现象:IDEA 打开项目,Java 类全红,Tomcat 添加不了,run 按钮灰的。

原因:老 Eclipse 项目的 .classpath 和 .project 指向旧路径,IDEA 对 Eclipse Web 项目识别有限;项目里没有 Maven 构建文件,IDEA 不知道类路径从哪来。

解决:用 import 方式而不是 open 目录打开;导入后到 Project Structure → Modules → Dependencies,把 WEB-INF/lib 整个目录作为 jar 引用加进来。再检查模块 SDK 是不是空的,选 JDK 1.8。如果 run 方式还是别扭,干脆给项目补一个 pom.xml,把依赖交给 Maven 管理——改造量不大,但能彻底解决“IDEA 不认 lib”这个历史问题。

6. 把它改造成能写进简历的项目:三个必改点和一套验收清单

系统能跑顺之后,别急着交。聪明的做法是再花一晚做三处升级,每一处都是面试官爱问、文档里也写得出价值的点。

第一个必改点是数据库连接换成连接池。老代码里 DBUtil 每次操作都 DriverManager.getConnection,高并发下会拖垮数据库。换成 Druid 后,配置一个初始化连接数和最大连接数,代码里只拿连接不关连接池:

DruidDataSource dataSource = new DruidDataSource(); dataSource.setUrl("jdbc:mysql://localhost:3306/jwxt?useUnicode=true&characterEncoding=utf8"); dataSource.setUsername("root"); dataSource.setPassword("123456"); dataSource.setInitialSize(5); dataSource.setMaxActive(20); Connection conn = dataSource.getConnection();

参数说明:initialSize 平滑启动,maxActive 限制峰值,超出这个连接数请求会等待。这是慢 sql 优化的前置条件之一,面试被问“数据库连接管理”时,你有真实依据去讲。第二个必改点是账号密码加密,把裸 MD5 改成加盐:

SecureRandom random = new SecureRandom(); byte[] salt = new byte[16]; random.nextBytes(salt); // 存储时 password = MD5(password + salt),salt 一并存库

逻辑说明:不加盐的 MD5 能被彩虹表解出常见弱口令,加盐后每个用户盐不同,碰撞代价翻几百倍。这是 java 面试题里“数据安全怎么做”的小切口。第三个必改点是列表页加分页,学生列表、选课列表都不该一次全量拉取,SQL 用 limit ? , ? 即可降负担。

改完后按面试官视角验收一遍:用三种角色各登录一次,确认菜单差异;输入万能密码试试登录页是否被拦死;不开登录状态直接访问 student/index.jsp 看是否被重定向;开两个浏览器同时选同一门课,观察容量变化。有能力的再补一句“生产中会加行锁”。验收通过后,把之前的 db.sql 删掉重导入一遍,从头再跑一次全流程,确保这份源码交到谁手里都能复现——这是我自己带项目养成的习惯:每次交付前冷启动验证,不在现场翻车。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询