多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

JavaWeb酒店预订系统毕设实战:从数据库设计到答辩加分

JavaWeb酒店预订系统毕设实战:从数据库设计到答辩加分 简介提供一套基于JavaWeb的酒店预订系统完整毕业设计资源面向计算机相关专业正在做毕设的学生及需要项目实战的Java开发者解决从零搭建酒店客房预订、订单管理等核心业务的需求。系统采用JSP、Servlet、JDBC与MySQL实现基于B/S结构区分用户与管理员两种角色涵盖注册登录、设施与价格展示、可用房间查询、订单新增与修改删除、订单明细管理、历史预订信息查询等完整功能界面简洁、操作便捷。资源包共3个文件包括项目说明txt、项目源码zip以及数据库脚本sql压缩包整体约3.52MB结构精简便于快速导入部署。已有1846人学习下载可作为毕设直接使用或作为JavaWeb综合项目练习帮助理解分层开发、数据库设计与核心业务流程实现。1. 基于JavaWeb的酒店预订系统为什么说它是毕设里性价比最高的一类选题如果你正在为毕设选题发愁又不想碰推荐算法、高并发秒杀这类容易被评委追问到哑火的方向那基于JavaWeb的酒店预订系统几乎是稳妥的代名词。它覆盖了JavaWeb开发的全套标准动作Servlet或SpringMVC处理请求、JSP渲染页面、JDBC或MyBatis操作MySQL、会话跟踪维持登录态、事务保证下单不超卖。这套技术栈不新但胜在成熟任何一个带过毕设的老师都能看懂你的代码结构答辩时不会因为「用了什么冷门框架」而质疑你。这个项目能解决的问题也很具体房型管理、房间状态维护、用户注册登录、在线预订、订单状态流转、后台数据统计。它的数据模型天生清晰表与表之间的关系是面试官最喜欢问的「一对多、多对一」的活教材。对新手而言拿到一套能跑的源码和数据库脚本比什么都重要。这篇文章我就按自己当年做同类项目的经验把从数据库设计到IDEA里跑通再到答辩加分项的每一步拆给你看。我不是在介绍某个神秘代码包而是告诉你这套东西背后真正值得投入的精力应该花在哪。2. 技术选型和项目结构为什么JavaWeb比SpringBoot更适合当毕设2.1 从技术栈看这个项目该选什么所谓JavaWeb广义上指基于Java Servlet规范构建的Web应用狭义到毕设语境里通常就指JSP Servlet JDBC MySQL这套组合。虽然现在企业里已经很少直接用JSP但毕设场景下这套方案有两个无法替代的优势。第一是代码可见性高请求从浏览器发出到JSP渲染回来每一步都写在明面上你可以在答辩时对着代码讲清楚「用户点了预订按钮之后到底发生了什么」这是SpringBoot自动装配给不了你的。第二是依赖简单不需要Maven拉一堆starter一个Tomcat加上JDBC驱动就能跑对网络条件不好的实验室环境非常友好。如果你拿到的是SSM版本Spring SpringMVC MyBatis也不排斥但我会建议你至少把SpringMVC的请求流转机制弄明白。评委问得最多的几个问题比如「SpringMVC和Servlet有什么区别」「MyBatis的#{}和${}有什么区别防止SQL注入」都属于这个项目的必考题。反过来如果你是新手且时间紧纯Servlet JSP版本其实更容易讲清楚因为每一行代码都在做可见的事情没有那么多「框架内部帮你搞定了」的黑匣子。2.2 标准目录结构与分层原则我见过大量翻车的毕设问题几乎都出在分层混乱。一个完整的JavaWeb酒店预订系统哪怕功能再少也建议按下表这样的结构组织代码层级包名或目录职责典型类名控制层com.xxx.servlet或com.xxx.controller接收请求、参数校验、跳转页面RoomServlet,OrderServlet业务层com.xxx.service核心业务逻辑如下单时检查库存RoomService,OrderService数据层com.xxx.daoJDBC操作SQL语句写在这里RoomDao,OrderDao实体类com.xxx.entity对应数据库表结构Room,User,Order工具类com.xxx.utilDB连接、字符串处理、日期转换DBUtil,MD5Util控制层只做三件事取参数、调服务、决定跳转哪个JSP。业务层是核心下订单时「先查房态再插入订单再更新房态」的顺序必须写在Service里如果写在Dao里后面扩展事务就麻烦了。DAO层里只允许出现JDBC代码不能出现request.getParameter()这种Web内容。这样分层的好处是老师问「订单模块怎么改」你能立刻定位到对应文件而不是在几百行的Servlet里翻。2.3 环境版本搭配JDK、Tomcat和MySQL的隐性约束跑毕设最常见的人生感悟是「本地明明能跑换台机器就废了」。九成原因是版本不匹配。JavaWeb这套组合里版本约束是实打实的硬规则。JDK 8搭配Tomcat 8.5或9.0是最稳的组合Tomcat 10以后把javax.servlet换成了jakarta.servlet如果你用的是Tomcat 10老项目里所有import javax.servlet.*全部编译报错这是最大的一个版本坑。MySQL这边8.0以上默认使用com.mysql.cj.jdbc.Driver而MySQL 5.7时代用的是com.mysql.jdbc.Driver数据库脚本的写法差别不大但连接串里的serverTimezoneAsia/Shanghai参数在8.0必须加不然日期查询会差8个小时。如果你是刚刚开始配置环境我建议直接用JDK 8 Tomcat 9.0 MySQL 8.0这组搭配在2025年的各大教程和开源项目里验证量最大遇到问题最容易搜到答案。版本统一了你从IDEA里导出数据库脚本放到别人机器上跑的时候才能少一半的玄学问题。3. 数据库脚本的核心从表设计到一键导入MySQL3.1 五张核心表的字段设计与关系酒店预订系统的数据库脚本说透了就是围绕「谁在什么时间订了哪个房间」这句话展开。最少需要五张表用户表、酒店表、房型表、房间表、订单表。房型表和房间表要分开——这是新手最爱犯的错误以为房型就是房间。房型是「大床房」「双床房」这类分类属性房间是具体的「301房间」这种物理实体。一个房型对应多个房间一个房间对应多个订单这是典型的一对多关系。用户表字段至少要有id, username, password, phone, create_time其中password我强烈建议存MD5值而不是明文。数据库脚本里可以直接写入一条加密后的管理员账户加密算法在Java代码里用MD5Util统一处理。订单表是核心表字段建议包括id, order_no, user_id, room_id, check_in_date, check_out_date, total_price, status, create_time。这里order_no要单独设置因为它是前端展示的订单号不能复用数据库自增主键。check_out_date计算房价时用得到total_price是冗余字段你可以通过SQL计算但在订单表里冗余存一份查询效率高且JSP展示时少一次计算这个冗余是合理的。房间表要有room_number, room_type_id, status其中status用整型或字符串标识0代表空闲1代表已入住2代表打扫中。做毕设时这个状态字段就够用了不需要做成单独的状态表。下面是房型表和房间表的建表脚本可以直接抄CREATE DATABASE IF NOT EXISTS hotel_db DEFAULT CHARACTER SET utf8mb4; USE hotel_db; CREATE TABLE room_type ( id INT PRIMARY KEY AUTO_INCREMENT, type_name VARCHAR(50) NOT NULL COMMENT 房型名称, price DECIMAL(10, 2) NOT NULL COMMENT 每晚价格, bed_info VARCHAR(100) COMMENT 床型信息, area INT COMMENT 房间面积平方米, max_people INT DEFAULT 2 COMMENT 最多入住人数 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE room ( id INT PRIMARY KEY AUTO_INCREMENT, room_number VARCHAR(10) NOT NULL UNIQUE COMMENT 房间编号, room_type_id INT NOT NULL, status TINYINT DEFAULT 0 COMMENT 0空闲 1已入住 2打扫中, floor INT COMMENT 所在楼层, FOREIGN KEY (room_type_id) REFERENCES room_type(id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; INSERT INTO room_type (type_name, price, bed_info, area, max_people) VALUES (标准单人间, 188.00, 1.2m单人床, 18, 1), (豪华大床房, 388.00, 1.8m大床, 28, 2), (行政双床房, 588.00, 1.35m双床, 36, 2), (家庭套房, 888.00, 1.8m1.2m, 55, 3); INSERT INTO room (room_number, room_type_id, status, floor) VALUES (501, 1, 0, 5), (502, 1, 0, 5), (503, 2, 0, 5), (601, 2, 0, 6), (602, 2, 1, 6), (603, 3, 0, 6), (701, 4, 0, 7), (702, 4, 0, 7);这段脚本做了三件事建库、建表、插入测试数据。utf8mb4比utf8强在能存Emoji和生僻字现在手机端用户昵称经常带Emoji用utf8会报Incorrect string value错误。ENGINEInnoDB是硬性要求只有InnoDB支持事务和外键MyISAM虽快但不支持毕设选InnoDB永远不会被问倒。房间表里故意把602的状态置为1就是为了让你跑通项目后能看到「已入住」的界面效果不用手动改数据库。外键约束FOREIGN KEY建议保留虽然有人为了性能会去掉但毕设场景里外键体现的是你懂数据库完整性约束这点加分比那点性能损耗更重要。3.2 从IDEA里导出数据库脚本的正确姿势标题里写着「数据库脚本」说明源码包里应该有一个.sql文件。但很多时候你拿到的脚本可能是别人从Navicat导出的编码可能是UTF-8或GBK结构也可能没建库语句——这里涉及一个冷知识用客户端导出的MySQL脚本默认不含CREATE DATABASE语句只包含CREATE TABLE。这意味着你新建库然后导入是正常的但如果直接执行整个脚本如果没有CREATE DATABASE hotel_db这一行就会报「No database selected」。如果你需要自己从IDEA导出一份可分发的数据库脚本正确路径是IDEA右侧Database面板 → 右键数据库连接 →Database Tools→Dump Data to File(s)→ 选择Database and Tables结构。导出时注意两个选项一是Include CREATE DATABASE statement要勾上这样别人拿到脚本后一条命令就能建库二是字符集选择utf8mb4。如果你用的是Navicat右键数据库 →转储SQL文件→ 选择「结构和数据」效果类似但同样要检查导出的文件开头有没有CREATE DATABASE没有就手动加一行再提交。导入到新环境的命令行做法是mysql -u root -p hotel_db.sql这条命令让MySQL客户端读取hotel_db.sql文件并逐行执行-p参数会在执行前提示输入密码。如果SQL文件里已经写了CREATE DATABASE你不需要提前建库如果没写需要先执行CREATE DATABASE hotel_db再导入。遇到Unknown database报错时先打开SQL文件看开头几行这是最快的排查路径。3.3 JDBC连接MySQL的参数配置与账号密码坑数据库脚本导入再快Java代码连不上数据库也是白搭。JDBC连接串是JavaWeb项目里最容易踩坑的地方尤其是在连接MySQL 8.0的时候。下面这个DBUtil工具类是JDBC连接的标准写法package com.hotel.util; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; 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 PASSWORD 123456; static { try { Class.forName(com.mysql.cj.jdbc.Driver); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USER, PASSWORD); } public static void close(Connection conn, java.sql.Statement stmt, java.sql.ResultSet rs) { // 关闭顺序rst - stmt - conn从下往上 try { if (rs ! null) rs.close(); if (stmt ! null) stmt.close(); if (conn ! null) conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }这段代码里几个参数说清楚。useSSLfalse是因为本地开发不需要加密连接加上true会导致MySQL 8.0在有证书校验时频繁告警。serverTimezoneAsia/Shanghai处理时区问题没有它java.util.Date写入DATETIME字段会差8小时。characterEncodingutf8保证中文不乱码注意这里写utf8而不是utf8mb4JDBC驱动认utf8它自动兼容utf8mb4的数据库。Class.forName(com.mysql.cj.jdbc.Driver)是MySQL 8.0的驱动类名如果是5.7则用com.mysql.jdbc.Driver两个类名长得像混用会直接报ClassNotFoundException这是最常见的新手翻车点。连接池在这个篮子里属于加分项。如果你用的是Tomcat可以在META-INF/context.xml里配置DataSource资源用JNDI获取连接。这会让答辩时多一个「你了解连接池的作用」的发挥点但前提是你自己得讲清楚连接池为什么比每次都新建连接快。讲不清的话老老实实用上面的DBUtil也完全够。4. 把项目跑通IDEA配置Tomcat与源码排查指南4.1 IDEA导入项目到成功启动的五个操作拿到源码之后第一步不是双击打开而是先看目录结构。标准JavaWeb项目应该是这样的形态src/放Java源码web/或WebContent/下放JSP和WEB-INF/web.xml。在IDEA里导入的完整路径是File→New→Project from Existing Sources→ 选项目根目录 → 一路Next到「Select categories」时选Web。如果IDEA没有自动识别出Web模块需要手动在Project Structure里添加。配置Tomcat是另一个关键环节。Run→Edit Configurations→ 左上角→Tomcat Server→Local→ 在Application server处选到你的Tomcat安装目录。然后切到Deployment标签页点选Artifact把项目以war exploded形式部署选这个模式可以热更新JSP改完直接刷新浏览器就能看到效果。Application context填/hotel这样启动后访问地址就是http://localhost:8080/hotel/。如果Artifact列表是空的说明项目没被识别为Web项目回到Project Structure→Artifacts→→Web Application: Exploded再把WEB-INF和lib目录配进去。最后一步是启动前把MySQL服务打开并确认DBUtil里的账号密码和本地一致。遇到Access denied for user报错九成是密码不一致打开MySQL Command Line Client验证一下root能不能登录。启动Tomcat后控制台出现Server startup in [xxx] milliseconds才算启动成功没看到这行就去查日志不要看浏览器。4.2 web.xml与Servlet映射请求路径404排查JavaWeb项目里web.xml就是路由表。Servlet 3.0之后虽然可以用WebServlet注解代替XML配置但毕设项目里两者都存在你需要两个都看得懂。传统写法是在web.xml里这样映射servlet servlet-nameRoomServlet/servlet-name servlet-classcom.hotel.servlet.RoomServlet/servlet-class /servlet servlet-mapping servlet-nameRoomServlet/servlet-name url-pattern/room/list/url-pattern /servlet-mappingservlet-name只是自定义别名servlet-class必须是完整类名带包路径写错一个字就是ClassNotFoundException。url-pattern是浏览器访问的路径用户访问http://localhost:8080/hotel/room/list时Tomcat根据这个映射把请求交给RoomServlet处理。如果你打开页面报404第一个要去排查的就是url-pattern和前端页面表单里action值是否完全一致大小写差一个字母都不行。如果用的是注解方式检查WebServlet(/room/list)注解里的路径是否和前端提交地址一致方式不同但坑一样深。JSP里的链接路径也是个重灾区。在webapp根目录下的JSP里写a hrefroom/list浏览器解析时是相对于当前URL路径的。如果你当前在http://localhost:8080/hotel/index.jsp这个链接会指向http://localhost:8080/hotel/room/list没问题。但如果当前在http://localhost:8080/hotel/user/order.jsp同样的链接会变成http://localhost:8080/hotel/user/room/list直接404。解决方案是JSP里用${pageContext.request.contextPath}拼绝对路径写成a href${pageContext.request.contextPath}/room/list。这个方法麻烦一次但能救你后面的所有页面跳转值得当成习惯。4.3 JSPServlet实现登录与权限拦截的最小代码登录逻辑是每个模块的前提直接决定用户能不能安全地访问订单页面。下面这段是Servlet里登录校验的标准写法核心是「查用户 → 存Session → 跳转」三步WebServlet(/user/login) public class LoginServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding(UTF-8); String username request.getParameter(username); String password MD5Util.md5(request.getParameter(password)); UserDao userDao new UserDao(); User user userDao.findByUsernameAndPassword(username, password); if (user ! null) { request.getSession().setAttribute(loginUser, user); response.sendRedirect(request.getContextPath() /room/list); } else { request.setAttribute(errorMsg, 用户名或密码错误); request.getRequestDispatcher(/login.jsp).forward(request, response); } } }request.setCharacterEncoding(UTF-8)必须写在取参数之前否则中文用户名会乱码。MD5Util.md5()在比对前加密保证数据库里存的也是密文这样即使数据库脚本泄露密码原文也不会暴露。登录成功后setAttribute存入Session后面JSP页面通过${sessionScope.loginUser.username}就能显示当前登录者。失败时用forward而不是sendRedirect这样errorMsg能带到login.jsp上显示而URL栏不会变化用户体验更好。权限拦截用Servlet的Filter实现这是JavaWeb里最标准的解决方案。写一个LoginFilter在doFilter里判断Session是否为空。注意过滤器的拦截路径要写在web.xml或注解里只拦截/order/*、/user/*这类需要登录的路径/login.jsp和静态资源要放行否则会出现「登录页也进不去」的尴尬。Filter的顺序也有讲究编码过滤器要在登录过滤器之前因为过滤器执行顺序按filter-mapping顺序编码乱掉之前先被拦截住的话登录就永远不可能成功——这个顺序坑是我见过最隐蔽的Bug之一。5. 避坑指南JavaWeb酒店预订系统最常见的七个翻车现场5.1 页面中文乱码三处编码不一致问题都不同现象是JSP页面显示正常的标题从数据库查出来的房型名称却是一串问号。原因不是某一处没设编码而是「JSP文件编码 → 数据库连接编码 → 数据库表字段编码」整条链路断了任一一环都会乱。解决方式是三个位置统一为UTF-8JSP文件头部写% page languagejava contentTypetext/html; charsetUTF-8 pageEncodingUTF-8%DBUtil连接串里带characterEncodingutf8建表语句里用utf8mb4。另一个乱码源头是POST请求需要在Servlet的doPost方法第一行写request.setCharacterEncoding(UTF-8)。如果是GET请求乱码改Tomcat的conf/server.xml里Connector标签加URIEncodingUTF-8属性。经验之谈是先确认浏览器页面本身是否是UTF-8再排查数据库最后才动Tomcat配置按数据流顺序排查比瞎改快得多。5.2 下单时房间超卖事务没加导致同一间房被订两次现象是两个用户同时预订同一间空闲房间两个订单都创建成功。原因是在OrderService里「查询房间状态 → 插入订单 → 修改房间状态」这三步没有放在同一个数据库事务里。高并发下两个请求都先查到了房间状态为0然后各自插入订单最后都把状态改成了已入住结果就是同一间房卖给了两个人。解决方式是这个场景必须加事务用DBUtil拿到连接后手动控制setAutoCommit(false)、commit()和rollback()Connection conn DBUtil.getConnection(); try { conn.setAutoCommit(false); // 1. 查询房间状态加 FOR UPDATE 锁行 // 2. INSERT 订单 // 3. UPDATE 房间状态 conn.commit(); } catch (SQLException e) { conn.rollback(); throw e; } finally { conn.setAutoCommit(true); DBUtil.close(conn, stmt, rs); }setAutoCommit(false)是关键它告诉MySQL这三条SQL语句要么全部成功要么全部不做。如果进一步要解决并发下的正确性查询房间状态的SQL要写成SELECT * FROM room WHERE id? AND status0 FOR UPDATEFOR UPDATE会把这一行锁住另一个事务必须等这个事务提交后才能查这条记录从根上避免超卖。如果你在答辩时能主动说出这段逻辑评委的追问基本就到顶了。5.3 JSP页面找不到${}表达式的结果现象是页面上直接显示了${loginUser.username}这段原文而不是用户名。原因是JSP没有开启EL表达式支持或者web.xml用的是Servlet 4.0规范但JSP版本过低。解决方式是确认web.xml头部声明用的是Servlet 3.0以上版本或者手动在JSP页面加% page isELIgnoredfalse %。另一个相关坑是JSTL标签库的% taglib prefixc urihttp://java.sun.com/jsp/jstl/core%报红这是因为WEB-INF/lib下没有jstl.jar和standard.jar去下载对应版本放进lib目录即可。5.4 Tomcat部署后一直停留在启动中现象是IDEA里Run Tomcat后控制台停在Deploying [hotel]或者日志显示UnsupportedClassVersionError。原因是编译类和运行的JDK版本不一致。在IDEA里检查File→Project Structure→Project的SDK版本和Modules里的Language level再把Tomcat→Edit Configuration→Startup settings看一下所用JRE。这三处版本不一致就会出现「代码在A机器能跑在B机器报错」的经典问题。还有一个小概率原因是WEB-INF/classes目录下有旧编译产物先Build→Rebuild Project清理再重新部署。5.5 数据库脚本导入时报错Unknown column或Duplicate entry现象是导入SQL脚本时有些表能建有些表报错。原因通常是脚本里有重复执行过的痕迹或者版本差异导致字段名冲突。解决方式是导入前先检查库里是否已经存在同名表存在就先DROP TABLE清理干净。另一个常见情况是脚本里AUTO_INCREMENT从0开始但已有数据中主键占用了某些值所以Duplicate entry 1 for key PRIMARY时要先TRUNCATE TABLE清理自增计数然后再重新导入。这套操作正确顺序是DROP旧表 → 导入新脚本 → 验证数据行数。5.6 IDAE导出的数据库脚本本机执行正常换MySQL版本后日期乱了现象是同一份SQL文件在MySQL 8.0导出的在5.7上插入的DATE类型字段都少一天。原因是MySQL 8.0默认DATETIME存储时区敏感而5.7默认不带时区加上脚本里TIMESTAMP类型在不同版本间对时区处理规则不同。解决方式是建表时日期字段统一用DATETIME而不是TIMESTAMP并且连接串固定加serverTimezoneAsia/Shanghai。如果你要在不同MySQL版本间分发脚本这是必备细节。5.7 页面提交订单后用浏览器返回键订单被重复提交现象是用户提交订单成功后点浏览器后退再点提交按钮生成了两条相同订单。原因是订单表里没有幂等约束。解决方式是在订单表增加order_no字段并设置唯一索引UNIQUE KEY uk_order_no (order_no)Java代码里生成order_no时带上时间戳加随机数即System.currentTimeMillis()拼接UUID前几位。数据库层面的唯一索引是最后一道防线比你在Servlet里用Session做「已提交标记」可靠得多后端永远不要信任前端和浏览器行为。6. 从能跑到加分订单状态机与持久层升级的实战建议项目跑通了只是起点答辩时能不能拿高分取决于你还能主动展示哪些「超纲但合理」的思考。我建议你从两个方向准备。第一个是订单状态流转。目前大多数毕设里的订单表只有一个status字段0待支付、1已确认、2已入住、3已离店、4已取消没问题但你真正要准备的是状态跳转的逻辑在哪一层实现。常见做法是在OrderService里写updateStatus(int orderId, int fromStatus, int toStatus)更新SQL里带上WHERE status fromStatus这样即使用户手动拼接URL调用状态更新接口也只有满足当前状态的订单才能跳转成功。这一点体现的是你对状态机校验的认知很多工作两三年的开发都未必说得清答辩时效果极好。第二个是把纯JDBC换成MyBatis的代价与收益。如果你时间充裕可以把DAO层用MyBatis重构sqlSessionFactory配置里的mapperLocations指向XML文件夹实体类和DAO接口不用变。但你必须能在答辩时说清楚换来的是什么——XML里写SQL可以去掉大量PreparedStatement的样板代码更重要的是#{}预编译防SQL注入比字符串拼接可靠得多。如果评委追问MyBatis和JDBC的关系你要答「MyBatis底层还是JDBC只是帮你管理了连接、预编译、结果集映射」。我做这类项目时还有一个验证习惯用三个SQL验证系统的核心链路是否健壮。第一个验证订房不超卖开两个终端同时对一个房间执行预订接口看最终订单数和房间状态是否一致。第二个验证价格计算手动改数据库里的房价看前台页面展示是否实时更新——如果没更新说明JSP页面缓存了数据这是需要修正的地方。第三个验证用户退出后无法访问订单列表用浏览器无痕窗口访问/order/list看是否被过滤器拦截并跳转登录页。这三个验证做完你的系统在评委眼里就是一个有完整逻辑闭环的作品而不是「能跑但一碰就碎」的演示品。最后说一句我的私人教训毕设答辩之前一定把数据库脚本配合源码重新走一遍从零到启动的全流程用一台干净环境的电脑。你永远不知道评委会不会当场说「我想换个数据库试试」。我当时就是因为在别的机器上没连上MySQL被迫现场调了两分钟虽然最后跑通了但那两分钟的紧张感现在还记得。把从CREATE DATABASE到Tomcat亮绿灯的操作练到肌肉记忆你才有底气讲真正的设计思路。希望这些经验对你有用。本文还有配套的精品资源点击获取
返回列表