尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Servlet+JSP+MySQL宿舍管理系统快速搭建指南

Servlet+JSP+MySQL宿舍管理系统快速搭建指南 简介这是一份面向Java Web开发初学者的完整宿舍管理系统实战项目基于ServletJSPMySQL技术栈实现原生界面开发聚焦Web基础架构与前后端协同逻辑适用于高校课程设计、自学入门及小型管理类应用练手。资源包共63个文件含18个Java源码核心Servlet与业务逻辑、18个Class编译文件、5个JSP页面登录、列表、增删改表单等视图层、1个SQL建库脚本nafeng.sql、1个配置文档详细配置.docx及1个实操演示视频mp4整体10.01MB结构清晰便于按模块理解MVC分层实现。已有1160人学习下载配套功能描述.txt与多张界面截图png帮助快速掌握数据库设计、JDBC连接、Session会话管理、表单提交与响应跳转等关键环节是打通Web开发全流程的典型教学案例。1. 为什么用 ServletJSPMySQL 做宿舍管理系统反而比 Spring Boot 更快跑通第一版这不是一个“过时技术怀旧帖”而是我带三届学生做课程设计、帮中小后勤部门搭轻量管理工具时反复验证的结论当你要在三天内交付一个可查、可增、可删、带登录权限的宿舍管理系统原型且部署环境只有 Tomcat 8.5 MySQL 5.7 JDK 8 的老旧机房服务器时原生 ServletJSPMySQL 不是退而求其次而是最短路径。它没有 Spring Boot 的自动装配黑匣子没有 MyBatis 的 XML 映射玄学所有请求流转、页面跳转、SQL 执行都裸露在代码里——你改一行doPost()就能立刻看到表单提交是否进来了out.print()一句就能确认数据有没有查出来% student.getName() %一写就明白 JSP 是怎么把 Java 对象吐到 HTML 里的。它不解决高并发、微服务、分布式事务但它能让你在没配好 Maven 仓库、没搞清RestController和Controller区别、甚至还不知道web.xml是干啥的阶段先做出一个能跑、能用、能交差的系统。适合刚学完 Java 基础和 JDBC、正卡在“学了但不会串起来”的人也适合需要快速验证业务流程、不想被框架约定绑架的后勤管理员。这不是终点但它是绝大多数 Java Web 入门者真正踩实的第一块砖。2. 从零搭建用最简依赖跑通登录宿舍列表双核心功能ServletJSPMySQL 的最小可行闭环不靠任何框架只靠 Java EE 规范原生能力。关键不是堆功能而是让请求从浏览器进来、经 Servlet 处理、查 MySQL、再用 JSP 渲染出去这条链路完全透明。下面每一步我都标出必须出现的文件名、必须写的代码段、必须执行的 SQL跳过任何“配置 IDE”“下载插件”类泛泛而谈。2.1 创建标准 Web 工程结构拒绝 IDE 自动魔改手动建目录Eclipse/IntelliJ 都要关掉“自动创建 web.xml”选项dorm-system/ ├── src/ │ └── main/ │ └── java/ │ └── servlet/ ← 所有 Servlet 放这里 │ ├── LoginServlet.java │ └── DormListServlet.java ├── WebContent/ ← JSP 和静态资源放这里不是 webapp │ ├── WEB-INF/ │ │ └── web.xml ← 必须手写不能缺 │ ├── login.jsp │ └── dorm_list.jsp └── lib/ └── mysql-connector-java-5.1.49.jar ← 下载地址https://dev.mysql.com/downloads/connector/j/5.1.html选 Platform Independent ZIP提示WebContent是 Eclipse 默认 Web RootIntelliJ 要在 Project Structure → Modules → Web → Web Resource Directory 设为WebContent。lib下的 jar 必须手动复制进去IDE 不会自动加到 Build Path —— 这是新手翻车第一坑。2.2 写web.xml定义 URL 映射这是整个请求路由的总开关?xml version1.0 encodingUTF-8? web-app xmlnshttp://xmlns.jcp.org/xml/ns/javaee xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd version4.0 !-- 登录入口 -- servlet servlet-nameLoginServlet/servlet-name servlet-classservlet.LoginServlet/servlet-class /servlet servlet-mapping servlet-nameLoginServlet/servlet-name url-pattern/login/url-pattern /servlet-mapping !-- 宿舍列表入口 -- servlet servlet-nameDormListServlet/servlet-name servlet-classservlet.DormListServlet/servlet-class /servlet servlet-mapping servlet-nameDormListServlet/servlet-name url-pattern/dorm/list/url-pattern /servlet-mapping /web-app逻辑说明servlet块声明一个 Servlet 类全限定名servlet-mapping把它绑定到/login这个路径。浏览器访问http://localhost:8080/dorm-system/login时Tomcat 就会实例化LoginServlet并调用其doPost()方法因为表单 method 是 post。参数说明version4.0对应 Servlet 4.0 规范要求 Tomcat 8.5xsi:schemaLocation必须完整少一个字符都会导致部署失败报web.xml is invalid。2.3 实现LoginServlet.java处理表单、校验、跳转package servlet; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; import java.sql.*; public class LoginServlet extends HttpServlet { private static final String DB_URL jdbc:mysql://localhost:3306/dorm_db?useSSLfalseserverTimezoneUTC; private static final String USER root; private static final String PASS 123456; // 生产环境绝不能硬编码 Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String username req.getParameter(username); String password req.getParameter(password); // 1. 简单非空校验真实项目需加密码加密 if (username null || username.trim().isEmpty() || password null || password.trim().isEmpty()) { req.setAttribute(error, 用户名或密码不能为空); req.getRequestDispatcher(/login.jsp).forward(req, resp); return; } // 2. 查询数据库注意此处未用连接池仅演示最小路径 boolean loginSuccess false; String role ; try (Connection conn DriverManager.getConnection(DB_URL, USER, PASS); PreparedStatement ps conn.prepareStatement(SELECT role FROM users WHERE username ? AND password ?)) { ps.setString(1, username); ps.setString(2, password); // 注意明文密码仅用于教学实际必须 bcrypt 加密 ResultSet rs ps.executeQuery(); if (rs.next()) { loginSuccess true; role rs.getString(role); } } catch (SQLException e) { e.printStackTrace(); req.setAttribute(error, 系统繁忙请稍后再试); req.getRequestDispatcher(/login.jsp).forward(req, resp); return; } // 3. 登录成功则存 session跳转失败则回传错误 if (loginSuccess) { HttpSession session req.getSession(); session.setAttribute(username, username); session.setAttribute(role, role); resp.sendRedirect(req.getContextPath() /dorm/list); // 重定向避免刷新重复提交 } else { req.setAttribute(error, 用户名或密码错误); req.getRequestDispatcher(/login.jsp).forward(req, resp); } } }逻辑说明与参数说明req.getParameter(username)获取表单中nameusername的输入值这是 JSP 表单与 Servlet 通信的唯一桥梁。req.getRequestDispatcher(/login.jsp).forward(...)是请求转发URL 不变适合错误回显resp.sendRedirect(...)是重定向URL 变适合成功后跳转防止 F5 刷新重复提交。try-with-resources自动关闭Connection和PreparedStatement避免连接泄漏——这是 JDBC 最易踩的内存泄漏坑。DB_URL中useSSLfalse是 MySQL 8.0 默认强制 SSL 的绕过方案开发环境可用serverTimezoneUTC解决时区乱码缺一不可。2.4 编写login.jsp原生 JSP 混合 HTML零框架渲染% page contentTypetext/html;charsetUTF-8 languagejava % html head title宿舍管理系统 - 登录/title style .form-group { margin: 10px 0; } .error { color: red; font-size: 14px; } /style /head body div stylemax-width: 400px; margin: 50px auto; padding: 20px; border: 1px solid #ddd; h2宿舍管理系统登录/h2 form action${pageContext.request.contextPath}/login methodpost div classform-group label用户名/label input typetext nameusername value${param.username} required /div div classform-group label密码/label input typepassword namepassword required /div div classform-group button typesubmit登录/button /div div classerror % request.getAttribute(error) ! null ? request.getAttribute(error) : % /div /form /div /body /html逻辑说明${pageContext.request.contextPath}动态获取应用上下文路径如/dorm-system避免硬编码保证部署到任意路径都有效。% ... %是 JSP 表达式直接输出 Java 表达式结果这里用来显示错误信息。value${param.username}让表单在提交失败后保留已输入的用户名提升用户体验——这是原生 JSP 比纯 HTML 表单强的地方。3. 数据库建模与连接用最朴素 SQL 定义宿舍核心实体MySQL 不是配角而是整个系统的数据基石。这里不讲范式理论只列宿舍管理系统必须的三张表及其建表语句每句都经过本地 MySQL 5.7 实测字段命名直白无冗余索引。3.1 创建数据库与用户表支撑登录鉴权-- 创建数据库UTF8MB4 支持 emoji生产环境必须 CREATE DATABASE IF NOT EXISTS dorm_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- 切换数据库 USE dorm_db; -- 用户表存储管理员、宿管、学生三类角色 CREATE TABLE users ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(100) NOT NULL, -- 明文仅教学实际存 bcrypt hash role ENUM(admin, warden, student) NOT NULL DEFAULT student, real_name VARCHAR(30), phone VARCHAR(20), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- 插入测试管理员密码明文 123456 INSERT INTO users (username, password, role, real_name) VALUES (admin, 123456, admin, 系统管理员);参数说明CHARACTER SET utf8mb4是 MySQL 5.5.3 推荐的 UTF-8 实现utf8mb4_unicode_ci排序规则支持中文正确比较。ENUM类型限制role只能取三个值比VARCHAR更安全且省空间。DEFAULT CURRENT_TIMESTAMP让created_at自动填入当前时间无需 Java 代码生成。3.2 创建宿舍表与学生表建立一对多关系-- 宿舍表楼号、房间号、容纳人数、当前入住数 CREATE TABLE dorms ( id INT PRIMARY KEY AUTO_INCREMENT, building VARCHAR(10) NOT NULL COMMENT 如 A栋、B栋, room_number VARCHAR(10) NOT NULL COMMENT 如 101、202, capacity INT NOT NULL DEFAULT 4 COMMENT 最大容纳人数, current_occupancy INT NOT NULL DEFAULT 0 COMMENT 当前已住人数, status ENUM(空闲, 已满, 维修中) NOT NULL DEFAULT 空闲, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- 学生表关联宿舍记录基本信息 CREATE TABLE students ( id INT PRIMARY KEY AUTO_INCREMENT, student_id VARCHAR(20) NOT NULL UNIQUE COMMENT 学号, name VARCHAR(30) NOT NULL, gender ENUM(男, 女) NOT NULL, major VARCHAR(50), dorm_id INT COMMENT 外键指向 dorms.id, check_in_date DATE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (dorm_id) REFERENCES dorms(id) ON DELETE SET NULL ); -- 插入测试数据 INSERT INTO dorms (building, room_number, capacity, status) VALUES (A栋, 101, 4, 空闲), (B栋, 202, 6, 已满); INSERT INTO students (student_id, name, gender, major, dorm_id, check_in_date) VALUES (2021001, 张三, 男, 计算机, 1, 2024-09-01), (2021002, 李四, 女, 外语, 1, 2024-09-01);逻辑说明FOREIGN KEY (dorm_id) REFERENCES dorms(id) ON DELETE SET NULL定义外键约束当删除宿舍时对应学生记录的dorm_id设为NULL而非级联删除学生——符合宿舍调整的业务逻辑。COMMENT字段注释在 Navicat 或命令行SHOW CREATE TABLE students中可见是团队协作的低成本文档。3.3 在 Servlet 中复用数据库连接封装成工具类避免重复代码新建src/main/java/utils/DBUtil.javapackage utils; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class DBUtil { private static final String URL jdbc:mysql://localhost:3306/dorm_db?useSSLfalseserverTimezoneUTCcharacterEncodingutf8mb4; private static final String USER root; private static final String PASSWORD 123456; static { try { Class.forName(com.mysql.jdbc.Driver); // MySQL 5.x 驱动类名 } catch (ClassNotFoundException e) { throw new RuntimeException(MySQL Driver not found!, e); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USER, PASSWORD); } // 关闭连接的静态方法供各 Servlet 调用 public static void closeConnection(Connection conn) { if (conn ! null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }使用方式在DormListServlet.java中替换原生DriverManager.getConnection(...)为Connection conn null; try { conn DBUtil.getConnection(); // ... 执行查询 } finally { DBUtil.closeConnection(conn); // 确保关闭 }为什么这么做static块确保驱动只加载一次避免每次 getConnection 都反射加载。closeConnection封装关闭逻辑防止某处忘记conn.close()导致连接耗尽——这是 Tomcat 下最常见的“Too many connections”错误根源。4. 宿舍列表页实现JSP 原生循环 Servlet 数据传递dorm_list.jsp是整个系统的信息中枢它必须清晰展示宿舍状态、入住学生并支持按楼号筛选。这里不用任何 JS 框架纯 JSP 标签 EL 表达式 JavaBean代码即文档。4.1 编写DormListServlet.java查询宿舍及关联学生package servlet; import utils.DBUtil; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; import java.sql.*; import java.util.ArrayList; import java.util.List; // 宿舍实体类JavaBean class Dorm { private int id; private String building; private String roomNumber; private int capacity; private int currentOccupancy; private String status; // getter/setter 省略IDE 自动生成即可 public int getId() { return id; } public void setId(int id) { this.id id; } // ... 其他 getter/setter } // 学生实体类 class Student { private String studentId; private String name; private String gender; private String major; private String checkInDate; // getter/setter 省略 } public class DormListServlet extends HttpServlet { Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 1. 检查登录态 HttpSession session req.getSession(false); if (session null || session.getAttribute(username) null) { resp.sendRedirect(req.getContextPath() /login.jsp); return; } // 2. 获取筛选参数GET 请求 String building req.getParameter(building); ListDorm dormList new ArrayList(); String sql SELECT d.id, d.building, d.room_number, d.capacity, d.current_occupancy, d.status, s.student_id, s.name, s.gender, s.major, s.check_in_date FROM dorms d LEFT JOIN students s ON d.id s.dorm_id WHERE 11; ListObject params new ArrayList(); if (building ! null !building.trim().isEmpty()) { sql AND d.building ?; params.add(building); } sql ORDER BY d.building, d.room_number; try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { // 设置动态参数 for (int i 0; i params.size(); i) { ps.setObject(i 1, params.get(i)); } ResultSet rs ps.executeQuery(); // 3. 手动组装 Dorm 学生列表因 LEFT JOIN 会产生多行 Dorm currentDorm null; ListStudent currentStudents new ArrayList(); while (rs.next()) { int dormId rs.getInt(id); if (currentDorm null || currentDorm.getId() ! dormId) { // 新宿舍保存上一个并初始化新对象 if (currentDorm ! null) { currentDorm.setStudents(currentStudents); dormList.add(currentDorm); } currentDorm new Dorm(); currentDorm.setId(dormId); currentDorm.setBuilding(rs.getString(building)); currentDorm.setRoomNumber(rs.getString(room_number)); currentDorm.setCapacity(rs.getInt(capacity)); currentDorm.setCurrentOccupancy(rs.getInt(current_occupancy)); currentDorm.setStatus(rs.getString(status)); currentStudents new ArrayList(); } // 添加学生若 s.student_id 为 null说明该宿舍无学生 if (rs.getString(student_id) ! null) { Student stu new Student(); stu.setStudentId(rs.getString(student_id)); stu.setName(rs.getString(name)); stu.setGender(rs.getString(gender)); stu.setMajor(rs.getString(major)); stu.setCheckInDate(rs.getString(check_in_date)); currentStudents.add(stu); } } // 处理最后一个宿舍 if (currentDorm ! null) { currentDorm.setStudents(currentStudents); dormList.add(currentDorm); } } catch (SQLException e) { e.printStackTrace(); req.setAttribute(error, 查询宿舍列表失败); } req.setAttribute(dormList, dormList); req.getRequestDispatcher(/dorm_list.jsp).forward(req, resp); } }关键点解析LEFT JOIN确保即使宿舍空闲无学生也能查出宿舍信息s.student_id IS NULL在 Java 层判断。手动组装Dorm对象及其ListStudent是原生 JDBC 的典型做法虽不如 MyBatis 自动映射优雅但逻辑完全可控调试时System.out.println一行就能看到中间结果。req.setAttribute(dormList, dormList)将数据存入请求域供 JSP 通过 EL 表达式读取。4.2 编写dorm_list.jsp用 JSTL EL 渲染嵌套数据注意JSTL 不是必须但比% %脚本片段更清晰。需下载jstl-1.2.jar和standard-1.1.2.jar放入WEB-INF/lib/。% page contentTypetext/html;charsetUTF-8 languagejava % % taglib prefixc urihttp://java.sun.com/jsp/jstl/core % html head title宿舍列表/title style table { width: 100%; border-collapse: collapse; margin-top: 20px; } th, td { border: 1px solid #ccc; padding: 8px; text-align: left; } .status-free { color: green; } .status-full { color: red; } .status-maintain { color: orange; } /style /head body h1宿舍管理系统 - 宿舍列表/h1 !-- 筛选表单 -- form methodget label按楼号筛选/label select namebuilding option value全部/option option valueA栋 ${param.building A栋 ? selected : }A栋/option option valueB栋 ${param.building B栋 ? selected : }B栋/option /select button typesubmit查询/button /form !-- 宿舍列表 -- c:if test${not empty dormList} table thead tr th楼号/th th房间号/th th容量/当前/th th状态/th th入住学生/th /tr /thead tbody c:forEach items${dormList} vardorm tr td${dorm.building}/td td${dorm.roomNumber}/td td${dorm.capacity}/${dorm.currentOccupancy}/td td span classstatus-${dorm.status} ${dorm.status} /span /td td c:if test${empty dorm.students} em空闲/em /c:if c:forEach items${dorm.students} varstu varStatusstatus ${stu.name}(${stu.studentId})${status.last ? : } /c:forEach /td /tr /c:forEach /tbody /table /c:if c:if test${empty dormList empty error} p暂无宿舍数据/p /c:if c:if test${not empty error} p classerror${error}/p /c:if pa href${pageContext.request.contextPath}/login.jsp返回登录/a/p /body /html逻辑说明c:forEach遍历dormListvardorm绑定每个宿舍对象${dorm.building}直接取属性值。${param.building A栋 ? selected : }实现下拉框记忆上次选择是 JSP 原生状态保持的惯用法。c:if test${empty dorm.students}判断宿舍是否空闲避免 NPE。${status.last ? : }在学生列表末尾不加顿号细节决定专业度。5. 避坑指南五个血泪经验总结全是部署时真实翻车现场这节不讲原理只列我在机房、学生作业、外包小项目里亲手踩过的坑。每一条都附带现象、原因、解决照着做能省掉至少 3 小时排查时间。5.1 现象Tomcat 启动成功但访问/dorm-system/login报 404原因web.xml中url-pattern写成了/login.do但 JSP 表单action写的是/login两者不匹配或servlet-class的包路径与实际.java文件物理路径不一致如servlet.LoginServlet对应src/servlet/LoginServlet.java若错放成src/LoginServlet.java则找不到类。解决检查web.xml的url-pattern与表单action完全一致在 Eclipse 中右键项目 → Properties → Java Build Path → Source确认src/main/java是源文件夹查看 Tomcatlogs/catalina.out搜索ClassNotFoundException或Servlet not available错误。5.2 现象登录成功后跳转/dorm/list页面空白控制台无报错原因DormListServlet的doGet方法中req.getRequestDispatcher(/dorm_list.jsp).forward(req, resp)的路径/dorm_list.jsp是相对于WebContent目录的但实际文件放在WebContent/dorm_list.jsp而requestDispatcher的路径必须以/开头且是 WebRoot 下的相对路径——这里写对了真正原因是dorm_list.jsp里用了c:forEach却没引入 JSTL 库导致 JSP 编译失败Tomcat 默认静默忽略错误返回空白页。解决确认WEB-INF/lib/下有jstl-1.2.jar和standard-1.1.2.jar下载地址https://archive.apache.org/dist/jakarta/taglibs/standard/binaries/在dorm_list.jsp顶部加% taglib prefixc urihttp://java.sun.com/jsp/jstl/core %查看 Tomcatlogs/localhost.date.log搜索JasperException。5.3 现象MySQL 查询中文字段显示为??如building字段存的是A栋查出来是A??原因四个环节任一没设 UTF-8① MySQL 服务器默认字符集不是utf8mb4② 数据库创建时没指定CHARACTER SET utf8mb4③DB_URL中没加characterEncodingutf8mb4④ JSP 页面没设% page contentTypetext/html;charsetUTF-8 %。解决执行SHOW VARIABLES LIKE character_set_%;确认 MySQL 全局设置重建数据库CREATE DATABASE dorm_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;DB_URL必须包含characterEncodingutf8mb4所有 JSP 顶部加contentType声明。5.4 现象学生表插入时报Cannot add or update a child row: a foreign key constraint fails原因students.dorm_id外键指向dorms.id但插入学生时dorm_id值在dorms表中不存在如dorm_id999但dorms表最大id是 5。解决先查SELECT * FROM dorms;确认目标宿舍存在在DormListServlet的学生插入逻辑前加 SQL 校验SELECT COUNT(*) FROM dorms WHERE id ?使用ON DELETE SET NULL而非CASCADE避免误删宿舍连带清空学生。5.5 现象多次登录后 Tomcat 内存溢出java.lang.OutOfMemoryError: Java heap space原因LoginServlet中创建了大量new String()或未关闭ResultSet但根本原因是 Session 没清理。HttpSession session req.getSession();默认创建长期 Session学生反复登录不退出Session 对象堆积。解决在LoginServlet登录成功后显式设置 Session 过期时间session.setMaxInactiveInterval(30 * 60);30 分钟在logout.jsp中调用session.invalidate();Tomcatbin/catalina.shLinux或catalina.batWindows中增加 JVM 参数-Xms512m -Xmx1024m。6. 进阶技巧用 Filter 实现统一登录拦截与字符编码过滤做到上面五章你已经能交付一个可运行的宿舍管理系统。但真正的工程化藏在那些“看不见”的基础设施里。Filter 是 Servlet 规范提供的拦截器它不修改业务逻辑却能让整个系统更健壮、更安全。下面两个 Filter我坚持在每一个 ServletJSP 项目里手写从不依赖框架。6.1 登录拦截 Filter保护所有/dorm/*路径新建src/main/java/filter/LoginFilter.javapackage filter; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; public class LoginFilter implements Filter { Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request (HttpServletRequest) req; HttpServletResponse response (HttpServletResponse) resp; String path request.getServletPath(); // 放行登录页、静态资源、登录接口 if (path.startsWith(/login.jsp) || path.equals(/login) || path.endsWith(.css) || path.endsWith(.js) || path.endsWith(.png) || path.endsWith(.jpg)) { chain.doFilter(req, resp); return; } // 检查 Session 是否有登录用户 HttpSession session request.getSession(false); if (session null || session.getAttribute(username) null) { // 未登录重定向到登录页并保留原请求路径作为参数 String originalUrl request.getRequestURI(); if (request.getQueryString() ! null) { originalUrl ? request.getQueryString(); } response.sendRedirect(request.getContextPath() /login.jsp?redirect java.net.URLEncoder.encode(originalUrl, UTF-8)); return; } // 已登录放行 chain.doFilter(req, resp); } Override public void init(FilterConfig filterConfig) throws ServletException {} Override public void destroy() {} }注册到web.xml加在/web-app之前filter filter-nameLoginFilter/filter-name filter-classfilter.LoginFilter/filter-class /filter filter-mapping filter-nameLoginFilter/filter-name url-pattern/dorm/*/url-pattern /filter-mapping效果访问/dorm/list时Filter 自动检查登录态未登录则跳转login.jsp?redirect/dorm/list登录成功后在LoginServlet中读取redirect参数并跳转实现“想去哪就去哪”的体验。这才是真正的登录拦截不是每个 Servlet 里写 if 判断。6.2 字符编码 Filter一劳永逸解决 POST 中文乱码新建src/main/java/filter/EncodingFilter.javapackage filter; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import java.io.IOException; public class EncodingFilter implements Filter { private String encoding UTF-8; Override public void init(FilterConfig config) throws ServletException { String enc config.getInitParameter(encoding); if (enc ! null !enc.trim().isEmpty()) { encoding enc; } } Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request (HttpServletRequest) req; // GET 请求的编码由 Tomcat server.xml 的 URIEncoding 控制此处只处理 POST if (POST.equalsIgnoreCase(request.getMethod())) { request.setCharacterEncoding(encoding); } chain.doFilter(req, resp); } Override public void destroy() {} }注册到web.xmlfilter filter-nameEncodingFilter/filter-name filter-classfilter.EncodingFilter/filter-class init-param param-nameencoding/param-name param-valueUTF-8/param-value /init-param /filter filter-mapping filter-nameEncodingFilter/filter-name url-pattern/*/url-pattern /filter-mapping为什么必须用 Filterrequest.setCharacterEncoding(UTF-8)必须在request.getParameter()之前调用否则第一次调用getParameter()会锁定编码。Filter 在所有 Servlet 之前执行确保万无一失。6.3 最后一个习惯用web.xml的welcome-file-list设置首页在web.xml的/web-app之前添加welcome-file-list p a hrefhttps://download.csdn.net/download/qq_34715954/19512984 stylecolor:#ec7500;font-size:14px; 本文还有配套的精品资源点击获取 /a img altmenu-r.4af5f7ec.gif srchttps://csdnimg.cn/release/wenkucmsfe/public/img/menu-r.4af5f7ec.gif stylewidth:16px;margin-left:4px;vertical-align:text-bottom;cursor:text; /p
返回列表