简介:一套面向Java毕业设计的Spring Boot酒店管理系统资源包,完整覆盖源码、论文与PPT答辩材料,适合计算机专业学生完成选题、设计、实现和文档写作。系统以Java和Spring Boot为核心,结合MySQL数据库,划分管理员与用户两类角色,支持客房预订、入住登记、服务费用及退房登记等全流程管理,具备典型的毕业设计项目结构。包体共814个文件,压缩后24.3MB,主要包括Java后端源码、Vue前端组件、JS/CSS/HTML页面、SQL数据库脚本,以及docx论文和PPT演示文稿;同时附有安装、运行、构建等批处理脚本,便于本地部署。资源内还包含许多.bak备份文件,方便对照修改前后代码,降低调试门槛。目前已有253人学习下载,对正在准备答辩或需要可运行毕业设计源码的学生有较强的参考价值。按论文目录展开,涵盖课题背景、可行性分析、数据库设计、功能模块实现与系统测试等完整章节,配合源码可快速理解酒店管理系统的实现思路。
1. Spring Boot酒店管理系统:一个毕设怎么从源码做到答辩
Spring Boot酒店管理系统是计算机类毕业设计里出现频率最高的选题之一,它把 Spring Boot 后端框架、MySQL 数据库、前端页面和完整业务闭环串在一起,做完之后能演示、能答辩、也能在面试时当项目经验讲。这套系统的核心业务是:前台人员管理房型和房间状态,客户预订和入住,退房时自动结算房费,管理员查看订单与营收数据。系统适合两类人——一是需要在一学期内完成毕业设计的学生,二是想通过完整项目熟悉 Spring Boot 全流程开发的从业者。但标题里的"设计与实现"远不是只写代码那么简单,论文结构和答辩 PPT 才是很多人卡住的地方,这篇文章就是把这条路讲透。
2. 技术选型与架构设计:Spring Boot版本、数据库表与分层落地
2.1 Spring Boot版本与项目骨架:2.7还是3.x,JDK怎么搭
选版本是第一个要做的决定。现在网上搜"springboot框架"能搜到大量 3.x 的教程,但 3.x 要求 JDK 17,且部分第三方依赖还没完全跟上,对毕设来说反而增加不确定性。我一般建议直接用Spring Boot 2.7.18 + JDK 8/11 + Maven 3.8,这套组合经过大量生产验证,遇到问题随便一搜就有答案,兼容性最稳。
创建项目时不需要用 Spring Initializr 在线生成,直接手写 pom.xml 反而更清楚。最简依赖如下:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.18</version> <relativePath/> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.7</version> </dependency> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-api</artifactId> <version>0.11.5</version> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-impl</artifactId> <version>0.11.5</version> <scope>runtime</scope> </dependency> </dependencies>这段 pom 的核心逻辑是:spring-boot-starter-web 提供 MVC 和内嵌 Tomcat,MyBatis Plus 帮我们省掉大量 Mapper XML 编写,jjwt 负责生成和校验登录令牌。参数上注意 MyBatis Plus 版本要选 3.5.x,太老版本对 Spring Boot 2.7 的自动配置支持不好;mysql-connector-j 是 MySQL 8 的驱动坐标,如果是 MySQL 5.7 就换成mysql-connector-java5.1.49。
项目结构上按 com.hotel 作为基础包,下面分 controller、service、mapper、entity、config、common 六个子包,这是 springboot 项目结构里最常见也最容易被答辩老师认可的分层。controller 只做参数接收和结果封装,service 写业务逻辑,mapper 直接对应数据库操作,entity 就是数据库表的映射实体。坚持这个规则,后面写功能时不会乱。
2.2 数据库设计:七张表覆盖酒店完整业务闭环
数据库是酒店管理系统的地基,表设计得好不好直接决定代码复杂度。我做过三个酒店类的项目,最终沉淀出下面这七张表,不多不少刚好覆盖"用户—房型—房间—客户—预订—入住—订单"这个完整业务闭环。
| 表名 | 业务含义 | 核心字段 | 关联关系 |
|---|---|---|---|
| sys_user | 系统用户(管理员/前台) | username, password, role | 无 |
| room_type | 房型定义 | type_name, price, bed_type | 被 room 引用 |
| room | 物理房间 | room_no, floor, status | 外键 room_type_id |
| customer | 客户档案 | name, phone, id_card | 被预订和入住引用 |
| reservation | 预订单 | room_id, customer_id, check_in_date, check_out_date | 外键 room_id, customer_id |
| check_in | 入住登记 | reservation_id, room_id, customer_id, status | 外键 reservation_id |
| orders | 结算订单 | check_in_id, total_amount, status | 外键 check_in_id |
建表时最容易忽略的是状态字段的取值约定,我习惯在表设计文档里直接写清楚:room.status 只有"空闲、已预订、已入住、维修"四种;reservation.status 只有"已预订、已取消、已入住";check_in.status 只有"已入住、已退房"。字段用DECIMAL(10,2)存金额,不用 float,避免精度丢失。所有表都加create_time和deleted字段,前者做审计,后者配合 MyBatis Plus 的逻辑删除功能,这样删除房间记录时就不会真的删掉数据,答辩被问到"数据安全"时有话讲。
SQL 脚本里还有一个坑:表名不要直接用order,order 是 MySQL 的保留字,直接建表会报语法错误。我统一用复数orders或者加前缀t_order,这一步能给你省出半天排查时间。
2.3 application.yml配置:数据源、MyBatis Plus与JWT参数
配置文件的健壮程度决定了项目能不能在一台新电脑上快速跑起来。我习惯把配置拆成 application.yml 和 application-dev.yml 两份,前者放公共配置,后者放本地开发环境的数据源信息。最小可运行配置如下:
server: port: 8080 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/hotel_manager?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai username: root password: your_password jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT+8 mybatis-plus: mapper-locations: classpath*:mapper/**/*.xml configuration: map-underscore-to-camel-case: true log-impl: org.apache.ibatis.logging.stdout.StdOutImpl global-config: db-config: logic-delete-field: deleted logic-delete-value: 1 logic-not-delete-value: 0 jwt: secret: hotel-manager-jwt-secret-key-please-change expire-hours: 24这里几个参数最需要调:serverTimezone=Asia/Shanghai不设置的话,MySQL 8 驱动会报时区错误;map-underscore-to-camel-case开启后数据库的room_no字段才能自动映射到实体的roomNo属性;logic-delete-field告诉 MyBatis Plus 哪个字段是逻辑删除标记,之后所有 delete 方法都会自动变成 update。jackson 的日期格式必须配,否则前端传2025-06-01这种日期字符串到后端 LocalDate 字段时容易翻车。
JWT 的密钥在生产环境要用环境变量注入,不要写死在配置文件里。毕设项目为了演示方便写死问题不大,但论文里最好提一句"密钥可配置化",这属于答辩时的加分细节。
3. 核心模块实现:从JWT登录到退房结算的Spring Boot代码
3.1 JWT登录认证与拦截器配置
酒店管理系统的用户角色分为管理员和前台,客户可以注册成普通用户在线订房。无论哪种角色,登录后都需要一个凭证来标识身份,这里选 JWT 而不是传统 Session。原因是 JWT 无状态,前后端分离后前端拿到 token 存起来,后续每个请求带上就行,后端不用维护会话,这在论文"技术选型"部分也好写理由。
登录接口的 Service 层代码:
@Service public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Autowired private JwtUtil jwtUtil; @Override public LoginResult login(String username, String password) { // 1. 根据用户名查询用户,校验密码(密码经MD5加密存储) User user = userMapper.selectByUsername(username); if (user == null || !user.getPassword().equals(MD5Util.md5(password))) { throw new BusinessException("用户名或密码错误"); } if (user.getDeleted() == 1) { throw new BusinessException("账号已被禁用"); } // 2. 生成JWT令牌,把用户ID、用户名和角色写进token String token = jwtUtil.generateToken(user.getId(), user.getUsername(), user.getRole()); return new LoginResult(token, user.getRealName(), user.getRole()); } }这段代码的核心逻辑是三步:第一步查用户并做密码比对,注意数据库里存的是 MD5 后的密文,明文密码绝对不允许落库;第二步判断逻辑删除标记;第三步用配置好的密钥生成 token 返回前端。参数说明:selectByUsername是 MyBatis Plus 里用 LambdaQueryWrapper 拼出来的查询,任何用户名都能查,攻击者可以通过不同回显判断用户是否存在,所以密码错误提示要统一成"用户名或密码错误",不要分别提示。
有了登录接口还不够,得用拦截器把所有需要认证的接口保护起来。写一个 HandlerInterceptor 的实现类:
@Component public class JwtInterceptor implements HandlerInterceptor { @Autowired private JwtUtil jwtUtil; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 放行登录和注册接口,其他接口必须携带有效token String uri = request.getRequestURI(); if (uri.contains("/api/auth/login") || uri.contains("/api/auth/register")) { return true; } String token = request.getHeader("Authorization"); if (token != null && token.startsWith("Bearer ") && jwtUtil.validateToken(token.substring(7))) { return true; } response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); response.setContentType("application/json;charset=UTF-8"); response.getWriter().write("{\"code\":401,\"msg\":\"未登录或token已过期\"}"); return false; } }注意token.startsWith("Bearer ")这段是否有必要取决于你前端的习惯。美观起见前端一般会在 header 里加Bearer前缀,方便后端统一提取。截取substring(7)之后交给validateToken校验签名和过期时间,校验通过才放行。这里有一个容易踩的坑:拦截器放行的 URL 规则要在 WebMvcConfigurer 里注册时写清楚,否则静态资源也被拦截,前端页面全打不开。
3.2 房间预订流程:事务控制与日期冲突检查
房间预订是酒店系统的核心业务,也是答辩时最容易被追问的模块。需求是:前台或客户选中某房间,填写入住和离店日期,系统检查房间在目标日期段内没有被占用,然后生成预订单。这里的关键点是"日期冲突检查"和"事务一致性"。
@Service public class ReservationServiceImpl implements ReservationService { @Autowired private RoomMapper roomMapper; @Autowired private ReservationMapper reservationMapper; @Transactional(rollbackFor = Exception.class) @Override public Reservation createReservation(ReservationRequest request) { // 1. 校验房间存在且当前状态为"空闲"或"已预订" Room room = roomMapper.selectById(request.getRoomId()); if (room == null || "维修".equals(room.getStatus())) { throw new BusinessException("房间不存在或不可预订"); } // 2. 日期冲突检查:目标时段内存在"已预订"或"已入住"记录则拒绝 Integer conflictCount = reservationMapper.checkDateConflict( request.getRoomId(), request.getCheckInDate(), request.getCheckOutDate() ); if (conflictCount != null && conflictCount > 0) { throw new BusinessException("该房间在所选日期内已被预订"); } // 3. 创建预订记录,状态置为"已预订" Reservation reservation = new Reservation(); reservation.setRoomId(request.getRoomId()); reservation.setCustomerId(request.getCustomerId()); reservation.setCheckInDate(request.getCheckInDate()); reservation.setCheckOutDate(request.getCheckOutDate()); reservation.setStatus("已预订"); // 4. 乐观锁更新房间状态,防止并发重复预订 int updated = roomMapper.compareAndSetStatus(request.getRoomId(), "空闲", "已预订"); if (updated == 0) { throw new BusinessException("房间状态已变化,请刷新后重试"); } reservationMapper.insert(reservation); return reservation; } }上面代码里第 2 步的日期冲突检查是核心。checkDateConflict 对应的 SQL 大致是:统计预订表和入住表中目标房间在[checkInDate, checkOutDate)区间内是否存在未取消的记录。这里有个细节务必注意:退房时间应小于入住时间,区间用左闭右开,即check_in_date < 新退房时间 AND 新入住时间 < check_out_date,这样才能正确覆盖连住多天的场景。我见过有人把等号也加进去,导致当天退房当天入住被误判冲突,纯属白踩坑。
第 4 步的compareAndSetStatus是 MyBatis Plus 里的自定义 SQL,核心是UPDATE room SET status = '已预订' WHERE id = ? AND status = '空闲',通过更新的影响行数判断有没有并发竞争。如果没有这一层保护,两个客户同时预订同一房间会各自都成功,这是高并发场景最经典的超卖问题,面试时能把这个讲清楚,项目含金量立即上升。
3.3 退房结算:价格计算与订单生成的完整链路
退房结算要把"入住天数、房费单价、订单生成、房间状态重置"串成一个事务。入住时记录了入住的起始日期,退房时用当前日期减去入住日期得到实际天数,再乘房型单价就是应收金额。这个模块的代码需要同时操作 check_in、orders、room 三张表,验证事务是否生效的好时机。
@Transactional(rollbackFor = Exception.class) @Override public CheckOutResult checkOut(Long checkInId) { // 1. 查入住记录,状态必须为"已入住" CheckIn checkIn = checkInMapper.selectById(checkInId); if (checkIn == null || !"已入住".equals(checkIn.getStatus())) { throw new BusinessException("入住记录不存在或已退房"); } // 2. 计算实际入住天数,最少按1天计费 LocalDateTime checkInTime = checkIn.getActualCheckInTime(); LocalDateTime now = LocalDateTime.now(); long hours = Duration.between(checkInTime, now).toHours(); int days = (int) Math.ceil(hours / 24.0); if (days <= 0) { days = 1; } // 3. 按房型单价计算总金额 Room room = roomMapper.selectById(checkIn.getRoomId()); RoomType roomType = roomTypeMapper.selectById(room.getRoomTypeId()); BigDecimal totalAmount = roomType.getPrice().multiply(BigDecimal.valueOf(days)); // 4. 生成结算订单 Orders order = new Orders(); order.setCheckInId(checkInId); order.setCustomerId(checkIn.getCustomerId()); order.setDays(days); order.setTotalAmount(totalAmount); order.setStatus("已结算"); orderMapper.insert(order); // 5. 更新入住记录为"已退房",房间状态重置为"空闲" checkIn.setStatus("已退房"); checkIn.setActualCheckOutTime(now); checkInMapper.updateById(checkIn); roomMapper.updateStatus(checkIn.getRoomId(), "空闲"); return new CheckOutResult(order.getId(), totalAmount, days); }计费逻辑这里有不同酒店的规则差异:有些按 12 点前退房不收当天费用,有些按整天算,有些按小时算加收。代码里用的是向上取整按天算,一个星期前入住、今天 14 点退房会算 8 天,这种规则要写进论文的需求分析里说明清楚,否则答辩时被问到"你房间超时退房怎么计费"不好回答。事务的注意点在于@Transactional必须加在 public 方法上,且不能是同一个类里私有方法调用,否则不生效。第 5 部更新房间状态属于跨表操作,任何一步抛异常都会回滚到初始状态,不会出现订单没生成但房间变空闲的脏数据。
4. 论文与答辩PPT:把代码和截图组织成能过审的交付物
4.1 论文八章结构:从需求分析到系统测试的写作顺序
源码写完只是完成了一半,"源码+论文+ppt答辩"里论文占的权重往往比代码更高。指导老师不管你的代码风格多好,只看论文里能不能把问题说清楚。我见过太多代码写得不错但论文只有需求分析和数据库设计两章的学生,最后被要求大改。一篇合格的工学毕设论文至少要有八章:
| 章节 | 核心内容 | 常见错误 |
|---|---|---|
| 第1章 绪论 | 研究背景、国内外现状、研究意义 | 变成百度百科式科普 |
| 第2章 相关技术 | Spring Boot、MyBatis Plus、MySQL、JWT | 直接贴官网简介 |
| 第3章 需求分析 | 角色划分、功能用例图、非功能需求 | 遗漏非功能需求 |
| 第4章 总体设计 | 系统架构图、功能模块图、数据库ER图 | 只画功能模块图 |
| 第5章 详细设计 | 核心表结构、关键接口时序图 | 直接贴代码 |
| 第6章 系统实现 | 按模块展示运行截图+核心代码 | 代码占满整页 |
| 第7章 系统测试 | 测试用例表、测试结果、BUG修复记录 | 只写"测试通过" |
| 第8章 总结展望 | 项目总结、不足、后续改进 | 写得太短 |
写作顺序建议按"第1章→第3章→第4章→第5章→第7章",最后再回头写第2章和相关技术,因为写完后你对项目理解更深,技术选型理由也更清晰。
论文最常见的问题是"需求分析写得像功能列表",只写"系统有登录功能、房间管理功能",这是不及格的。需求分析应该写角色的目标:前台在什么场景下需要什么操作、会遇到什么异常场景。例如"前台在客户到店后,需要快速查询当日预订记录并办理入住,预订时间超过当天的订单,需要支持提前入住或取消"。这种能落到场景里的描述,才是需求分析师该写的内容。
4.2 答辩PPT:五页讲清问题、设计与效果
答辩 PPT 的目标不是炫技,是让你在 8 分钟内讲清楚"为什么做、怎么做、做了什么"。别再放二十页的幻灯片从 Spring Boot 是什么讲起,评委最烦这种东西。我一般会按五页来组织,这五页能覆盖 90% 的提问方向:
- 第1页:项目背景与要解决的问题——用一小段话讲酒店当前手工管理低效,需要数字化系统来管房态和订单。
- 第2页:技术选型与架构图——画一张控制器、服务、Mapper、MySQL 的四层架构图,旁边列出每层用的技术和选型理由。
- 第3页:核心业务流程——画出预订→入住→退房→结算的状态流转图,把事务控制的点标出来,这是最能加分的一页。
- 第4页:运行效果展示——放三到四张核心界面截图,配一句话说明功能,不要贴满屏代码。
- 第5页:总结与不足——主动说两个不足,比如"当前系统没有对接支付接口,订单只能线下结算",再补一句后续计划。
答辩前把这个 PPT 讲三遍,每页控制在 1 分半左右,中间留出切屏演示的时间。评委对你的期望就是"熟悉自己的系统、能说清设计决策",满足这两点就稳稳过关了。
4.3 答辩高频问题:这些追问和springboot面试题高度重合
答辩现场的提问方向其实相当固定,和 springboot 面试题也高度重叠。我见过的高频问题就三类:技术选型类、业务设计类、异常处理类。技术选型类最常问的就是"为什么用 Spring Boot 而不用 SSM?"和"为什么用 MyBatis Plus 不用 JPA?",要从开发效率、内置 Tomcat、自动配置、SQL 可控几个角度准备。业务设计类常问"并发订房怎么解决?""退房时间怎么计算?",答案就在 3.2 和 3.3 的代码逻辑里,要把"乐观锁 + 状态比较更新"讲清楚。异常处理类问"系统如果某一步失败怎么办?",要答上事务回滚和全局异常处理器。
准备这些内容不需要死记硬背,把代码里的每个选择都问自己一句"为什么",能答上来就是得分点。答不上来的提前在论文里写出来,真被问到至少能说"论文第几章有详细说明"。
5. 避坑指南:五个Spring Boot酒店项目的翻车现场
5.1 启动失败:springboot版本太高导致依赖不兼容
现象:项目启动直接报错,控制台出现java.lang.ClassNotFoundException: javax.annotation.PostConstruct或者Error creating bean with name 'requestMappingHandlerAdapter'。很多同学从网上下载的现成源码用的 Spring Boot 3.x,自己的 JDK 却是 8,一启动就全崩。
原因:Spring Boot 3.0 开始全面切换到 Jakarta EE 规范,javax.*包改成jakarta.*,且强制要求 JDK 17 以上。JDK 8 环境下连类都加载不到,跟代码本身没关系,纯粹是环境错配。
解决:毕设项目如果不需要特别新的特性,直接用 Spring Boot 2.7.18 + JDK 8/11。如果必须用 Spring Boot 3.x,就安装 JDK 17 并把所有依赖里的javax全部替换成jakarta。另外注意 Maven 的 settings.xml 里不要配了过旧的镜像源,会导致依赖拉不下来,这种情况换成阿里云公共仓库即可。
5.2 MySQL关键字冲突导致SQL执行报错
现象:系统写 SQL 时用到order做表名或字段名,启动后在插入或查询时报You have an error in your SQL syntax; check the manual ... near 'order'。我用一个订单表把整个项目搞崩,当时完全没想到是关键字问题,排查了半小时才发现是表名的问题,可以说是血泪经验。
原因:order是 MySQL 的保留字,排序用的ORDER BY就是它,直接当表名或列名使用时语法解析失败。同样危险的还有desc、group、rank这些词。
解决:表名统一改成复数orders、sys_user,如果一定用order作为业务名词,SQL 里加反引号包裹\order``,但更推荐在表设计阶段就用别的命名,避免后续每个查询都小心翼翼。
5.3 前端传日期字符串报错,LocalDate接收失败
现象:前端 Vue 组件传checkInDate: "2025-06-01"给后端接口,后端用@RequestBody接收时直接抛HttpMessageNotReadableException或者JSON parse error: Cannot deserialize value of type java.time.LocalDate from String。
原因:Spring Boot 默认的 Jackson 反序列化不支持把yyyy-MM-dd字符串直接转成 LocalDate,需要配置日期格式或加注解。同时前端传的时间格式和后端配置不一致,也会出现这个错。
解决:推荐在配置文件里统一设置 jackson 的格式,全局生效,不用每个实体字段加注解。配置写法在 2.3 已经展示过。另一种方式是在 DTO 的日期字段上单独加@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss"),但既然有全局配置就不建议逐字段加。
5.4 @Transactional自调用导致数据没回滚
现象:在同一个 Service 类里,A 方法调用了本类内部的 B 方法,B 方法标了@Transactional,B 中某一步抛了异常,但数据没有回滚,订单已经插入但房间状态没重置。
原因:Spring 的@Transactional基于动态代理实现,只有调用方从容器里拿到的代理对象才带事务逻辑。类内部this.method()调用直接走原对象,绕过代理,事务完全没有生效,这是网上最经典的 Spring AOP 失效场景。
解决:把需要事务的方法拆到独立的 Service 类中,通过注入的 Bean 调用。如果不想拆类,则在类中注入自身代理@Autowired private UserService self,然后通过self.method()调用。实际项目中我一般选择拆类,职责更清晰,答辩也能讲得更有条理。
5.5 跨域请求被拦截,前端调不通接口
现象:前端 Vue 项目启动在 5173 端口,后端跑在 8080,前端 axios 请求后端接口报Access to XMLHttpRequest at ... has been blocked by CORS policy。这是前后端分离项目的必经之坑,第一次遇到时确实懵。
原因:浏览器的同源策略默认阻止跨域请求,前后端端口不一致就属于跨域,必须在后端配置跨域策略允许来自前端域名、端口、请求头的访问。
解决:新建一个全局的 CorsFilter 配置类,页面路径/**,允许来源http://localhost:5173和http://127.0.0.1:5173,允许方法GET, POST, PUT, DELETE, OPTIONS,允许请求头Authorization, Content-Type。配置完成后记得重启后端,这个过滤器要跟随 Spring 容器一起启动。调试时如果还报错,看是不是请求带了自定义 header,服务端没有通过allowedHeaders放行。
6. 验证与进阶:Postman回归、缓存设计与答辩演示要点
6.1 Postman测试脚本:把核心接口变成可重复的回归用例
项目写完不能只在浏览器里点两下就认为完成了,要把核心接口整理成一组可重复执行的测试用例。我一般会在 Postman 里建一个集合,按照"登录→房间查询→创建预订→办理入住→退房结算"的顺序串起来,每个请求保存好环境变量。登录接口返回的 token 要自动存入变量,后面的接口在 Authorization 里引用{{token}}。Postman 支持在 Tests 标签页写 JavaScript 脚本提取返回值,如下:
// 从登录响应中提取token保存到环境变量 const response = pm.response.json(); if (response.code === 200) { pm.environment.set("token", response.data.token); }这段脚本的逻辑是:发起登录请求后,Postman 自动执行该脚本,拿到响应中请求体里的 token 字段存为环境变量。后续请求通过Bearer {{token}}方式引用,整个集合就能一键顺序执行,跑完看每个请求的响应码和耗时基本就完成了功能回归。参数上注意 Postman 的环境变量分本地和全局,毕设演示时建议把 baseUrl 也做成变量{{baseUrl}},切换环境时只改一个值。
6.2 Redis缓存与并发控制:给系统加一层生产可用性
如果论文里想写一个进阶亮点,在不引入分布式框架的前提下,最自然的方案是给房型查询加 Redis 缓存,给订单号加分布式唯一 ID。酒店场景里房间视图、房型价格是读多写少的操作,每次订单结算后房间状态变化频繁但写入库的次数不多,非常适合缓存。核心做法是引入spring-boot-starter-data-redis,在查询房型列表时先查缓存命中再回源数据库,房间状态变更后主动清除对应缓存 key。这个点写进系统测试和总结展望里,答辩时能明显看到评委的认可度。
6.3 答辩演示技巧:用真实数据撑起十五分钟
最后一个关键技巧是演示数据的准备。答辩现场最容易出事故的环节就是临时创建数据失败。我现在习惯的做法是:提前准备一套干净的演示数据,包含 5 种房型、20 个房间、3 个客户、2 条历史订单,答辩演示时先登录系统,用最快路径创建一条预订、办理入住、再进行退房结算,全程不超过 5 分钟。数据库脚本单独备份,现场出问题时一键恢复。另外提前测试一次投影分辨率下的页面显示,避免界面错位。
这套系统做到这个程度,既能用 Postman 验证核心链路,也有 Redis 和小并发处理的进阶设计,论文和答辩素材都够了。我刚开始做毕设时也是拿到一个 Spring Boot 酒店系统就埋头写代码,结果论文改了三轮才过,后来才明白先跑通业务闭环、再把每个设计决策整理成文档,才是最高效的路径。这是血泪经验换来的习惯,希望对你能有帮助。
本文还有配套的精品资源,点击获取