Tomcat6时代的JavaWeb酒店管理系统:JDBC+Servlet+DAO三层实战解析
简介这套基于Java Web的在线酒店管理系统资料包面向Java Web课程设计或毕业设计人群也适合需要快速搭建前后台业务闭环的开发者。系统覆盖前台会员注册、登录、网上预订与退房后台客房、入住、预订、退房、会员和系统管理功能完整便于理解分层架构与数据库设计。压缩包共221个文件大小约5.91MB以72个java源码、72个class编译文件及42个jsp页面为核心同时附带MySQL数据库脚本、doc/docx设计文档与翻译、css/js前端资源及png/jpg界面图片方便对照源码检查页面交互、DAO实现和表结构。附带sql数据库脚本可直接导入MySQL工程可部署到Tomcat并使用MyEclipse打开完整的DAO、JSP与实体类分层代码适合作为课题设计参考、论文资料佐证和二次开发基础。目前已有376人学习下载可帮助读者快速跑通预订房间、入住登记到退房结算的完整流程。1. 拿到一套Tomcat 6时代的JavaWeb酒店管理系统先别嫌它老这正是能看懂的源码你搜到这份资源时大概和我第一次见到它时一样Tomcat 6.0、MyEclipse 6.0、MySQL三个关键词直接把人拉回十年前。但恰恰因为它是那个年代的产物整站没有Spring、没有MyBatisJSP Servlet DAO三层写得明明白白每个类名都是拼音HuiyuanDAOImpl、DengjiDAOImpl、TuifangDAOImpl反而成了新手理解Java Web请求-处理-响应全流程最直观的教材。它覆盖前台会员注册、登录、在线订房、退房后台房型管理、入住登记、预订确认、退房记录导出Excel整套业务闭环是完整的。适合两类人一是刚学完Servlet和JSP、想找一个完整项目拆着看的学生二是要快速交付课程设计或毕设、需要一套能跑通还能讲清楚业务的从业者。前提是你别用现在的Spring Boot习惯去要求它跟着它的技术栈走它能给你的比预期多。2. 搭环境先过三关JDK、Tomcat、MySQL的版本咬合问题2.1 为什么必须用JDK 1.6和Tomcat 6.0而不是顺手装个新版这套系统的编译级别和运行环境是按照2009年前后的技术栈设定的JDK版本不对后面全是坑。我最初拿到时图省事装了JDK 1.8和Tomcat 8.5结果Web项目部署后直接报内存溢出和类加载异常折腾了整整一个下午。先看JDK环境变量怎么配。解压JDK 1.6后安装版或绿色版都可以需要设置JAVA_HOME、PATH和CLASSPATH三个系统变量JAVA_HOMEC:\Java\jdk1.6.0_45 PATH%JAVA_HOME%\bin;%PATH% CLASSPATH.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar三个变量的作用分别对应编译、执行、类库查找。dt.jar和tools.jar是JDK自带的工具类库早期项目编译时依赖这两个包现在的新版JDK里它们的位置变了这也是为什么你强行用JDK 1.8编译老项目会报错的原因之一。配置完成后在命令行输入java -version验证看到1.6.0_45就对了。Tomcat 6.0对应的是Servlet 2.5规范它和JDK 1.6是官方测试过的组合。如果你非要用Tomcat 7或8项目里web.xml的头部声明也得跟着升级否则Servlet解析阶段会出兼容性警告这种隐藏问题排查起来极费时间。我一般会直接按摘要里的配置走不给自己找麻烦。2.2 MyEclipse 6.0导入工程发布路径和编译目录是第一个翻车点MyEclipse 6.0是个远古IDE界面和现在的Eclipse差不太多但有个细节不一样它默认的编译输出目录是classes文件夹而非target/classes。这套项目里的目录结构是按WebRoot/WEB-INF/classes组织的导入时选错编译输出目录会导致启动报找不到类。导入流程是这样打开MyEclipse选择File - Import - General - Existing Projects into Workspace选中压缩包解压后的webproject目录导入。如果你发现导入失败八成是.classpath或.project文件里的路径引用和实际目录对不上手动删掉这两个文件重新导入就行MyEclipse会自动按目录结构重新生成。导入后需要做两件事第一右键项目选Properties - Java Compiler把Compiler compliance level设为1.6第二在MyEclipse - Servers面板里新建Tomcat 6.0服务器指向本机Tomcat安装目录然后把工程Add Deployment到服务器上。2.3 数据库导入SQL脚本执行顺序和字符集不能糊弄这套系统用的是MySQL摘要里说“把数据库文件导入到MySQL数据库内”。解压后你会看到一个.sql文件一般叫webproject.sql或hotel.sql。导入前建议先用文本编辑器打开看一眼确认里面是否有CREATE DATABASE语句。如果有直接进MySQL执行即可如果没有需要手动先建库再导入。mysql -u root -p mysql CREATE DATABASE IF NOT EXISTS webproject DEFAULT CHARSET utf8; mysql USE webproject; mysql SOURCE D:/webproject.sql;这里多提一句字符集。老项目的SQL脚本大多是GBK或GB2312编码如果你的MySQL默认字符集是utf8mb4导入后网页上显示的酒店名称、房型描述全是乱码。我习惯的做法是用记事本打开SQL文件另存为UTF-8编码后再导入同时建库语句里指定utf8字符集——两头都堵住才稳。数据库账号密码也要留意。项目的DBUtil或DBConnection类里写死了连接用户名和密码默认通常是root和空密码或123456如果你的MySQL设了密码直接改这个类里的配置再编译。这个配置一般长这样String url jdbc:mysql://localhost:3306/webproject?useUnicodetruecharacterEncodingutf8; String username root; String password 123456;提示改完数据库配置记得重新发布工程到Tomcat否则用的还是旧配置。3. 源码结构拆解从那一串DAOImpl类名反推整个业务地图3.1 类名就是需求文档十个DAO类对应十张业务底表拆这套源码最过瘾的地方是它的类命名完全够直白不需要看框架映射配置就能明白每个类承担的角色。我们把项目正文里提到的类名整理一下它们基本就是系统的全部业务域类名对应业务核心操作UserDAOImpl系统用户管理后台登录验证、用户增删改HuiyuanDAOImpl会员管理注册、登录、积分/等级维护RoomtypeDAOImpl / RoomLeibieDAOImpl房型分类房型新增、价格修改、状态查询RoomreserveDAOImpl房间预订预订单创建、取消、查询DengjiDAOImpl入住登记散客登记、订单转入住TuifangDAOImpl退房管理结算金额、释放房间RoomreserveHistoryDAOImpl预订历史历史订单归档查询YuDingDanHistoryExcel预订订单Excel导出导出到xlsTuifangRecordsExcel退房记录Excel导出退房数据导出这套命名就是典型的“拼音即表意”风格初看觉得不够专业但对学习来说反而是优点——你不用去翻数据库注释就知道这个DAO是管什么的。对照这个表去打开DAO实现类你看到的CRUD也基本一致几乎没有跳业务逻辑。3.2 DAO层的JDBC写法没有框架的增删改查反而更适合看细节现在的项目都用MyBatis或JPA一个Select注解搞定查询新手根本看不到底层连接怎么打开、预处理语句怎么传参。这套源码用的是原生的JDBC动手跟着写一遍对理解Connection、PreparedStatement、ResultSet三个核心接口的帮助比看十篇教程都大。我随便打开一个DAO实现类里面的查询方法写法大致是这样public Huiyuan findHuiyuanById(int id) { Connection conn null; PreparedStatement ps null; ResultSet rs null; Huiyuan huiyuan null; try { conn DBUtil.getConnection(); String sql SELECT * FROM huiyuan WHERE id ?; ps conn.prepareStatement(sql); ps.setInt(1, id); rs ps.executeQuery(); if (rs.next()) { huiyuan new Huiyuan(); huiyuan.setId(rs.getInt(id)); huiyuan.setName(rs.getString(name)); } } catch (SQLException e) { e.printStackTrace(); } finally { DBUtil.close(rs, ps, conn); } return huiyuan; }这套写法的核心思想就是三步取连接、拼SQL、释放资源。注意它用的是PreparedStatement而不是Statement好处是SQL注入风险低而且参数用?占位传入值类型由setInt、setString这些方法显式确定。这套源码里的DAO普遍采用这个模式你读懂一个类其余九个类全通。对比现在的框架写法这套代码显得啰嗦但正是这个“啰嗦”让你能看到每一行代码在干什么。学JDBC阶段我一直建议学生把这种代码手抄一遍不是让你以后还这么写而是你看得懂底层以后用MyBatis出问题时能推测到它内部在做什么。3.3 JSP页面与DAO之间的调度登录请求的完整生命周期最有教学价值的一条链路是后台登录。login.jsp发出表单请求后Servlet接收参数调用UserDAOImpl或HuiyuanDAOImpl比较账号密码再把结果转发回页面。这条链路虽然短但把JavaWeb的核心知识点全部串起来了。我打开登录相关的代码梳理了一下典型的调用逻辑如下// LoginServlet中的核心片段 String username request.getParameter(username); String password request.getParameter(password); UserDAO dao new UserDAOImpl(); User user dao.findUserByUsernameAndPassword(username, password); if (user ! null) { request.getSession().setAttribute(currentUser, user); response.sendRedirect(admin/index.jsp); } else { request.setAttribute(errorMessage, 用户名或密码错误); request.getRequestDispatcher(login.jsp).forward(request, response); }这段代码反映了几层信息getParameter负责取前端数据DAO返回User对象判断登录成败成功走sendRedirect改变URL并写入会话失败走forward保留当前请求并在原页面回显错误信息。重定向和转发的差异在教科书里讲一百遍都不容易懂这里看到真实场景里的用法比背十遍概念都顶用。如果你要改这套系统把这段代码注释掉自己重写一遍再调试几次断点JavaWeb的请求流就成了身体记忆。4. 主业务闭环拆解从网上预订到退房结算和Excel导出的完整链路4.1 前台订房链路会员注册到预订确认的状态流转这套系统的前台入口是netroomreserve.jsp对应摘要里说的“前台预订房间界面”。它的业务链路是游客注册成为Huiyuan登录后选择房型填写入住日期和天数提交预订单。预订单在数据库里用一张roomreserve表存储关键字段大致包含会员ID、房型ID、入住时间、退房时间、预订状态。状态字段是这个系统的精髓预订单默认是“待确认”还是“直接生效”取决于后台管理员要不要人工介入。我读预订相关的Servlet代码时发现它并没有做复杂的房间数量并发校验而是直接往预订表插记录。这在真实酒店场景里可能有超卖风险但作为教学项目反而是个可扩展的点——你可以在预订方法里先查一下该房型当天已预订数量再加个判断。具体改法围绕RoomreserveDAOImpl的insertReserve方法动刀我会在第六章展开说。4.2 前台退房与后台登记的交接逻辑这个系统最有意思的设计是“网上退房”和“退房管理”是两条路径。前台会员发起退房请求写入退房申请表后台管理员在TuifangDAOImpl里处理后更新房间状态。同时DengjiDAOImpl负责入住登记它和预订数据是联动关系——预订过的房客来店直接调预订信息办理入住不用重新填全部资料。这个交接过程用表格表示更清晰步骤操作角色调用的DAO数据变化1前台会员RoomreserveDAOImpl新增一条预订记录状态为已预订2后台管理员DengjiDAOImpl根据预订信息登记入住房间状态改为已入住3前台/后台TuifangDAOImpl计算金额、释放房间、房间状态改为空闲4系统记录RoomreserveHistoryDAOImpl归档该订单到历史表注意第3步和第4步往往是一次性完成的。退房时先调TuifangDAOImpl里的结算方法算出总费用再调历史DAO把这条订单从当前表挪到历史表里。这种拆表设计思路对学习数据库表结构设计很有参考价值——当前表只存有效数据历史数据单独归档避免表数据量越来越大拖慢查询。4.3 Excel导出实现预订单和退房记录如何落地成文件YuDingDanHistoryExcel.class和TuifangRecordsExcel.class是这套项目里比较亮眼的功能点很多毕设项目都没做数据导出。这两个类的作用是把预订历史和退房记录导出成Excel文件。老项目导出Excel通常有两种方案一种是操作POI的HSSFWorkbook类逐行写入数据另一种是拼HTML表格改后缀为.xls。这套系统的实现我不确定具体用了哪种但按那个年代的常见做法大概率是POI。核心逻辑一般长这样HSSFWorkbook workbook new HSSFWorkbook(); HSSFSheet sheet workbook.createSheet(退房记录); HSSFRow header sheet.createRow(0); header.createCell(0).setCellValue(会员姓名); header.createCell(1).setCellValue(房型); header.createCell(2).setCellValue(退房时间); // 遍历查询结果逐行写入数据 for (int i 0; i records.size(); i) { HSSFRow row sheet.createRow(i 1); row.createCell(0).setCellValue(records.get(i).getName()); row.createCell(1).setCellValue(records.get(i).getRoomType()); row.createCell(2).setCellValue(records.get(i).getCheckoutTime()); } // 设置响应头强制浏览器下载 response.setContentType(application/vnd.ms-excel); response.setHeader(Content-Disposition, attachment;filenametuifang.xls); workbook.write(response.getOutputStream());这里有两个细节值得注意第一导出的行数据来源是RoomreserveHistoryDAOImpl或TuifangDAOImpl里的查询结果集说明这两个Excel类和DAO层是配合工作的第二响应头Content-Disposition里的attachment参数决定了浏览器是直接打开文件还是弹下载框改这两个响应头参数就能控制导出文件名。如果你打开Excel类发现是乱码不用怀疑逻辑十有八九是字符编码问题把字符串先new String(str.getBytes(GBK), UTF-8)转一遍再写入单元格基本能解决。5. 避坑排查老项目部署中的五个高频故障点这套系统整体不难但卡住人的全是环境细节。这里写几个我自己部署时踩过、以及帮别人排过的问题每条都是熬过夜的代价。坑一Tomcat启动后访问http://localhost:8080/webproject/login.jsp显示404现象Tomcat正常启动访问主页就报404但Tomcat自带的管理页面能打开。原因工程没有正确发布到Tomcat的webapps目录下。MyEclipse里Add Deployment操作没做成功或者发布路径选成了wtpwebapps而不是Tomcat的webapps。解决在MyEclipse的Servers窗口右键Tomcat服务器选择Add Deployment把工程加进去再重启服务器。如果还不行直接把工程整个复制到Tomcat的webapps目录下手动部署一定有效。坑二数据库查询出来全是问号或乱码现象页面能打开但数据库里的中文数据全部显示为???。原因JDBC连接串里没有指定characterEncoding参数同时MySQL库表本身字符集也不是utf8。解决先确认SQL文件建表语句里的DEFAULT CHARSET是utf8再把DBUtil里的连接串改成jdbc:mysql://localhost:3306/webproject?useUnicodetruecharacterEncodingutf8。坑三启动时报ClassNotFoundException: com.mysql.jdbc.Driver现象Tomcat控制台爆这个异常项目无法加载数据库驱动。原因MySQL的JDBC驱动JAR包没有放到WEB-INF/lib目录下。解决确认webproject/WebRoot/WEB-INF/lib里有mysql-connector-java-x.x.x.jar。如果没有从本地Maven仓库或MySQL安装目录里复制一个进这个文件夹然后右键项目Refresh。坑四页面能打开但登录没反应控制台没有任何输出现象点登录按钮页面刷新了一下但就是不跳转后端也没报错。原因最常见的是表单提交的URL写的是绝对路径和实际部署的上下文路径对不上。老项目里经常写actionlogin.jsp或action/login部署上下文路径变成/webproject/login后请求就打不到了。解决把表单的action改成相对路径或动态拼接例如form action%request.getContextPath()%/login methodpost也可以用浏览器F12看Network标签页实际请求的URL对比一下就能定位。坑五Tomcat 6.0在Win10/11上启动闪退现象双击startup.bat后黑框一闪就关。原因Tomcat 6.0默认的catalina.bat在启动时检测不到JAVA_HOME或者JAVA_HOME指向了1.8以上版本。解决确认JAVA_HOME环境变量指向JDK 1.6目录修好后重新打开命令行执行%CATALINA_HOME%\bin\startup.bat不要用双击方式。也可以编辑bin/setclasspath.bat在开头手动指定set JAVA_HOMEC:\Java\jdk1.6.0_45。这些坑看起来多整体是一条线版本匹配、字符集、发布路径。把这三项一次做对其余都顺利。6. 进阶玩法把老项目跑通之后怎么改出可展示的亮点环境跑通、业务理顺只是第一步这套系统的价值在于你可以站在它基础上改出一个有区分度的成品。我讲三个改动方向你任选一个做进去答辩或演示的深度立刻就不一样了。第一个方向是给预订加并发校验。现在系统里预订房间是直接插表不做数量判断这在实际场景中会导致同一天同一房型被超卖。你可以修改RoomreserveDAOImpl的预订方法在插入前先执行一条统计SQL判断当前房型在目标入住日期内的预订间数是否小于该房型总数。String checkSql SELECT COUNT(*) FROM roomreserve WHERE roomtype_id? AND in_date? AND status1;这条语句执行后返回的数量如果已达上限就中断预订并给前台提示。这个改动很小但能非常清晰地展示你对业务边界和数据库查询的理解。第二个方向是接入任意一个前端UI框架。这套系统的前台页面是纯JSP加原生CSS观感比较老。你可以保留全部后端代码只把登录页和预订页的HTML部分抽出来引入Bootstrap改一套现代化样式。老式JSP页面里的Java代码片段在改造时用JSTL替换页面会整洁很多。这个改动风险最低、视觉冲击力最强适合做演示首屏。第三个方向是给DAO层写单元测试。这套代码没有任何测试你可以在工程里新建一个测试目录用JUnit 4给HuiyuanDAOImpl和RoomreserveDAOImpl写几个增删改查的测试用例。这听起来不像“功能亮点”但答辩时你直接说“我补了测试覆盖”和说“我会写代码”是两个说服力层级。我的个人习惯是拿到这种老项目后先完整跑通原版流程再动手改代码。很多同学一上来就大改最后改挂了都不知道是改错的还是原来就是坏的。从那以后我每次拿到这种教学项目都会强制走一遍完整部署流程确认原版能跑再复制一份开始动手——原始版本留着就是最好的后悔药。希望帮到你。本文还有配套的精品资源点击获取