资讯动态

Spring Boot + Android 酒店预订系统全栈开发实战与毕设避坑指南

发布时间:2026/10/9 6:40:41 来源:尧图企业网站定制
做了好几套“Spring Boot Android”的毕业设计项目这种酒店预订系统算是我被问得最多的类型之一。一方面因为题目关键词覆盖广有后端有客户端还有小程序另一方面网上虽然能找到大量源码片段但真正能跑通闭环、配套文档齐全、能应付答辩完整的并不多。这篇就把我实际落地一套酒店预订 App 的全过程拆开讲从技术选型、数据库设计、核心接口、Android 端联调到常见坑位和答辩准备全部覆盖。无论你是刚拿到这个题目、想要完整源码作参考还是已经开始写代码卡在某个环节这篇文章都应该能帮你少走不少弯路。1. 项目整体设计与功能拆解1.1 毕设为什么要选“酒店预订”方向酒店预订系统是典型的“信息展示 状态管理 交易闭环”业务麻雀虽小但五脏俱全。比起图书管理系统、班级管理系统这类纯 CRUD 项目酒店预订有更真实、更清晰的业务约束库存、日期冲突、订单状态流转、支付流程。这些约束放在毕业设计里恰恰是你能展示技术深度的地方。老师问到“你的订单状态怎么设计”“并发下单会不会超卖”你都有具体场景可以展开回答。从技术选型来看这个题目自带了完整链路Android 原生客户端负责用户操作Spring Boot 提供后端接口MySQL 存数据可以再加一个微信小程序端复用同一套接口。对毕设来说它天然体现“移动端 后端服务 数据库”三种能力的结合展示效果也比网页后台直观得多。你在台上用模拟器点两下订房比放几张系统截图有说服力。还有一个很实际的优势酒店预订贴近日常不需要额外学习行业知识。需求分析章节也不难写用户角色、预订流程、房型信息、价格计算都是普通人都理解的场景不会在开题阶段就卡住。后面想扩展也容易比如加评论、地图定位、会员积分、价格日历随便挑一个都能作为论文里的“系统特色”。1.2 核心功能模块怎么拆系统按角色分为用户端和管理端两部分。用户端就是 Android App 和微信小程序管理端一般用后台 Web 页面或 Swagger 接口文档来体现。我这里主要围绕用户端梳理几个必备功能用户模块注册、登录、个人资料修改。密码不能明文存登录成功后返回 Token客户端在后续请求里带上。首页与房源模块酒店和房型列表支持按城市、价格区间筛选展示房型图片、床型、面积、设施、价格。预订模块选择入住和离店日期自动计算晚数和总价生成订单。核心是校验日期不能冲突、不能选过去日期并且下单时要锁定对应日期段的库存。订单模块订单列表按状态区分为待支付、已支付、已入住、已完成、已取消。用户可取消未支付的订单管理端可确认入住和退房。支付模块毕业设计一般用模拟支付生成一个支付二维码或直接模拟支付成功回调避免真实资金操作。管理后台维护房型信息、管理订单状态、管理用户可以通过 Spring Boot 提供 REST API再配一个简单的 Vue 页面或者直接用 Swagger 展示接口能力。我的建议是实现优先级先做登录、房源列表、房型详情、下单、订单列表这五个闭环。不需要一开始就把所有页面都做出来。很多同学一上手只顾着写漂亮的 Android 页面后端接口还没跑通最后演示时只能点死界面这是最坑的。先打通最小端到端链路再逐步补后台和支付才是稳的做法。1.3 服务端与客户端职责怎么划分一个常见错误是让客户端做太多业务判断。比如判断入住日期是否在今天之前前端做了校验固然体验好但真正的判断必须放在 Spring Boot 后端因为接口可以被任何人直接调用不只是你的 App。正确做法是客户端只做展示和交互业务规则全部由后端兜底。后端接口统一返回固定格式的 JSON大概长这样{ result: success, code: 200, msg: 操作成功, data: {} }失败时 result 为 failurecode 换成业务状态码msg 是展示给用户的信息data 为业务数据。这个统一响应结构非常重要Android 端在 Retrofit 的解析层做统一处理登录状态失效就自动跳回登录页小程序端在 request 封装里做同样逻辑。我后来做其他项目也一直沿用这套约定能省掉大量重复的错误判断代码。2. 技术选型与核心实现细节2.1 Spring Boot 后端分层与依赖选择我的后端选的是 Spring Boot 2.7搭配 MyBatis-Plus、MySQL、Redis 和 JWT。选 2.x 而不是 3.x主要是兼容性考虑3.x 要求 JDK 17 及以上很多同学本机装的还是 JDK 8 或 11强上用 Spring Boot 3 会遇到大量环境问题。另外 2.x 的教程和踩坑资料最丰富MyBatis-Plus 等中间件适配也稳定对毕设来说完全够用。如果你的电脑已经是 JDK 17 以上并且想尝新才考虑升级。切记不是版本越新越好先求稳。后端采用标准三层结构Controller 层接收参数调用 Service不写业务逻辑。Service 层处理核心业务事务在这里控制。Mapper 层MyBatis-Plus 的 BaseMapper 提供单表 CRUD复杂查询再用 XML 写动态 SQL。这样分层最大的好处是定位问题快。参数不对找 Controller业务逻辑错找 ServiceSQL 慢看 Mapper。写论文架构图时也很清晰三层加客户端再加数据库一张图讲完所有。依赖方面核心的是 spring-boot-starter-web、mybatis-plus-boot-starter、mysql-connector-java、spring-boot-starter-data-redis、jjwt以及 hutool 工具库。Hutool 主要是用来做随机数、日期处理、雪花 ID 生成这些琐碎操作不引也行但引用后效率高很多。2.2 Android 端网络请求与页面架构Android 端用原生 Java Retrofit OkHttp Glide RecyclerView 这一套组合。页面架构没有上重框架就用简化版 MVVMActivity/Fragment 负责交互ViewModel 持有数据Repository 封装网络请求。对于毕设项目来说不需要把 LiveData、Room 全引进来过度设计反而是负担重点是把网络层写好。网络请求的写法以登录为例定义 ApiService 接口public interface ApiService { POST(user/login) CallApiResponseUserVo login(Body LoginRequest request); GET(room/list) CallApiResponseListRoomVo roomList(Query(city) String city, Query(page) int page, Query(size) int size); }Retrofit 初始化时设置 baseUrl这里有一个经典大坑Android 模拟器访问本机 Spring Boot不能写 localhost 或 127.0.0.1要用 10.0.2.2。真机调试则通过 adb reverse tcp:8081 tcp:8081 把电脑端口映射到手机或者确保手机和电脑在同一局域网使用电脑的局域网 IP。很多毕设项目第一次联调百分之八九十的时间都耗在这个地址问题上后面我会在常见问题里详细展开。2.3 小程序端怎么快速复用后端接口题目里带“小程序”这里单独解释一下。小程序的定位是复用同一个后端服务展示多端能力。因为后端接口全部是 RESTful JSON小程序端不需要重新写业务逻辑只需要封装一层 request把 Token 拼接、错误提示、401 处理这些公共逻辑抽出来。小程序页面结构大致是首页搜索城市和推荐酒店、房型列表页、房型详情页、下单页、订单列表页、个人中心。如果使用原生微信小程序开发代码量不小但如果你已经写了 Android 原生 App不建议再花大量时间做一个小程序版本。除非你的课题明确要求多端覆盖否则更推荐用 uni-app 写一套基础版小程序页面与 Android 核心功能对齐即可。论文里把这个做法总结为“多端复用同一套接口降低业务实现成本”本身就是一个亮点。3. 实操过程与核心环节实现3.1 数据库设计与建表 SQL数据库命名 hotel_db核心表为用户表、房型表、库存表、订单表。用户表负责账号登录房型表存酒店和房间信息库存表按日期维度管理可订数量订单表记录用户每一笔预订。四张表就能构成完整闭环。用户表CREATE TABLE user ( id BIGINT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(100) NOT NULL, nickname VARCHAR(50), phone VARCHAR(20), avatar VARCHAR(255), create_time DATETIME DEFAULT CURRENT_TIMESTAMP );房型表CREATE TABLE room_type ( id BIGINT PRIMARY KEY AUTO_INCREMENT, hotel_name VARCHAR(100) NOT NULL, city VARCHAR(50) NOT NULL, name VARCHAR(100) NOT NULL COMMENT 房型名大床房/双床房, price DECIMAL(10,2) NOT NULL, area INT, bed_type VARCHAR(50), max_people INT, image_url VARCHAR(500), description TEXT, status INT DEFAULT 1 COMMENT 1上架 0下架 );订单表CREATE TABLE orders ( id BIGINT PRIMARY KEY AUTO_INCREMENT, order_no VARCHAR(32) NOT NULL UNIQUE COMMENT 订单号, user_id BIGINT NOT NULL, room_type_id BIGINT NOT NULL, room_id BIGINT DEFAULT NULL, check_in_date DATE NOT NULL, check_out_date DATE NOT NULL, nights INT NOT NULL, total_price DECIMAL(10,2) NOT NULL, contact_name VARCHAR(50), contact_phone VARCHAR(20), status INT DEFAULT 0 COMMENT 0待支付 1已支付 2已入住 3已完成 4已取消 5已退款, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, pay_time DATETIME );这里有几个设计点值得专门说。第一订单号字段必须唯一不要在代码里直接拿自增 id 当订单号展示并发场景下很容易出问题用时间戳加随机数或雪花 ID 更合适。第二库存控制不要简单用“订单总数减总库存”因为已取消的订单会污染数量建议单独建库存表按房间类型和日期维度管理。第三订单状态用 int 不用字符串枚举直观且查询高效。第四金额字段用 DECIMAL不要用 float 或 double否则价格计算会出现浮点误差。库存表是预订模块的核心脚本如下CREATE TABLE hotel_stock ( id BIGINT PRIMARY KEY AUTO_INCREMENT, room_type_id BIGINT NOT NULL, stock_date DATE NOT NULL, total_stock INT NOT NULL DEFAULT 10, booked_stock INT NOT NULL DEFAULT 0, UNIQUE KEY uk_room_date (room_type_id, stock_date) );每次下单时把入住到离店每一天的库存都检查一遍全部有房才允许创建订单并在事务里对 booked_stock 加一。3.2 后端核心接口实现登录接口是第一个闭环。用户注册时用 BCrypt 加密密码登录成功后生成 JWT 返回给客户端。JWT 是无状态方案服务端不保存会话客户端在后续请求的 Header 里带 Authorization后端拦截器解析即可。登录 Controller 的代码很简单RestController RequestMapping(/user) public class UserController { Resource private UserService userService; PostMapping(/login) public ApiResponseLoginResult login(RequestBody Valid LoginRequest request) { return ApiResponse.success(userService.login(request.getUsername(), request.getPassword())); } }Service 里核心是查用户、比对密码、生成 Token。比对密码不要用 MD5引入 spring-security-crypto 的 BCryptPasswordEncoder 单独处理比写一堆加盐逻辑规范得多。预订接口是整个系统的重头戏。下单时要做三件事校验用户、校验所选日期段库存、创建订单并扣库存。这里扣库存的做法决定系统是否容易出脏数据。我在事务里执行更新库存的 SQLUPDATE hotel_stock SET booked_stock booked_stock 1 WHERE room_type_id ? AND stock_date ? AND booked_stock total_stock;如果影响行数为 0说明当天没房直接抛业务异常并回滚事务提示用户“所选日期段部分日期已满房”。这种写法本质上是数据库行锁加乐观条件更新能避免两个用户同时下单导致超卖。答辩时把这个逻辑讲清楚老师基本不会再纠结你的并发控制问题。3.3 Android 端登录与房源列表实现登录页逻辑很直接EditText 拿账号密码点击按钮调用 Retrofitloading 对话框等待返回成功就把 Token 存到 SharedPreferences然后跳转主页。需要注意在 Activity 销毁时取消请求避免页面关闭后回调更新 UI 导致崩溃。房源列表页用 RecyclerView 展示卡片每张卡片包含酒店图、房型名、地址、价格和剩余库存。列表数据用分页接口Android 端监听 RecyclerView 滑动到底部时自动加载下一页。这个功能基础但很实用体现移动端性能优化意识。几个 Android 开发细节值得单独记一下图片加载用 Glide占位图和错误图一定要设置否则弱网环境下页面很难看。Item 使用 ViewBinding 或 ViewHolder 管理不要在列表里频繁 findViewById。日期选择建议用 MaterialDatePicker比两个 EditText 手输日期体验好太多。金额展示统一用 BigDecimal 转字符串避免精度问题。每次请求都要处理网络错误和业务错误不要只在成功回调里写 UI。4. 常见问题与排查技巧实录4.1 Spring Boot 版本过高引发的兼容问题最近毕设季收到最多的提问就是“为什么我的项目启动就报错”。翻来覆去查大多都是新建项目时顺手选了 Spring Boot 3.x结果 MyBatis-Plus 版本不兼容或者 javax.* 包名改成 jakarta.* 后一堆代码全挂。GitHub 上大量教程还是 2.x 的写法抄作业抄到一半发现类不存在这种体验非常折磨人。解决办法是选稳的组合Spring Boot 2.7 MyBatis-Plus 3.5.x JDK 8。如果你的环境已经是 JDK 17 且想用 3.x至少要把所有 javax.* 换成 jakarta.*并引入 mybatis-plus-spring-boot3-starter。但对毕业设计来说2.7 在功能上完全不落后以稳为主就好。还有一个建议把项目所有第三方依赖的版本整理成一张对照表放进文档答辩时问到“版本怎么定”你能答出依据印象分会明显提升。4.2 模拟器与真机联调的网络地址问题这个话题在毕设联调里几乎必问。先记住三条规则Android 模拟器访问宿主机后端地址用 10.0.2.2不是 localhost。后端端口不要用 8080建议换 8081 或 9000减少被本机其他程序占用的概率。Spring Boot 配置文件的 server.address 不要写 127.0.0.1直接留空或写 0.0.0.0否则手机连不上。真机调试时用 adb reverse 最省心adb reverse tcp:8081 tcp:8081执行之后手机访问 localhost:8081 就会转发到电脑的 8081 端口不需要手机和电脑在同一 WiFi。这个方法对 USB 调试场景非常稳定。如果非要用局域网 IP要确保手机和电脑在同一网段并且 Windows 防火墙放行对应端口。很多同学后端启动成功但手机连不上八成都是防火墙没放行。4.3 订单状态与并发预订的几个坑订单状态流转看着简单实际做起来容易漏细节。几个反复被问到的坑重复提交订单。用户快速点两次“提交预订”可能产生两条订单。前端要加防抖后端在短时间窗口内限制同一用户对同一房型重复下单两者都做最保险。取消订单后库存没恢复。取消接口的 Service 方法必须有事务并且在修改订单状态的同时减去库存表对应日期的已订数量。这个逻辑漏了之后库存会越卖越少而且很难定位。价格与日期挂钩。节假日和平日价格不一样计算总价不能只乘一个固定单价。我的做法是增加价格日历表按日期保存价格下单时聚合求和。超时未支付。如果要做“下单 15 分钟未支付自动取消”用 Scheduled 定时任务扫表最稳妥不要依赖 Redis 过期事件。Redis 过期事件在流量高的场景下并不可靠漏触发很常见。这些细节我在文档里整理成“异常场景清单”每个截图配一段说明。答辩老师看到一个学生主动聊异常处理印象分往往比聊功能要高。5. 毕设文档与答辩准备5.1 论文结构怎么组织任何一个带 Spring Boot 和 Android 的毕设论文大纲都是“绪论、需求分析、系统设计、系统实现、系统测试、总结展望”这个框架但内容要落到实处绪论写背景和国内外现状时不用抄千篇一律的话可以引用一两个具体产品和技术演进趋势比如移动端酒店预订 App 的常见架构以及服务端从单体走向微服务的过程。需求分析放用户角色、用例图、功能需求、非功能性需求。系统设计放总体架构图、功能模块图、数据库 E-R 图、界面原型图。系统实现按模块写每个模块给出关键类图、接口说明、核心代码片段、运行截图。系统测试设计测试用例覆盖正常流程和异常流程列出测试结果表。论文里放代码要克制只截取核心逻辑的关键片段不要整个类贴进去。截图要清晰、尺寸统一界面状态与文字描述对应。数据库设计章节我给每张表都做了字段说明表一个字段一行整理成 Markdown 再粘进 Word比手敲高效很多也更整齐。最重要的一条原则代码和论文必须一致。我见过不少学生最终演示的接口和论文里写的完全对不上老师一追问就露馅。正确做法是代码跑通一个模块就截图、写描述代码改动后同步更新论文里的接口说明。千万不要代码写完了再补论文那样既累又容易遗漏。5.2 答辩演示和常见提问演示顺序建议先启动后端用 Swagger 或 Postman 展示核心接口再打开 Android 模拟器演示注册、登录、浏览房源、下单、取消订单最后打开管理端修改一条数据展示前后端联动。整个过程控制在 10 分钟以内不需要把每个按钮都点一遍重点演示三个闭环即可。答辩老师常问的问题我列了几个JWT 为什么无状态服务端怎么判断登录失效答JWT 自带过期时间后端解析签名并检查过期时间要主动踢人则引入 Redis 记录登出态或黑名单。MyBatis-Plus 与 MyBatis 的区别答前者内置常用 CRUD后者需要手写 SQL本项目单表操作用 MyBatis-Plus复杂查询用 XML 写自定义 SQL。库存扣减如何避免超卖答核心是对库存表的可用数量做条件更新影响行数为 0 则回滚同时在事务里完成。为什么不用微服务架构答当前业务规模单体架构足够引入服务注册、网关、配置中心会显著增加复杂度将来用户量和订单量增长后可以按用户服务和订单服务拆分。客户端与服务端数据传输怎么保证安全答生产环境使用 HTTPS接口层可加签名和参数加密毕设演示使用本地环境重点把业务闭环和异常处理讲清楚。回答问题的核心不是背概念而是讲清“我遇到了什么问题、为什么选这个方案、有没有验证过”。老师最怕只会背理论不知道怎么落地的学生你把自己的设计和实践讲清楚分数通常不会低。踩过几次坑之后我的体会是做这类全栈毕设项目最大的成本不是写代码而是联调和兜底。提前把统一响应结构、Token 机制、库存更新策略定下来后面所有功能都会顺很多。数据库表也不用刚开始就急着建完先跑通登录再慢慢加订单和库存边写边补反而更自然。毕设资料一定要边做边整理代码注释、数据库导出脚本、接口文档、测试用例截图每完成一个模块就同步更新一次。真到了写论文阶段基本只是把素材组装进去不会再有那种熬夜赶工的绝望感。如果时间还宽裕我建议把支付模块换成真实的小程序支付沙箱或者把后台管理做成一个独立的小型 Vue 页面这两个改动会让项目的完整度和答辩亮点直接上一个台阶。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑