ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Spring Boot + Android房屋租赁系统实战:从架构设计到联调部署

2026/10/6 9:33:57 拓冰建站 浏览量
Spring Boot + Android房屋租赁系统实战:从架构设计到联调部署 1. 项目概述与受众先聊聊这套 Java Spring Boot 基于 Android 的房屋租赁系统。很多人一听这名字第一反应是 又一个毕设项目但实际把它拆开看它就是一套典型的移动端 服务端两层结构Android 负责给租客、房东、管理员提供操作界面Spring Boot 负责提供房源数据的增删改查、用户登录、租赁订单管理等所有后端能力。市面上大量房屋租赁平台比如链家、自如的 App核心流程也是这套逻辑浏览房源、预约看房、下单签约、管理房源状态区别只是业务复杂度和 UI 精致度。所以这个项目学通了不只是能过答辩而是能理解一个真实业务系统从数据库到接口再到 App 界面的完整链路。这个系统能解决什么问题最直白地讲它把在线下中介门店或者社区公告栏里贴房源信息、打电话约看房的场景搬到了手机端。房东在 App 里录入房源、传图片、设置租金租客按区域、户型、租金区间筛选房源看到合适的可以直接收藏或发起预约管理员在后端接口的帮助下做房源审核、用户管理、数据统计。用技术来替代人工撮合和信息登记这就是项目存在的意义。适合什么人参考如果你是做 Java 后端开发想看看 Spring Boot 接口设计、权限认证、文件上传怎么在一个真实项目里落地如果你是学 Android 的想知道一个完整 App 怎么组织页面、怎么封装网络请求、怎么和后台联调如果你是毕设或者课程设计需要一套能讲清楚、能跑得起来的系统那这个项目都值得花时间拆一遍。我这个分享不会只停留在 下载源码、启动运行 的层面而是把里面的技术点、设计取舍、常见坑位全部讲透看完之后你能对这套系统 不仅会跑还知道为什么这样写。2. 技术选型与架构思路2.1 为什么选择 Spring Boot Android先说服务端。Spring Boot 在这个项目里的地位几乎是不可替代的。相对传统 SSM 框架Spring Boot 内置 Tomcat省掉大量 XML 配置利用自动装配让开发者专注写业务代码。即便是刚从 Java Web 基础转过来的学生也能在一两小时内把它跑起来。如果选 PHP 或 Node.js当然也能做租赁系统但在 Java 技术栈的分子里Spring Boot 是面试、毕设、小公司外包项目中出场率最高的学一遍的性价比极高。Android 客户端为什么不用 Web 页面替代因为项目的定位是 移动端房屋租赁并且 Android 原生能调用相册选图、推送本地通知、保持登录状态等能力比 H5 页面体验更接近真实产品。在实际开发中很多团队为了省事会把 Android 换成 Vue 做后台管理页面再套一层 WebView但这样一来你失去了原生 App 的完整开发链路——OkHttp 网络请求、RecyclerView 列表复用、图片框架加载这些都是 Android 面试和工作中非常常用的点。这个项目选择原生 Android走的是更正统且更耐看的路线。2.2 前后端职责划分与交互流程这套系统的架构并不复杂但我建议学习的时候把它想象成 一个前台 App 一个后台服务。后端 Spring Boot 不负责渲染任何页面而是暴露一套 RESTful API统一返回 JSON 数据。Android 端通过 HTTP 请求访问这些接口拿到 JSON 后解析成 JavaBean渲染到界面。这样前后端完全是解耦的后期想换一个客户端比如再加一个 iOS 端后端代码一行都不用动。典型的一次 房东发布房源 流程是这样的Android 端登录保存 Token 到本地。房东在发布页面填写房源的标题、户型、面积、租金、地址、描述并选择多张图片。Android 端把图片通过 OkHttp 以 multipart/form-data 方式上传到 Spring Boot 的文件上传接口。接口返回图片 URL 后Android 端再连同房源文本字段一起提交到/house/add接口。Spring Boot 收到请求后先校验 Token 权限再校验参数完整性最后向 MySQL 中插入房源记录。这个过程中客户端只做 展示和收集服务端做 校验和落库双方通过 JSON 定好数据结构。理解了这个分界线后面看代码、改功能才有方向感。2.3 基础设施与目录结构我用一个表格把项目推荐的技术栈和版本整理出来这套组合比较稳不容易出现环境冲突层级技术选型备注服务端框架Spring Boot 2.7.x兼容性最好JDK 8/11 都能用ORMMyBatis-Plus租户隔离、分页插件、CRUD 代码生成器很实用数据库MySQL 5.7 / 8.0推荐 5.7多数毕设环境已预装认证方案JWTjsonwebtoken 0.9.1无状态Android 端存入本地Android 网络OkHttp 4.x Gson简洁直接便于理解请求流程Android 图片Glide 4.x图片加载缓存统一处理图片存储本地磁盘路径 静态资源映射简单易部署无需引入第三方 OSS在源码结构上后端通常按照controller / service / mapper / entity / common / config分包。Android 端则是activity / adapter / bean / api / utils / fragment分层。这种分法不花哨但胜在清晰。实际接手项目时我第一件事就是把包结构看一遍因为包结构能直接反映这个项目写没写 人样。3. 数据库设计与核心表结构3.1 用户、房源、订单、收藏表设计数据库设计是决定系统好改难改的关键。很多毕设项目外观能跑但新增一个功能要动六七张表就是因为当初字段设计不合理。这套房屋租赁系统里最核心的是四张表user用户house房源housestate租赁订单/状态collect收藏。用户表不必多说需要区分管理员和普通用户我一般在role字段里用数字区分1表示管理员2表示房东3表示租客。有同学问为什么不建三张用户表这属于过度设计。除非业务差异大到字段完全不同否则一张表加角色字段就够了。房源表是信息密度最大的表我列出比较常见的字段设计思路你可以直接抄作业字段名类型说明idint主键user_idint发布者 IDtitlevarchar(100)房源标题typevarchar(20)出租方式整租/合租addressvarchar(255)小区地址areadouble面积平方米pricedouble月租价格imagestext图片 URL多张用逗号分隔statusint0 待审核 / 1 已上架 / 2 已出租 / 3 已下架create_timedatetime发布时间我这里特意把images字段设计成逗号分隔的字符串而不是单独建一张图片表。有人会争论这样做不规范但在这种小体量系统里这是一种性价比极高的方案查询列表时只需查一张表减少一次子查询或关联查询。如果你追求范式严格也可以拆图片表但实际开发和毕设维护都会变麻烦没必要。订单表是整个业务核心它负责记录一次租赁关系的完整状态变化字段一般包括图片、house_id、user_id、landlord_id、start_time、end_time、rent_month 等尤其是status字段要灵活动态化因为后续接口逻辑全靠它判断。3.2 状态字段与关键索引设计状态字段是最容易被小看的。比如房源状态我建议用int而不是字符串原因很简单字符串一旦拼写不一致比如 上架 和 上架 直接会导致列表查不到数据数字枚举在代码里写常量或枚举类可读性一点不差。后续你写 SQL比如 查询所有已上架房源就是WHERE status 1清晰高效。订单表的状态流转我习惯用状态机思维设计避免业务逻辑到处乱写。比如一次租赁订单可以经历这些状态0待确认1已确认等待支付/签约2租赁中3已到期4已取消5已退租这样一来每次状态变化的判定都集中到service层的一个方法里不会出现 在 controller 里偷偷改字段 的烂代码。索引设计也不能只靠默认主键。在这个项目里有两个查询场景频率最高用户查看自己的发布记录user_id查询、平台端按状态筛选列表status查询。所以我会在user_id和status上各自加一个普通索引。数据量不大时可能看不出差别但这是好习惯也方便你在答辩时说清楚 为什么加索引。4. 后端接口与核心逻辑实现4.1 登录认证与权限控制登录认证是后端最重要的一块。这个项目常用 JWT 或者 Session我建议优先使用 JWT因为它是无状态的Android 端拿到 Token 存本地即可服务端升级扩容、横向扩展时没有 Session 同步问题。我简单描述一下 JWT 的接入思路。用户调用/user/login提交用户名和密码后端校验通过后用 secret key 生成 Token返回给 Android。Token 里可以带上 userId、role 这些关键信息但千万不要把密码放进去。之后每次 Android 发起需要身份认证的请求都在 header 里携带token: xxx。Spring Boot 通过一个拦截器或者过滤器在进入 controller 前解析 Token、校验合法性和有效期再把用户信息放到 request 里。写拦截器时有几个容易踩的坑不需要认证的路径比如登录、注册、房源列表必须放行否则用户没登录就看不到任何内容。Token 过期后要返回统一格式的错误信息Android 端收到后需要做 重新登录 的跳转提示而不是让界面卡在空白页面。管理员的接口要校验 role 字段防止普通用户通过直接调用接口删房源。4.2 租赁流程中的关键接口与状态机围绕房屋租赁我认为最值得学习的是两个接口添加房源和创建订单。添加房源接口的流程我前面提过这里补充一个关键点图片上传接口一定不能和房源新增接口耦合成一个接口否则图片较大时请求超时概率很高。正确做法是先后端提供一个/upload返回图片 URL再把 URL 拼接进房源数据。这样一方面提高了重试的灵活性另一方面方便复用。上传建议限制图片大小比如单张最大 5MB格式校验白名单防止用户传非图片文件进来。创建订单接口的难点在于并发和防重复。业务中租客可能手快点了两次 立即租房如果不做处理会出现同一房源同时生成两笔订单。处理方法不复杂在创建订单前先查询该房源当前状态是否为 已上架如果不是就返回明确提示同时给用户 ID 加一个防重复提交标记比如 Redis 里面存一个 key这是企业级做法。但如果你不想引入 Redis也可以在 SQL 层面做判断用一个带house_id status的唯一约束兜底让数据库去挡第二次提交。下面这段代码可以帮你理解查询房源列表时常用的条件组合写法public IPageHouse getHouseList(int page, int size, String type, Integer status, String keyword) { LambdaQueryWrapperHouse wrapper new LambdaQueryWrapper(); if (StrUtil.isNotBlank(type)) { wrapper.eq(House::getType, type); } if (status ! null) { wrapper.eq(House::getStatus, status); } if (StrUtil.isNotBlank(keyword)) { wrapper.like(House::getTitle, keyword); } wrapper.orderByDesc(House::getCreateTime); return houseMapper.selectPage(new Page(page, size), wrapper); }这里我习惯用LambdaQueryWrapper好处是字段名是带编译时检查的字段拼错会直接报错而不是运行时才暴露问题。分页用的是 MyBatis-Plus 自带的分页插件前端传page和size后端返回total和records这套交互协议在真实项目里也是标准做法。4.3 参数校验与统一返回格式很多新手项目最大的问题是前后端各写各的字段名对不上错误提示对不上。要避免这个问题从第一天就要定好统一返回结构。我常用这样的 JSON 格式{ code: 0, message: success, data: {} }code0表示成功非 0 表示失败。message是给用户看的提示比如 用户名或密码错误、图片大小不能超过5MB。Android 端解析的时候只用判断code是否为 0再拿到data来做后续逻辑非常省事。参数校验要依托Validated注解加实体类字段约束比如NotBlank、NotNull、Min。千万别把一堆 if 判断写在 controller 里谁维护谁知道痛苦。当然校验不通过的异常也要集中处理用RestControllerAdvice ExceptionHandler把异常统一包装成上面的 JSON 格式再返回给 Android 端。这一块虽然在界面上看不到但在后端代码评审时加分极多。5. Android 端实现细节5.1 项目结构与网络层搭建Android 端的源码质量直接决定这个项目给人第一印象好不好。我最反感的是把几百行代码全部写在 MainActivity 里页面一多就变成 面条代码。这个项目我建议至少分这么几类包bean存放对应后端返回结构的实体类。api存放接口定义比如登录接口、房源列表接口、收藏接口。adapter各个列表的适配器。activity/fragment页面逻辑。utils公共工具类PrefUtil、网络判断等。网络层不用过度封装但至少要做一个单例。我讲解视频里最常演示的是用 OkHttp 封装一个HttpUtil类内部维护一个 OkHttpClient 实例对外提供 get 和 post 方法。再在此基础上加一个回调接口把成功和失败分发出去这样 Activity 里就不用关心线程切换问题了。HttpUtil.post(house/list, params, new HttpUtil.CallBack() { Override public void onSuccess(String json) { // 解析 json更新 UI } Override public void onFailed(String msg) { Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show(); } });回调里要记得runOnUiThread切换主线程否则直接更新 TextView 会崩溃。这个细节很多初学者会忽略也是很常见的 Android 崩溃点。5.2 页面清单与功能拆解在界面设计上一个完整租赁 App 至少要包含这些页面登录、注册页。主界面首页房源列表或轮播推荐、类型筛选、个人中心用 BottomNavigationView Fragment 实现。房源详情页图片轮播、房屋信息、房东信息、收藏按钮、预约看房/立即租房按钮。发布房源页表单录入 多图选择上传。我的订单页区分 我发布的 和 我租赁的。后台管理页房源审核、用户列表、数据概览。房源列表页通常用 RecyclerView 展示Adapter 里的 item 布局要包含标题、价格、户型、面积、封面图。这里有一个实际经验列表页不要一次性把所有字段都加载进来尤其是images字段较长很容易拖慢首次加载速度。更合理的做法是在列表接口中只返回图片的第一张也就是前端截取逗号分隔结果的第一个这样列表加载会明显变快。图片加载直接上 Glide。Glide 的好处是支持占位图、错误图、内存和磁盘缓存还能自动处理 OOM 风险。如果你还在用它加载网络图片时忘记加路径比如把http://192.168.1.100:8080/upload/1.png写成本地路径那一定加载不出来。5.3 登录状态与 Token 管理Android 端的登录态保存最简单可靠的是 SharedPreferences。登录成功以后把 Token、userId、role 存下来在每次网络请求的 header 里带上 Token用户在个人中心点击退出登录时清除这些数据并跳回登录页。这个流程看起来简单实际有几个细节要注意。第一SharedPreferences 提交要用apply()而不是commit()因为前者是异步写入不会卡主线程。第二不能把所有页面都要求登录比如首页房源列表一定要允许未登录访问否则搜索引擎和分享链接的场景会非常尴尬。第三当某个接口返回 Token 失效时Android 端最好能统一弹出一个对话框让用户重新登录而不是在每个 Activity 里各自判断。可以用一个全局的 Activity 管理工具在检测到失效码时关闭所有页面并回到登录页这样体验才像一个真正的商业 App。6. 运行部署与调试经验6.1 本地启动步骤一个新环境要跑起这个系统顺序很重要。先启动 MySQL创建好数据库house_rental修改后端配置里的数据库连接字符串然后启动 Spring Boot 项目。建议在src/main/resources下的application.yml中用外置配置覆盖默认配置这样换环境不用改源码。你可以这样配置server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/house_rental?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai username: root password: 123456 servlet: multipart: max-file-size: 5MB max-request-size: 20MB mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl启动后后端默认端口 8080可以用 Postman 或者直接用浏览器访问http://localhost:8080/house/list验证接口能否返回 JSON。我每次都建议新人先跑通一个最简接口再写页面不要一上来就全量堆代码否则定位问题会非常难。Android 端先在 Android Studio 里导入工程等待 Gradle 同步完成。注意本机 Android SDK 版本要匹配项目配置最常见的报错是 SDK Build Tools 版本缺失AS 一般会提示自动安装。然后在模拟器或真机上运行。用模拟器时后端地址一定要写成http://10.0.2.2:8080而不是localhost因为模拟器里localhost指向模拟器自己。用真机时填电脑的局域网 IP并且保证手机和电脑连的是同一个 Wi-Fi。6.2 常见联调问题与排查思路联调阶段我整理了下面几个高频问题几乎每个初学者都会遇到现象原因解决办法Android 请求接口超时后端服务没启动或地址填错先看后端控制台日志再确认 IP/端口中文乱码数据库字符集不是 utf8mb4在建库语句里指定DEFAULT CHARSETutf8mb4同时连接串加characterEncodingutf8图片上传后加载 404后端静态资源映射未配置在 WebMvcConfig 中配置/upload/**资源映射到本地磁盘路径房源列表一直加载失败JSON 字段名与 JavaBean 不对应打印后端返回 JSON检查 Bean 字段名确认有无SerializedName真机访问不了后端手机与电脑不在同一局域网/防火墙拦截关防火墙或放行 8080 端口用别的手机热点测试关于跨域Android 原生 App 其实不受浏览器跨域限制但会有明文流量限制。如果后端是 http 而 Android 较高版本默认禁止明文你需要在AndroidManifest.xml里设置usesCleartextTraffictrue不然请求会直接被拦截。这个问题特别隐蔽我见过很多同学在模拟器上正常、在真机上挂了半天找不到原因。7. 二次开发建议与避坑清单7.1 新手最容易踩的坑这个项目如果要作为毕设或者真实项目交付有几个坑我真心建议避开。第一个坑是时间字段的设计。很多新手会把starttime、endtime字段设计成 String直接存 2024-06-01 这样的文本。这样做的危害是排序、比较租期时会出错而且无法使用 MySQL 的时间函数。规范做法是用datetime类型后端用LocalDateTime接收和返回前端再格式化展示。第二个坑是删除数据的粗暴操作。房源、订单这类数据千万别用物理删除。一旦用户不小心误删或者面试官问 如何恢复数据你就难堪了。建议加一个is_deleted字段做逻辑删除MyBatis-Plus 也支持配置TableLogic注解查询时自动过滤删除时自动改为 update非常省心。第三个坑是接口权限遗漏。很多毕设项目只在界面上做了按钮隐藏但接口完全没有权限过滤用户只要抓个包直接调用接口就能删别人房源。这个系统里至少要保证 修改、删除、审核 三类接口都必须校验管理员或资源拥有者身份。实现方式是在 service 里传入当前用户 ID再和资源的user_id比对不一致就直接抛出 无权操作。7.2 可扩展方向如果答辩时间充裕你完全可以在基础功能上加几个亮点成本和收益都高。在地图上展示房源位置后端存经纬度字段Android 端引入高德或者百度地图 SDK做一个房源地图视图。这个功能视觉冲击力强且实现不复杂。增加短信验证码登录借助第三方短信服务传递用户手机号和验证码替换一部分密码登录场景可以展示你对消息通信的理解。增加爬虫或者数据字典比如在后台统计各区域房源数、平均租金用 ECharts 或 Android 图表框架展示。这是妥妥的加分项。租约支付如果要做得像商业产品还需要抽象支付回调流程但毕设阶段不一定落地可以在文档里描述清楚设计思路。另外提一句如果你想把这个项目包装成简历项目切记不能只写 实现了房屋租赁 CRUD。要突出你在权限控制、状态机设计、防重复提交、图片上传优化、真机联调兼容性这些点上的思考这才是面试官想听的东西。8. 实操体验与收尾建议最后分享一点个人体会。带过几届学生做类似的毕设和训练营项目我发现大家最容易卡住的阶段不是写代码而是 代码跑起来之后不知道干什么。拿到这套系统源码后我建议你按三步走第一步不看代码把后端数据库建出来用 Postman 测一遍主要接口感受一下接口的请求和响应结构第二步对照源码把接口实现捋清楚画一张自己看得懂的调用链路图第三步改一个小功能比如给房源列表增加按价格排序的参数亲自动手改代码、重启服务、验证效果。走完这三步这套系统才真正变成了你的东西。如果你打算在毕设答辩里讲这个项目多准备几个 为什么 的回答。比如 为什么订单状态用 int 不用 String、为什么图片地址用逗号拼接而不是关联表、为什么登录用 Token 不用 Session。这些问题都是加分机会也是真正体现你深入理解项目的时刻。做这套系统难度不在于堆功能而在于把每个模块之间的边界打磨清楚。服务端只提供接口逻辑客户端只负责展示和交互数据库用合理字段支撑业务流转。这套思路放到任何业务系统里都适用。希望这篇分享能帮你少走一些弯路把项目做得比大多数模板更有底气。