简介:这是一套面向Java Web初学者的Servlet+JSP+MySQL宿舍管理系统实战源码,适合刚接触Web开发、需要完整小项目练手的学生与自学者。系统实现用户注册登录及宿舍信息的增删改查,涵盖Servlet处理请求、JSP渲染页面、JDBC连接MySQL等核心环节,帮助理解MVC分层与前后端数据交互的基本流程。压缩包共63个文件,约10.01MB,包含18个java源文件与18个class编译文件、5个jsp页面、3个jar依赖包,以及sql建库脚本、配置说明docx、功能描述txt和演示mp4视频,另附若干png界面截图,便于对照运行效果。已有1160人学习下载。资源附带数据库脚本与详细配置文档,可直接导入运行,配合录屏能快速定位环境搭建与数据库连接中的常见问题,是入门Web开发、积累课程设计素材的实用参考。
1. 从一份老派 JSP 源码包说起:Servlet 直连 MySQL 的宿舍管理系统能跑出什么
如果你手头只有 JDK、Tomcat 和一个 MySQL,却想完整走一遍「浏览器发请求 → Servlet 处理 → JDBC 落库 → JSP 渲染」的闭环,这套008_java+jsp+mysql简单宿舍管理系统是个合适的练手对象。它没有 Spring 全家桶,没有 MyBatis,也没有前后端分离,界面是 JSP 原生写法,业务逻辑全压在 Servlet 里,数据库靠 JDBC 直连。听起来原始,但正因为原始,你才能看清一个 JavaWeb 请求到底经过了哪些环节。它适合刚学完 Servlet 生命周期、想找一个能跑通的课程设计案例的人,也适合需要快速交付一份「基于 JSP 的毕设选题」原型的同学。资源包里带了nafeng.sql、详细配置.docx、功能描述.txt和源码目录sushe,拿到手就能对着配置文档一步步搭起来。
2. 环境搭建与数据库导入:把 nafeng.sql 跑进 MySQL 8.0
2.1 为什么这套代码对 JDK 和 Tomcat 版本敏感
Servlet 和 JSP 的 API 在 Java EE 到 Jakarta EE 的迁移中改过包名,javax.servlet.*和jakarta.servlet.*不能混用。这套源码用的是javax.servlet体系,所以 JDK 建议锁在 8 或 11,Tomcat 用 8.5 或 9.0。如果你直接上 Tomcat 10,启动时大概率报ClassNotFoundException: javax.servlet.http.HttpServlet,因为 Tomcat 10 已经全面切到jakarta.*。这不是代码写错了,是运行容器和编译期依赖对不上。常见做法是:JDK 8 + Tomcat 8.5 + MySQL 8.0,这个组合在旧教材和课程设计里兼容性最好。MySQL 8.0 的驱动类名是com.mysql.cj.jdbc.Driver,而 5.x 是com.mysql.jdbc.Driver,连接串还要带上serverTimezone,否则会报时区错误。
2.2 导入 nafeng.sql 并核对表结构
先把数据库建好,再导入 SQL 文件。用命令行或 MySQL Workbench 都可以,命令行更直接:
# 登录 MySQL,输入密码后进入交互界面 mysql -u root -p # 创建数据库,字符集用 utf8mb4 避免中文乱码 CREATE DATABASE nafeng DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; # 切换到该数据库 USE nafeng; # 导入同目录下的 nafeng.sql,注意路径换成你本机实际位置 source D:/download/008_java+jsp+mysql简单宿舍管理系统/数据/nafeng.sql;导入完成后执行SHOW TABLES;,正常应该看到用户表和宿舍信息表。宿舍表里通常有dorm_id、dorm_no、room_type、capacity这类字段,用户表里是username、password、role。如果导入时报ERROR 2002 (HY000): Can't connect to local MySQL server through socket,说明 MySQL 服务没启动,先去服务列表里把 MySQL 拉起来。如果导入后中文变成问号,检查建库时有没有指定utf8mb4,以及 SQL 文件本身的编码是不是 UTF-8。
2.3 改 JDBC 配置:四个参数决定能不能连上
源码里数据库连接信息一般写在某个工具类或db.properties里。你需要改的是 URL、用户名、密码、驱动类。以 MySQL 8.0 为例:
// DBUtil.java 中的连接方法,参数按你本机实际情况改 private static final String URL = "jdbc:mysql://localhost:3306/nafeng?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false"; private static final String USER = "root"; private static final String PASSWORD = "你的密码"; private static final String DRIVER = "com.mysql.cj.jdbc.Driver"; // 加载驱动,MySQL 8.0 必须用 cj 包下的类 Class.forName(DRIVER); Connection conn = DriverManager.getConnection(URL, USER, PASSWORD);useUnicode=true&characterEncoding=utf8保证中文能正确写入,serverTimezone=Asia/Shanghai解决 8.0 驱动的时区异常,useSSL=false在本地开发时省去证书配置。如果你用的是 MySQL 5.7,驱动类改成com.mysql.jdbc.Driver,URL 里可以去掉serverTimezone。改完这四个参数,把mysql-connector-java的 jar 包放进WEB-INF/lib,这一步漏了就会在启动时报No suitable driver found。
3. Servlet 与 JSP 的请求链路:登录、列表、增删改查怎么串起来
3.1 登录流程:从 login.jsp 到 LoginServlet 再到 session
登录是理解这套系统请求链路的最好入口。用户在login.jsp填用户名密码,表单action指向LoginServlet,方法为post。Servlet 里用request.getParameter拿到参数,拼 SQL 去用户表查,查到就把用户对象塞进session,然后重定向到宿舍列表页;查不到就转发回登录页并带一个错误提示。
// LoginServlet 的 doPost 核心逻辑 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); // 必须在取参数前设置,否则中文用户名乱码 String username = request.getParameter("username"); String password = request.getParameter("password"); UserDao dao = new UserDao(); User user = dao.login(username, password); // 内部用 PreparedStatement 防注入 if (user != null) { request.getSession().setAttribute("currentUser", user); // 登录态存 session response.sendRedirect("dormList"); // 重定向到列表 Servlet } else { request.setAttribute("msg", "用户名或密码错误"); request.getRequestDispatcher("login.jsp").forward(request, response); } }这里有两个容易翻车的点。第一,setCharacterEncoding必须放在getParameter之前,顺序反了中文就乱码。第二,登录成功后用sendRedirect而不是forward,避免刷新页面时重复提交表单。session 里存的 key 要和 JSP 页面里取的 key 一致,否则页面拿不到登录用户信息。
3.2 宿舍列表与分页:JSP 里嵌 Java 代码的写法
列表页通常由DormListServlet查出所有宿舍记录,存进request作用域,再转发到dormList.jsp渲染。JSP 里用 JSTL 或直接脚本片段遍历。这套源码是原生写法,大概率是脚本片段:
<!-- dormList.jsp 中的表格渲染片段 --> <table border="1"> <tr><th>宿舍号</th><th>房间类型</th><th>容纳人数</th><th>操作</th></tr> <% List<Dorm> list = (List<Dorm>) request.getAttribute("dormList"); for (Dorm d : list) { %> <tr> <td><%= d.getDormNo() %></td> <td><%= d.getRoomType() %></td> <td><%= d.getCapacity() %></td> <td> <a href="dormEdit?id=<%= d.getId() %>">编辑</a> <a href="dormDelete?id=<%= d.getId() %>" onclick="return confirm('确认删除?')">删除</a> </td> </tr> <% } %> </table><%= %>是输出表达式,<% %>是脚本片段。这种写法现在不推荐,但在课程设计里很常见,因为不用额外引入 JSTL 标签库。注意onclick里的confirm返回 false 时链接不会跳转,这是最省事的前端删除确认。如果列表为空,for循环不执行,页面就是一张空表,最好在循环前加一个if (list != null && !list.isEmpty())判断。
3.3 增删改查的 SQL 与参数绑定
新增和修改共用同一个表单页,通过是否有id参数区分。Servlet 里根据action或请求方法决定调insert还是update。删除一般走GET,带一个id参数。所有 SQL 都用PreparedStatement,不要用字符串拼接,否则一个' OR '1'='1就能绕过登录。
// DormDao 中的新增方法,? 是占位符,按顺序 set 参数 public int add(Dorm d) { String sql = "INSERT INTO dorm(dorm_no, room_type, capacity) VALUES(?, ?, ?)"; try (Connection conn = DBUtil.getConnection(); PreparedStatement ps = conn.prepareStatement(sql)) { ps.setString(1, d.getDormNo()); ps.setString(2, d.getRoomType()); ps.setInt(3, d.getCapacity()); return ps.executeUpdate(); // 返回受影响行数,1 表示成功 } catch (SQLException e) { e.printStackTrace(); return 0; } }try-with-resources会自动关闭Connection和PreparedStatement,比手动finally里 close 更省心。executeUpdate返回 int,插入成功是 1,失败是 0 或抛异常。如果新增后列表没变化,先看executeUpdate的返回值,再看有没有提交事务。MySQL 默认自动提交,但如果你在代码里手动开了事务却忘了commit,数据就不会落库。
4. 避坑与排查:这套老代码最容易卡住的五个地方
4.1 启动报 404:Servlet 映射路径对不上
现象是 Tomcat 启动没报错,但访问login.jsp之后的提交地址返回 404。原因通常是web.xml里的<url-pattern>和表单action不一致,或者用了@WebServlet注解但没生效。解决方法是先看web.xml里每个 Servlet 的映射,再核对 JSP 表单的action值,两者必须完全一致。如果项目同时存在web.xml和注解,以web.xml为准,注解会被覆盖。
4.2 中文乱码:三个位置都要设 UTF-8
现象是登录后用户名显示成问号,或者新增宿舍时中文存进数据库变乱码。原因可能出在 JSP 页面编码、Servlet 请求编码、数据库连接编码三处任意一处。解决方法是:JSP 顶部加<%@ page contentType="text/html;charset=UTF-8" %>,Servlet 里request.setCharacterEncoding("UTF-8")放在取参数前,JDBC URL 带上characterEncoding=utf8。三处都设了还乱码,就去检查 MySQL 表的字符集是不是utf8mb4。
4.3 ClassNotFoundException:驱动 jar 没放进 WEB-INF/lib
现象是启动或第一次连数据库时报ClassNotFoundException: com.mysql.cj.jdbc.Driver。原因是mysql-connector-java的 jar 包只加到了 IDE 的 build path,没有复制到WEB-INF/lib目录。Tomcat 运行时只认WEB-INF/lib下的 jar。解决方法是从 Maven 仓库或 MySQL 官网下载对应版本的 jar,手动复制进去,然后在 IDE 里刷新项目结构。
4.4 时区异常:MySQL 8.0 必须带 serverTimezone
现象是连接数据库时报The server time zone value '?D1ú±ê×?ê±??' is unrecognized。原因是 MySQL 8.0 驱动要求显式指定时区,而系统默认时区名它不认识。解决方法是在 JDBC URL 后面加?serverTimezone=Asia/Shanghai,如果 URL 里已经有其他参数,用&连接。这个坑在 MySQL 5.7 上不会出现,所以换版本后容易忽略。
4.5 删除后列表不刷新:重定向没写对
现象是点击删除后数据库里确实删了,但页面还显示旧数据。原因是删除 Servlet 处理完后用了forward回列表页,而列表数据是在 forward 之前查的,没有重新查询。解决方法是删除成功后用response.sendRedirect("dormList"),让浏览器重新发一次请求,触发列表 Servlet 重新查库。重定向的路径要写对,带斜杠和不带斜杠在 Tomcat 里解析结果不同。
5. 进阶改造:把 JDBC 直连换成连接池,再补一个登录过滤器
这套代码跑通之后,最值得做的两件事是加连接池和加登录拦截。JDBC 直连每次请求都新建连接,并发一高就顶不住。常见做法是引入 Druid 或 HikariCP,把DBUtil.getConnection()改成从池里取。以 Druid 为例,加一个druid.properties,在工具类静态块里初始化DataSource,之后所有 DAO 都从池里拿连接。改完之后,连接复用率上去了,响应时间会明显下降。
// 用 Druid 替换直连,静态块只执行一次 private static DataSource dataSource; static { try { Properties props = new Properties(); props.load(DBUtil.class.getClassLoader().getResourceAsStream("druid.properties")); dataSource = DruidDataSourceFactory.createDataSource(props); } catch (Exception e) { e.printStackTrace(); } } public static Connection getConnection() throws SQLException { return dataSource.getConnection(); // 从池里取,不再 DriverManager }druid.properties里配url、username、password、initialSize、maxActive这几个就够用。initialSize是启动时建几个连接,maxActive是最大并发连接数,本地开发设 5 和 20 就行。改完记得把mysql-connector-java和druid两个 jar 都放进WEB-INF/lib。
第二件事是加登录过滤器。现在任何人直接访问dormList都能看到数据,因为列表 Servlet 没校验 session。写一个LoginFilter实现Filter接口,在doFilter里判断session.getAttribute("currentUser")是否为空,为空就重定向到login.jsp,否则放行。在web.xml里配置过滤器拦截/*,但要把login.jsp、LoginServlet和静态资源排除掉,否则登录页本身也会被拦。这个过滤器加上之后,系统的安全边界才算立起来。
从那以后我每次拿到这种老派 JSP 源码包,都先确认 JDK、Tomcat、MySQL 三个版本能不能对上,再改 JDBC 四个参数,最后跑一遍登录和增删改查。顺序反了,就会在乱码和 404 之间来回折腾。希望帮到你。
本文还有配套的精品资源,点击获取