ARTICLE DETAIL

资讯详情

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

JSP+Servlet+JDBC实战:实验教学管理系统拆解与避坑指南

JSP+Servlet+JDBC实战:实验教学管理系统拆解与避坑指南 简介面向JavaWeb课程设计和毕业设计的学生这份实战项目提供了基于JSPSQL的实验教学管理系统完整源码包含前后端代码、论文、数据库脚本和说明文档。系统围绕实验教学管理核心业务展开涵盖实验课程安排、学生选课信息、实验成绩录入与查询等典型模块能够展示JSP页面、Servlet控制层与MySQL数据库之间的完整交互流程有助于学习者快速掌握JavaWeb分层开发思路并可直接作为课程设计或毕业设计的项目骨架。压缩包整体约3.66MB主要文件类型包括JSP页面、Java后端源码、SQL数据库初始化脚本、论文正文及运行说明文档目录结构按功能划分便于逐部分对照学习。目前已有88人学习下载适合具备一定Java基础、希望以完整项目为参照进行二次开发或答辩展示的读者资源内附运行环境配置说明便于快速部署运行。1. 拿到 Java 实战项目包却跑不起来JSPsql 实验教学管理系统就得这么拆当你的下载目录里躺着“Java实战项目——基于javaweb实现的JSPsql实验教学管理系统(前后端源码论文数据库说明文档).zip”这个压缩包时你其实已经站在了 Java Web 课程设计最典型的入口前。系统解决的是高校实验课的管理问题学生选实验、交报告教师发布任务、打分管理员维护课程数据。没有高并发也没有微服务但它把 Java Web 面试最常问的登录、会话、分页、上传、权限拦截全串了起来。适合正在做课设或者想找一个完整 javaweb 项目练手并写进简历的人。这种项目包的麻烦点在于它不像 Spring Boot 项目那样一键启动目录结构老、依赖靠 lib 文件夹、Tomcat 配置稍不留神就 404。接下来的内容按我做这类项目的固定顺序展开先拆业务和数据库再配 IDEA 跑登录接着做分页和报告上传最后是避坑和交付前验证。你照着走一遍能把黑匣子变成能讲清楚的数据流。2. 先拆库表再碰代码实验教学管理系统里的核心表结构和数据流2.1 三种角色与一条主链路从“建实验课”到“出成绩单”实验教学管理系统的核心业务可以用三个问题讲完管理员管什么、教师教什么、学生交什么。管理员维护课程和实验项目的基础属性相当于数据源教师把实验任务挂到课程下设置开放时间和允许提交次数学生看到实验后下载任务书上传实验报告等待教师评分。整个系统最终交付的是一张带分数的成绩报表这张表是教务管理最刚性的诉求。我在拿到项目包后不会先解压代码而是先在纸上画一遍主链路课程t_course关联实验t_experiment实验关联提交t_submission提交关联用户t_user。四张表按创建时间依次展开恰好复现“管理员建课 - 教师发实验 - 学生交报告 - 教师打分”的完整时序。任何一张表缺字段比如实验表没有end_time学生就能在截止日期后继续提交这就是数据流断裂的典型表现。这个理解直接决定后续写 SQL 和 JSP 的精力分配。主链路上的五张表是必做项通知公告、班级分组、实验设备预约这类附表属于加分项。检查项目包里的数据库脚本时我一般先确认主链路是否完整再确认外键到底是真的物理外键还是只在查询里写的逻辑外键。很多课程设计为了省事不建物理外键删除实验后残留一堆无人认领的提交记录答辩时被追问一下数据一致性就露馅了。2.2 核心表 DDL用户、课程、实验和提交记录字段类型与索引选择打开数据库脚本最核心的六张表一般是用户表、课程表、实验表、选课表、提交表和成绩视图。成绩视图可以不物理建表用view聚合就行。用户表和提交表的 DDL 前面已经给出这里补充课程表和选课表的设计这两张表决定了“谁能看到哪个实验”CREATE TABLE t_course ( id INT AUTO_INCREMENT PRIMARY KEY, course_name VARCHAR(50) NOT NULL, teacher_id INT NOT NULL, semester VARCHAR(20) NOT NULL COMMENT 如 2025-2026-1, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, KEY idx_teacher (teacher_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE t_elective ( id INT AUTO_INCREMENT PRIMARY KEY, student_id INT NOT NULL, course_id INT NOT NULL, UNIQUE KEY uk_student_course (student_id, course_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;t_elective上的联合唯一索引uk_student_course保证一个学生只能选一门课一次这是数据防重的第一道防线。很多旧脚本里压根没有这张选课表学生选课记录被直接塞进t_submission导致学生第一次交报告才算是选课成功教师发布实验后无法提前统计参与人数。semester用 VARCHAR 而非 ENUM因为学期数据要扩展用 ENUM 之后加一条新值就得ALTER TABLE维护成本高。字段类型方面凡是参与 WHERE 和 JOIN 的字段比如student_id、course_id、experiment_id都必须是整型且建索引。文本字段里exp_desc用 TEXT不要用 VARCHAR(2000)否则 utf8mb4 字符集下的索引长度会直接超限又绕进另一个坑。时间字段统一用 DATETIMEJava 侧用java.sql.Timestamp接收比较时写exp_end_time NOW()不要在前端做字符串比较服务器时区参数没配好时会平白差出 8 小时。2.3 三角色的菜单权限session 里放 roleFilter 里做两段式拦截登录成功后的User对象放进 sessionJSP 页面里按role值渲染不同菜单。我的习惯是把菜单写进独立的menu.jsp通过c:if判断角色输出入口role0 显示班级管理、课程管理、教师管理role1 显示我的实验、学生提交、评分管理role2 显示可选实验、我的报告、我的成绩。这个文件被所有业务页面 include改一处就全站生效。权限判断的第二段要放在 Servlet 层。只隐藏菜单是不够的用户可以直接在地址栏输入/admin/courseManage.jsp绕过入口。正确做法是在 Filter 里做 URL 前缀拦截以/admin/开头的资源只允许 role0以/teacher/开头的只允许 role1其余业务页面要求 session 非空。遇到不满足的请求不返回 403而是重定向到登录页这种处理对用户更友好也避免暴露后台地址。还有一个容易忽略的 session 过期问题。很多项目包的web.xml里没有显式配置session-timeout默认值 30 分钟。实验报告上传如果中途卡顿超过 30 分钟提交时会跳回登录页用户写了半天的内容全丢。我一般会在web.xml里写 60 分钟并在上传页面加一句“长时间编辑请定期保存”的提示。这是很小的改进但体验差别很明显。3. 在 IDEA 里运行 javaweb 项目JSPServlet 骨架搭建和登录模块参数3.1 为什么这类项目不用 Spring Boot而是坚持 JSPServletJDBC先说结论实验教学管理系统用 JSPServletJDBC是因为它把每个环节都暴露在阳光下。JSP 页面里可以直接看到 request、session 和查询结果适合演示“前端怎么把表单数据交给 ServletServlet 怎么拼 SQL 查库”Spring Boot 会把数据访问藏进 Mapper 层对练手的人来说反而像个黑匣子。JDBC 裸写虽然啰嗦但它逼着你理解四件事加载驱动、建立连接、预编译指令、处理结果集。换成 MyBatis 后这些细节几乎全部消失而 Java Web 面试里问得极多的PreparedStatement防注入、连接超时关闭、事务提交时机恰好都在这种 JSPsql 项目里要自己写。JSP 的四大作用域 page、request、session、application 也是面试常客亲手用过 session 判断登录状态比背十遍概念都管用。所以我的建议是别嫌这类项目老。把它拆干净再合上比追一个 Spring Cloud 脚手架有用得多。尤其当目标是短期搞定课程设计时JSPServlet 的调试链路短一个 Tomcat 就可以跑完不牵扯 Maven 私服、Nacos 注册中心这些额外负担。3.2 导入现有源码IDEA 的 Artifact、Tomcat 和 Application Context 配置用 IDEA 运行传统 javaweb 项目最容易卡在 Artifacts。项目包解压后一般是src/放 Java 文件web/放 JSP 和 WEB-INFlib/放 mysql-connector-java.jar。导入步骤我按顺序说全先在新窗口里用 File - New - Project from Existing Sources 选择解压目录导入类型选 Eclipse 或 Web看原项目用什么组织格式。接着在 File - Project Structure 里点 Artifacts加一个 Web Application: Exploded把左侧的web目录映射进去。这一步漏掉Tomcat 启动后必定 404。然后配置 Run/Debug Configurations添加 Local Tomcat Server。在 Deployment 标签页里加入刚才建好的 exploded artifactApplication context 填/expms。如果不填IDEA 会自动用_war_exploded当根路径浏览器访问/expms/login.jsp时就会打到一个不存在的目录上。# 检查 Tomcat 端口占用macOS / Linux lsof -i:8080 # Windows 下用 netstat 检查端口 netstat -ano | findstr :8080这三条命令的作用是排查端口被占用。表现是 Tomcat“启动成功”但浏览器一直转圈或连接重置。找到占用进程后直接把 Tomcat 端口改到 8081再重新启动。另外确认JAVA_HOME指向 JDK 而不是 JRE很多机器装了多个 JDKIDEA 默认选错了运行时。这个环节能一次跑通后面所有调试都有基础。3.3 登录模块前后端代码Servlet 接收表单PreparedStatement 查用户表现在动手写登录模块。先看后端LoginServlet它接收login.jsp的表单完成编码设置、JDBC 查询和 session 写入WebServlet(/login) public class LoginServlet extends HttpServlet { Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding(UTF-8); String username req.getParameter(username); String password req.getParameter(password); try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement( SELECT id, real_name, role FROM t_user WHERE username? AND password?)) { ps.setString(1, username); ps.setString(2, MD5Util.md5(password)); ResultSet rs ps.executeQuery(); if (rs.next()) { User u new User(rs.getInt(id), rs.getString(real_name), rs.getInt(role)); req.getSession().setAttribute(user, u); resp.sendRedirect(index.jsp); } else { req.setAttribute(error, 用户名或密码错误); req.getRequestDispatcher(login.jsp).forward(req, resp); } } catch (Exception e) { e.printStackTrace(); resp.sendError(500, 数据库异常); } } }这段代码的顺序是先设置请求编码从表单取username和password再用 try-with-resources 拿到连接和预编译语句。注意密码先用 MD5 转一遍再比较这是课程设计项目包里的常态生产环境应该换 BCrypt 加盐。参数说明ps.setString(1, ...)的索引从 1 开始和 SQL 中?出现的顺序一一对应。如果改回用Statement拼接字符串遇到用户名里的单引号就直接崩这也是 JDBC 裸写最常见的翻车点。对应的login.jsp页面要注意表单路径不能写死% page contentTypetext/html;charsetUTF-8 languagejava % html body form action${pageContext.request.contextPath}/login methodpost input typetext nameusername placeholder学号/工号 required input typepassword namepassword placeholder密码 required button typesubmit登录/button /form c:if test${not empty error} p stylecolor:red${error}/p /c:if /body /html${pageContext.request.contextPath}会动态输出/expms即使你后来改了 Tomcat 的 Application context前端代码也不用动。c:if是 JSTL 的标签老项目包里一般已经带jstl-1.2.jar如果没有把 error 用%request.getAttribute(error)%也能显示。这里有个隐藏参数Tomcat 8.5 之后连接器的maxPostSize默认只有 2MB如果登录表单里夹带了太大的验证码图片表单会被静默拒绝请求看起来像是没有提交。我一般在server.xml里把它调到 10MB或者干脆不在登录页放体积大的图片字段。4. 跑通实验报告上传与分页列表SQL 边界参数、MultipartConfig 与 PreparedStatement4.1 列表分页的 SQL 写法LIMIT 与 OFFSET 的参数换算实验教学管理系统里最容易被放大的功能是列表页。学生列表、实验列表、成绩列表都要分页。最常见的错误是先把全表查出来再在内存里做 subList数据量过千浏览器就开始卡。正确做法是用 SQL 的 LIMIT 配合偏移量让数据库只回传一页数据。下面这条 SQL 同时统计每个实验的提交人数是教师端“我的实验”页面的标准写法SELECT e.id, e.exp_name, e.start_time, e.end_time, IFNULL(COUNT(s.id), 0) AS submit_count FROM t_experiment e LEFT JOIN t_submission s ON s.experiment_id e.id GROUP BY e.id ORDER BY e.start_time DESC LIMIT 10 OFFSET 20;LIMIT 10 OFFSET 20表示跳过前 20 条再取 10 条也就是第 3 页。前端页码从 1 开始后端换算公式是offset (currentPage - 1) * pageSize。这两个数字就是分页必调参数pageSize 决定接口返回多少条OFFSET 决定从哪条开始。这里也提醒一下SQL Server 和 MySQL 方言不同SQL Server 用OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY且必须配套ORDER BY。标题里的 JSPsql 并不限定数据库但面试时说清这种差异很加分。对应的PageT工具类一般持有list、currentPage、pageSize、totalCount、totalPages五个字段。总页数计算公式是totalPages (totalCount pageSize - 1) / pageSize这个向上取整的写法比Math.ceil更直观也避免总页数为 0。JSP 渲染上一页下一页时首尾页码要禁用判断条件分别是currentPage 1和currentPage totalPages。4.2 报告上传参数savePath 目录、文件大小上限和版本号字段报告上传是整个系统的功能核心也是最容易埋雷的部分。老项目普遍用 commons-fileupload 依赖需要commons-fileupload和commons-io两个 jar如果项目包用的是 Servlet 3.0 的PartAPI则零依赖直接在 Servlet 上打MultipartConfig注解就行。先把保存路径和文件名的处理讲清楚MultipartConfig( maxFileSize 1024 * 1024 * 50, // 单文件最大 50MB maxRequestSize 1024 * 1024 * 200, // 单次请求总大小 200MB fileSizeThreshold 1024 * 1024 * 1 // 超过 1MB 落盘临时文件 ) WebServlet(/uploadReport) public class UploadReportServlet extends HttpServlet { protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding(UTF-8); User user (User) req.getSession().getAttribute(user); int experimentId Integer.parseInt(req.getParameter(expId)); Part filePart req.getPart(reportFile); String rawName filePart.getSubmittedFileName(); String ext rawName.substring(rawName.lastIndexOf(.)); String serverName UUID.randomUUID().toString().replace(-, ) ext; String basePath getServletContext().getRealPath(/uploads/experiment); File destDir new File(basePath); if (!destDir.exists()) { destDir.mkdirs(); } String dateDir new SimpleDateFormat(yyyyMMdd).format(new Date()); File destPath new File(destDir, dateDir); if (!destPath.exists()) destPath.mkdirs(); filePart.write(destPath.getAbsolutePath() File.separator serverName); // 插入提交记录并自动累加 versionSQL 略 resp.sendRedirect(myReport.jsp); } }这段代码里有三个参数值得调maxFileSize决定单份报告能不能传上来很多同学交几十 MB 的工程压缩包被静默拒绝却找不到原因fileSizeThreshold低于实际文件大小时文件先写临时文件再流转避免 JVM 堆溢出。保存路径里再用日期分一层子目录是批量报告下文件系统不卡顿的常规做法。文件名用 UUID 重命名而不是保留原名是为了避免两个学生交同名的report.docx互相覆盖。这是血泪经验换来的文件名一定不能信任浏览器传参。版本号字段是另一个容易忽略的边界参数。允许一个学生多次提交时t_submission表里依赖联合唯一索引(student_id, experiment_id, version)每次插入前先查出当前最大 version 再加一而不是直接 UPDATE 旧记录。这样保留历史版本教师和审计都能看到改动痕迹。如果项目包里没有这个设计建议补上因为“重复提交算哪一次成绩”是实验教学系统最容易被问到的业务问题。4.3 SQL 注入防线从万能密码绕过看 PreparedStatement 为什么是唯一正解很多 JSP 项目包的登录代码为了图省事会写字符串拼接 SQL比如SELECT * FROM t_user WHERE username name AND password pwd 。这时输入admin or 11就能把条件变成恒真这就是安全测试里常说的“sql注入万能密码绕过”。实验教学管理系统的登录接口同样逃不掉扫一遍就能让你的后台裸奔。正确做法是前面登录代码里已经展示的PreparedStatement。它能防注入的原因在于预编译语句在数据库端先固定了解析结构?只代表字面值不会被重新解释成 SQL 关键字。哪怕你传 or 11 --它也被当作完整的字符串去做值比较不产生逻辑绕过。除了注入防护预编译还天然解决了单引号转义问题这是裸写 SQL 时最烦人的细节。long start System.currentTimeMillis(); PreparedStatement ps conn.prepareStatement( SELECT id FROM t_user WHERE username? AND password?); ps.setString(1, username); ps.setString(2, password); long cost System.currentTimeMillis() - start; if (cost 200) { System.err.println(slow sql [login]: cost ms); }这段代码补充一个我习惯加在 DAO 里的细节打印 SQL 执行耗时。实验教学系统的数据量通常不大但如果某条查询超过 200 毫秒优先检查t_submission表上的联合索引是否被LEFT JOIN破坏了。JDBC 连接串也要注意参数jdbc:mysql://localhost:3306/expms?useUnicodetruecharacterEncodingUTF-8serverTimezoneAsia/Shanghai少配一个characterEncoding中文写入就可能直接乱码。这算是 javaweb 项目里最常见的“配置半对”状态。5. javaweb 实验教学系统避坑记录驱动、乱码、事务和 404 的五个现场5.1 启动 Tomcat 报 ClassNotFoundExceptionmysql-connector 没进 WEB-INF/lib现象Tomcat 一启动日志立刻出现java.lang.ClassNotFoundException: com.mysql.cj.jdbc.Driver所有页面 500。你不知道该去改哪里因为这个传统项目没有 pom.xml所有 jar 都躺在普通lib文件夹里。原因Tomcat 只加载WEB-INF/classes与WEB-INF/lib下的类。放在项目根目录lib下的 jar 虽然能被 IDE 在编译期找到但运行期根本不会进入 Tomcat 的类路径于是驱动类找不到Class.forName直接抛异常。解决把mysql-connector-java.jar复制到web/WEB-INF/lib后右键 Add as Library然后再去 Project Structure 的 Artifacts 里查看输出项确认 jar 出现在部署包中。如果还不行删掉本地的.idea目录重新导入。这个坑在“idea运行javaweb项目配置”的搜索记录里常年居前核心就是类加载目录对不对。5.2 页面和数据库里的中文全变问号三层编码没对齐现象登录后 JSP 显示学生姓名是???写入t_experiment的实验名称也是???。用 Navicat 查看表数据中文已经变成问号但 JSP 文件确实保存成了 UTF-8。原因乱码链路断了三个点。第一JSP 顶部只写了pageEncodingUTF-8这只解决文件本身读取HTTP 响应头里的 ContentType 没设置浏览器按默认编码解析第二请求侧没有request.setCharacterEncoding(UTF-8)POST 表单中文进入内存就是错的第三JDBC URL 没带characterEncodingUTF-8MySQL 按数据库默认字符集接收字节存进去自然乱码。解决三层全部补齐。请求侧加 Filter 统一setCharacterEncoding(UTF-8)响应侧每个 JSP 写% page contentTypetext/html; charsetUTF-8 %JDBC URL 追加useUnicodetruecharacterEncodingUTF-8。另外数据库连接和表统一用utf8mb4而不是utf8因为utf8mb4覆盖生僻字和 Emoji。这里有个快速判断标准如果你导入 SQL 文件时中文正常但项目运行时乱码问题几乎都在 JDBC URL。5.3 数据插进去了却在列表里消失事务没提交被隐式回滚现象上传实验报告成功后跳转到列表 JSP 却看不到新记录去数据库查记录也不存在。多次重新上传后数据库里只有零星几条像是随机丢数据。原因某些项目包里的DBUtil.getConnection()会执行conn.setAutoCommit(false)但业务代码里只调用了executeUpdate()没有在 finally 中commit()。连接在关闭时JDBC 默认回滚未提交事务于是一条看似成功的 INSERT 实际上被悄悄撤销。解决写操作必须显式提交。最小修法是执行完立即conn.commit()但更稳的是把所有写操作放进同一个事务方法里try (Connection conn DBUtil.getConnection()) { conn.setAutoCommit(false); PreparedStatement ps1 conn.prepareStatement( INSERT INTO t_submission(student_id, experiment_id, version) VALUES (?,?,?)); ps1.executeUpdate(); PreparedStatement ps2 conn.prepareStatement( UPDATE t_experiment SET submit_count submit_count 1 WHERE id ?); ps2.executeUpdate(); conn.commit(); } catch (SQLException e) { conn.rollback(); throw e; }参数说明多条写操作必须包在同一个事务里任何一条失败都要整体回滚否则会出现“提交记录存在但实验统计数没变”的脏数据。类似的坑还有连接池maxActive设成 5学生并发交报告时全部卡在等连接日志里全是Connection is not available。实验教学系统的并发不高连接池参数按 10 到 20 配就够。5.4 IDEA 部署后永远 404Application context 与 artifact 名字不一致现象Tomcat 显示startup in xxx ms浏览器访问/login.jsp却 404直接访问静态资源也一样。控制台没有任何异常堆栈。原因IDEA 里 Local Tomcat 部署的 artifact 名和 Application context 不一致。例如 artifact 是expms_war_explodedIDEA 自动生成的根路径就成了/expms_war_exploded/你访问/expms/login.jsp自然找不到资源。解决在 Run/Debug Configurations 的 Deployment 标签页里把 Application context 手动填成/expms然后重新启动。如果还是 404翻 Tomcat 日志找The absolute uri: http://java.sun.com/jsp/jstl/core这一行这表示缺少 JSTL jar把jstl-1.2.jar放进WEB-INF/lib再重启。另外改完代码不要反复重启 Tomcat用 IDEA 的 Update resources 热部署效率高得多。5.5 下载报告时文件名乱码或变成 UUIDHTTP 响应头没做转码现象教师点击下载学生报告浏览器保存的文件名变成一长串 UUID或中文部分全部变成%E6%9D%8E这类编码串。文件内容本身完好但文件名对不上学生信息。原因文件存到服务器时已经用 UUID 重命名数据库中只保留了原始文件名。下载响应通过resp.setHeader(Content-Disposition, attachment;filename rawName)下发时编码不匹配中文文件名在跨浏览器场景下就乱码。解决下载时把文件名重新编码为UTF-8的 URL 编码或者直接转成ISO-8859-1返回给浏览器。我一般用第一套方案中的URLEncoder.encode(rawName, UTF-8)这样 Chrome 和 Edge 都能正确还原。与此同时上传时在t_submission里完整保留file_name字段不要在save_path里去解析文件名这两列分工要清楚。6. 交付前用一条 SQL 验证数据闭环再把乱码 Filter 收口成项目习惯6.1 验证系统数据闭环一条多表 JOIN 检查所有链路项目跑通不等于数据对。我接手这类项目后交付前一定会执行这条 SQL它把用户、实验、提交记录三张表串起来看能否还原学生视角的完整视图SELECT u.real_name, e.exp_name, s.version, s.score FROM t_user u JOIN t_submission s ON s.student_id u.id JOIN t_experiment e ON s.experiment_id e.id ORDER BY e.exp_name, u.real_name;这条 SQL 如果按预期返回每个人的提交版本和分数说明从登录到成绩查询的链路没有断裂。如果只返回部分数据去查t_submission是否有脏数据或者关联条件漏了版本过滤。再追加一条聚合 SQLSELECT experiment_id, COUNT(*), AVG(score) FROM t_submission WHERE score IS NOT NULL GROUP BY experiment_id就能给论文的测试部分提供真实数字而不是拿网上的假截图。6.2 用 Filter 统一收口编码和登录态再考虑迁移 Maven我每次拿到 JSP 老项目第一件事不是加功能而是先写一个EncodingAndAuthFilter把散落在各处页面的编码设置和权限校验集中起来WebFilter(/*) public class EncodingAndAuthFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { req.setCharacterEncoding(UTF-8); resp.setCharacterEncoding(UTF-8); HttpServletRequest request (HttpServletRequest) req; String uri request.getRequestURI(); if (uri.endsWith(login.jsp) || uri.endsWith(/login) || uri.contains(/static/)) { chain.doFilter(req, resp); return; } HttpSession session request.getSession(false); if (session null || session.getAttribute(user) null) { ((HttpServletResponse) resp).sendRedirect(login.jsp); } else { chain.doFilter(req, resp); } } }这段代码的意义在于所有页面不再重复处理中文编码和登录跳转Filter 统一挡在前面。放行规则把登录入口、登录 Servlet 和静态资源排除其余请求一律要 session。改完之后用浏览器无痕窗口直接访问/admin/courseManage.jsp你会发现已经进不去了这才是完整的权限闭环。再进一步可以把项目从传统 lib 结构迁移到 Maven在pom.xml里声明javax.servlet-api和mysql-connector-java用maven-war-plugin接管打包。这种“javaweb项目完整案例mysql”的升级路线既保留原项目业务代码又把依赖管理纳入了现代工程体系值得在论文最后一章提一笔。我现在接手任何 JSP 项目都会先跑通登录、再查乱码、再看事务这三个习惯能解决九成问题。希望帮到你。本文还有配套的精品资源点击获取
返回列表