JavaWeb酒店管理系统实战:Servlet+JSP+MySQL源码与避坑指南
简介这是一套面向计算机专业学生与Java Web初学者、毕业设计选题者的酒店管理系统完整项目源码采用servletjspmysqljquery技术栈基于Myeclipse或Eclipse、jdk1.8、tomcat8与mysql5.6/5.7环境开发可用于课程设计、毕业设计参考或Java Web综合实战练习。压缩包共15个文件约186.16MB包含项目源码压缩包、jiudian.sql数据库脚本、数据库连接说明图、项目运行截图以及3段mp4功能演示与辅导视频、毕业设计论文、任务书、中期检查表、答辩PPT和说明文档覆盖从环境搭建到答辩展示的完整环节。资源中附带管理员与住店管理、餐饮相关管理等模块的实操录屏并给出初始可用账号便于快速运行与调试。目前已有1666人学习下载适合需要完整赛题方案、论文素材与排错思路的读者参考借鉴。1. 从一份能跑通的 ServletJSP 酒店管理系统源码说起很多同学做 JavaWeb 课程设计或毕设时第一反应是去搜「java 酒店管理系统源码 web项目 servletjspmysqljquery带论文和答辩文档」想找一份能直接跑、能改、能写进论文的完整工程。这个方向本身没问题问题在于大部分下载下来的压缩包要么缺 jar 包、要么数据库脚本对不上、要么 Tomcat 一启动就报 500最后时间全耗在环境上。我见过太多人卡在「MySQL 8.0 驱动类名写错」或者「JSP 页面放在 WEB-INF 外面导致 404」这种低级坑上。这篇笔记就按一线做法把 ServletJSPMySQLjQuery 这套经典 MVC 架构的酒店管理系统从建库、配环境、写核心业务到答辩文档要点一步步拆开讲清楚。适合正在做课程设计、毕设或者想用这个项目补 JavaWeb 基础的人。2. 环境搭建与数据库设计把地基打对2.1 JDK、Tomcat、MySQL 的版本匹配这套技术栈最怕版本乱配。Servlet 3.1 以上才支持注解方式配置JSP 2.3 对应 Tomcat 8 及以上。我一般固定用 JDK 8 Tomcat 8.5 MySQL 5.7 或 8.0原因是 JDK 8 对老项目兼容最好Tomcat 8.5 稳定且支持 Servlet 3.1 注解MySQL 8.0 是现在主流但驱动包必须换成mysql-connector-java-8.0.x。组件推荐版本关键原因JDK1.8兼容性最好避免模块化报错Tomcat8.5.x支持 Servlet 3.1 注解稳定MySQL5.7 或 8.08.0 需注意驱动类名和时区jQuery3.6.x兼容旧浏览器API 稳定MySQL 8.0 安装时记得选Use Legacy Authentication Method否则老驱动连不上。安装完执行mysql -u root -p能进就说明服务正常。如果报ERROR 2002 (HY000): Cant connect to local MySQL server through socket先检查服务有没有启动Windows 下用net start mysql80Linux 下systemctl start mysqld。2.2 酒店管理系统的库表设计酒店管理核心就几张表用户表、客房表、订单表、入住登记表。下面是我常用的建库脚本字段类型和索引都按实际查询场景定过。-- 创建数据库字符集用 utf8mb4 支持中文和特殊符号 CREATE DATABASE hotel_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE hotel_db; -- 用户表管理员和前台都存这里用 role 区分 CREATE TABLE t_user ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(100) NOT NULL, real_name VARCHAR(50), role TINYINT DEFAULT 0 COMMENT 0前台 1管理员, create_time DATETIME DEFAULT CURRENT_TIMESTAMP ); -- 客房表status 控制房态0空闲 1已预订 2已入住 3维修 CREATE TABLE t_room ( id INT PRIMARY KEY AUTO_INCREMENT, room_no VARCHAR(10) NOT NULL UNIQUE, room_type VARCHAR(20) NOT NULL, price DECIMAL(10,2) NOT NULL, status TINYINT DEFAULT 0, floor INT, remark VARCHAR(200) ); -- 订单表关联用户和房间记录入住离店时间 CREATE TABLE t_order ( id INT PRIMARY KEY AUTO_INCREMENT, order_no VARCHAR(32) NOT NULL UNIQUE, user_id INT, room_id INT, check_in DATE, check_out DATE, total_price DECIMAL(10,2), status TINYINT DEFAULT 0 COMMENT 0待入住 1已入住 2已退房 3已取消, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (room_id) REFERENCES t_room(id) );建表时room_no加唯一索引防止重复录入同一房间。t_order的order_no用时间戳加随机数生成避免并发重复。外键约束在课程设计里建议保留答辩时能体现数据完整性设计。如果 MySQL 8.0 执行外键报错检查两张表的引擎是否都是 InnoDB。2.3 项目目录结构与 jar 包放置标准 Maven 或普通 Web 项目目录如下关键是WEB-INF下必须有web.xmlServlet 3.0 以后可以注解替代但保留更稳妥和lib目录。hotel-system/ ├── src/ │ └── com/hotel/ │ ├── dao/ // 数据库操作 │ ├── service/ // 业务逻辑 │ ├── servlet/ // 控制器 │ └── util/ // 工具类 ├── WebContent/ │ ├── css/ js/ images/ │ ├── jsp/ // 页面放这里通过 Servlet 转发访问 │ └── WEB-INF/ │ ├── web.xml │ └── lib/ // 放 mysql 驱动、jstl 等 jarmysql-connector-java-8.0.x.jar、jstl.jar、standard.jar必须放进WEB-INF/lib不要只加到 IDE 的 Build Path否则部署到 Tomcat 会报ClassNotFoundException。这是血泪经验很多人本地跑得好好的一换机器就崩。3. ServletJSP 实现核心业务从登录到订单3.1 数据库连接工具类与 DAO 层写法先写一个DBUtil用静态代码块加载驱动避免每次请求都加载。MySQL 8.0 驱动类名是com.mysql.cj.jdbc.DriverURL 要加时区参数。public class DBUtil { private static final String URL jdbc:mysql://localhost:3306/hotel_db?useSSLfalseserverTimezoneAsia/ShanghaicharacterEncodingutf8; private static final String USER root; private static final String PWD 你的密码; static { try { Class.forName(com.mysql.cj.jdbc.Driver); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public static Connection getConn() throws SQLException { return DriverManager.getConnection(URL, USER, PWD); } public static void close(Connection conn, PreparedStatement ps, ResultSet rs) { // 依次关闭注意顺序和空判断 } }serverTimezone不写会报The server time zone value is unrecognized。useSSLfalse去掉启动警告。DAO 层用PreparedStatement防 SQL 注入比如登录查询public User login(String username, String password) { String sql SELECT * FROM t_user WHERE username? AND password?; try (Connection conn DBUtil.getConn(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, username); ps.setString(2, password); ResultSet rs ps.executeQuery(); if (rs.next()) { User u new User(); u.setId(rs.getInt(id)); u.setRole(rs.getInt(role)); return u; } } catch (SQLException e) { e.printStackTrace(); } return null; }try-with-resources 自动关连接比手动 close 干净。密码在真实项目里要加盐哈希课程设计可以先用明文但答辩时最好提一句改进方向。3.2 登录与权限过滤 Servlet登录 Servlet 接收表单调 Service 验证成功就把用户信息放进session然后重定向到主页。注意用request.getRequestDispatcher是转发URL 不变response.sendRedirect是重定向URL 变。登录成功用重定向防止刷新重复提交。WebServlet(/login) public class LoginServlet extends HttpServlet { protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding(UTF-8); String username req.getParameter(username); String password req.getParameter(password); UserService service new UserService(); User user service.login(username, password); if (user ! null) { req.getSession().setAttribute(currentUser, user); resp.sendRedirect(req.getContextPath() /room/list); } else { req.setAttribute(msg, 用户名或密码错误); req.getRequestDispatcher(/jsp/login.jsp).forward(req, resp); } } }权限过滤用Filter拦截/admin/*路径检查 session 里 role 是否为 1。没登录就跳登录页权限不够返回 403。Filter 里放行静态资源否则 css 和 js 加载不出来。3.3 客房列表与 jQuery 异步加载客房列表页用 JSP 展示数据由 Servlet 查出来放 request 域JSP 用 JSTL 遍历。如果要做无刷新筛选就用 jQuery 的$.ajax请求 Servlet 返回 JSON。// 按房态筛选客房点击按钮触发 $(#filterBtn).click(function () { $.ajax({ url: room/list, type: GET, data: { status: $(#statusSelect).val() }, dataType: json, success: function (data) { var html ; $.each(data, function (i, room) { html trtd room.roomNo /tdtd room.roomType /tdtd room.price /tdtd room.status /td/tr; }); $(#roomTable tbody).html(html); }, error: function () { alert(加载失败检查 Servlet 路径); } }); });Servlet 端用response.setContentType(application/json;charsetUTF-8)手动拼 JSON 或引入 Gson。注意 jQuery 的$.each第一个参数是索引第二个是元素。如果返回中文乱码检查response.setCharacterEncoding(UTF-8)有没有在getWriter()之前调用。3.4 订单创建与事务处理下单涉及两张表插入订单、更新房间状态。必须放在同一个事务里否则可能出现订单建了但房间还是空闲。public boolean createOrder(Order order) { Connection conn null; try { conn DBUtil.getConn(); conn.setAutoCommit(false); // 开启事务 String sql1 INSERT INTO t_order(order_no,user_id,room_id,check_in,check_out,total_price) VALUES(?,?,?,?,?,?); PreparedStatement ps1 conn.prepareStatement(sql1); // 设置参数... ps1.executeUpdate(); String sql2 UPDATE t_room SET status1 WHERE id? AND status0; PreparedStatement ps2 conn.prepareStatement(sql2); ps2.setInt(1, order.getRoomId()); int rows ps2.executeUpdate(); if (rows 0) { conn.rollback(); // 房间已被占回滚 return false; } conn.commit(); return true; } catch (SQLException e) { try { if (conn ! null) conn.rollback(); } catch (SQLException ex) {} return false; } finally { // 关闭资源恢复 autoCommit } }UPDATE语句带AND status0是乐观锁思路防止两个请求同时订同一间房。rows 0说明房间已被别人订走回滚并提示用户。这个细节答辩时是加分项。4. 避坑与常见问题排查4.1 启动报 500驱动类找不到或 URL 错误现象Tomcat 启动后访问页面报java.lang.ClassNotFoundException: com.mysql.jdbc.Driver。原因MySQL 8.0 驱动类名已改为com.mysql.cj.jdbc.Driver或者 jar 包没放进WEB-INF/lib。解决改类名确认 jar 在 lib 下IDE 里检查 Deployment Assembly 是否包含 lib。4.2 JSP 页面 404路径与 WEB-INF 限制现象浏览器访问/jsp/roomList.jsp报 404。原因JSP 放在WEB-INF下不能直接访问必须通过 Servlet 转发或者路径大小写不对。解决把 JSP 放WEB-INF/jsp/下统一走 Servlet 转发检查req.getRequestDispatcher(/WEB-INF/jsp/xxx.jsp)路径。4.3 中文乱码三处编码要统一现象表单提交后数据库里是问号。原因JSP 页面pageEncoding、Servletreq.setCharacterEncoding、数据库连接 URLcharacterEncoding三处不一致。解决JSP 头部% page contentTypetext/html;charsetUTF-8 pageEncodingUTF-8 %Servlet 第一行req.setCharacterEncoding(UTF-8)URL 加characterEncodingutf8。4.4 jQuery 请求成功但页面不更新现象$.ajax的 success 回调执行了但表格没变。原因选择器写错或者返回的 JSON 字段名和前端取的不一致。解决console.log(data)看返回结构确认dataType: json和 Servlet 返回的 Content-Type 匹配。如果 Servlet 返回的是字符串不是 JSONdataType改成text再手动JSON.parse。4.5 事务不回滚autoCommit 没关或异常被吞现象下单失败但订单记录还在。原因conn.setAutoCommit(false)没执行或者 catch 块里没调rollback()。解决确保事务开启在第一条 SQL 之前catch 里显式回滚finally 里恢复autoCommittrue再关连接。5. 答辩文档与论文写作的取巧点5.1 论文结构怎么对应代码论文里「系统设计」章节直接对应你的包结构DAO 层写数据访问Service 层写业务逻辑Servlet 写控制流程。画一张 MVC 架构图把 JSP 作为 View、Servlet 作为 Controller、DAOMySQL 作为 Model 标清楚。数据库设计章节把建表语句和 E-R 图放上去字段说明用表格。功能实现章节挑登录、客房管理、订单管理三个模块每个模块贴核心代码片段加流程图。5.2 答辩常问的五个问题第一个为什么用 Servlet 不用 SpringBoot答课程设计考察 JavaWeb 基础Servlet 能体现请求响应全流程SpringBoot 封装太深不利于展示底层理解。第二个session 和 cookie 区别答session 存服务端cookie 存客户端session 依赖 cookie 传 JSESSIONID。第三个怎么防 SQL 注入答全部用 PreparedStatement 预编译。第四个事务怎么保证一致性答下单时插入订单和更新房态放同一事务失败回滚。第五个jQuery 和原生 JS 比优势在哪答DOM 操作和 AJAX 封装更简洁兼容性好。5.3 让项目看起来更完整的三个小改动加一个简单的日志拦截器记录每个请求的 URL 和耗时答辩时能说「有性能监控意识」。把密码明文改成 MD5 加盐虽然简单但能体现安全考虑。订单号生成用System.currentTimeMillis() Random拼避免重复。这三个改动代码量不大但能让评委觉得你不是照抄的。我一般会建议学生答辩前把项目在另一台电脑上完整部署一遍从装 MySQL 到跑起来这个过程能暴露 90% 的环境问题。论文里的截图一定要自己跑出来的别用网上的。希望帮到你。本文还有配套的精品资源点击获取