ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Spring Boot房屋租赁系统毕业设计关键技术与实践

Spring Boot房屋租赁系统毕业设计关键技术与实践 1. 选这个课题先想清楚它到底难在哪每年到了毕业设计选题季Spring Boot 房屋租赁信息系统都会出现在选题列表里因为它看起来功能不少、技术不难、场景熟悉但真拿到需求文档动手做的时候很多同学才发现这个题目不是写个增删改查就能交差的。我见过太多人前期觉得简单中期在权限和订单状态流转上卡了三个星期最后临时砍功能答辩时被老师一问就露馅。房屋租赁信息系统的核心价值在于它不是一个单边系统而是用户端、房东端、管理后台三方协同的业务系统。用户要搜索房源、收藏、提交看房申请、签约下单房东要发布房源、维护房源状态、处理申请管理员要审核房源、管理用户、处理投诉和统计报表。三方角色的操作互相牵连数据状态相互影响这才是这个题目真正的分量所在。如果只做一个房源列表详情页后台管理那和课设没区别撑不起一篇合格的毕业设计论文。从这个角度说选这个题目的人必须接受一个现实你要交付的是一个有完整业务闭环的项目。表结构至少要覆盖用户、房东、房源、订单、收藏、公告、反馈这些核心实体接口要能支撑多角色权限隔离状态设计要能描述房源上下架、订单从申请到完成的全流程。这些内容既是开发的难点也是论文中最容易写出深度的部分。选这个题不亏但别低估它。1.1 房屋租赁系统的业务盘子有多大把需求展开看业务模块至少可以分为四块。第一块是用户端对应小程序或Web前端承载注册登录、房源搜索与筛选、房源详情、收藏、看房申请、租赁订单、在线签约、个人中心等功能。第二块是房东端主要包括房源发布、房源图片与配置维护、租客申请处理、合同管理、账单与收款记录。第三块是管理后台覆盖用户管理、房源审核、订单监督、公告发布、字典配置、数据统计。第四块是公共基础模块包括短信验证码、文件上传、权限拦截、日志记录、全局异常处理。这不是我故意把盘子铺大而是这个业务天然就需要这么多东西。房屋租赁不是商品交易它有一个很长的线下转化链路看到房源、咨询、线下看房、确认意向、签约、入住、付款、退租。线上的信息系统至少要管理房源-申请-订单-合同这条主链再把用户和角色挂在上面才叫完整。对于毕业设计而言你的任务不是把这些模块全部做满功能而是在完整的数据模型和清晰的模块划分之上选择两到三个核心模块做深其余的做到接口可用、页面可走通即可。这个度要把握好模块划分少了论文没有内容可以写功能做太浅演示的时候撑不住十五分钟。最好的状态是骨架完整、血肉突出比如把房源检索和订单流转做细把公告和反馈做成简单但可用的模块。1.2 毕业设计的核心考核点答辩老师看一个毕业设计项目通常不看你的界面炫不炫而是看三点数据模型是否合理、业务流程是否闭环、技术应用有没有自己的思考。这三点恰好都是房屋租赁系统的用武之地。数据模型方面你要能解释清楚为什么用户表要加role字段而不是单独建一张角色表为什么房源表要单独存landlord_id而不是直接使用user_id关联为什么订单状态要用int而不是字符串。这些看起来是细枝末节但老师一问你的表设计依据是什么答不上来就很被动。业务流程方面重点是状态流转。比如一个房源的状态应该是待审核 - 已上架 - 已下架/已租出一个租赁申请单的状态是已提交 - 房东已接受/已拒绝 - 待签约 - 已签约 - 已入住 - 已退租。每个状态由谁触发、在哪个接口触发、触发后对关联表产生什么影响都必须理清楚。这是毕业设计中最能体现工程思维的地方也是最容易被功能堆砌掩盖的地方。技术应用方面Spring Boot 本身没什么新意但你在项目里是否用到了缓存、是否做了全局异常处理、是否自定义了拦截器做权限控制、是否把SQL语句做了合理优化这些都是可以展开讲的内容。不要只顾着堆 CRUD 代码务必留下几个可以讲亮点的技术设计。2. 技术选型背后的取舍为什么是这套组合Spring Boot 房屋租赁题目的技术栈目前的主流组合是Spring Boot 2.x MyBatis Plus MySQL Redis Vue (或 Thymeleaf)。这套组合不是随便选的每个组件都有它在这个业务场景下不可替代的理由。2.1 基础框架Spring Boot 应该选哪个版本先说版本选择题。Spring Boot 目前市面上三个主流大版本2.1、2.6、2.7以及新出的 3.x。对毕业设计这个场景我的推荐非常明确除非老师有要求否则优先选 Spring Boot 2.7.xJDK 用 1.8。为什么不建议直接上 3.x因为 Spring Boot 3 基于 JDK 17底层是 Jakarta EE很多老教程、老开源项目、MyBatis Plus 的旧版本都不兼容遇到问题搜解决方案时你会发现自己陷进版本不兼容的泥潭。而 2.7 是 2.x 系列的最终版本稳定教程多第三方适配齐。至于 2.1太老了像springfox 3.0.0和 Spring Boot 2.6 那一波路径匹配策略的冲突问题在 2.1 里不是那么典型但它的依赖管理已经明显落后很多代码示例跑不起来。直接锁 2.7.18 就行。这里有一个非常容易踩的坑Spring Boot 2.6 之后默认的路径匹配策略从 AntPathMatcher 改成了 PathPatternParser导致 springfox 2.9.2 这类老版本 Swagger 启动直接报Failed to start bean documentationPluginsBootstrapper。如果你要集成 Swagger要么用 springfox 3.0.0 并配置spring.mvc.pathmatch.matching-strategyant_path_matcher要么干脆用 springdoc-openapi。我在项目里用的后者省心很多。这个细节论文里提一句老师会认为你不是死搬代码。2.2 ORM 与数据库方案ORM 层面我强烈推荐MyBatis Plus 而不是原生 MyBatis 或 Spring Data JPA。原因有三第一MP 的单表 CRUD 不需要写 XML内置IService、BaseMapper足够覆盖用户、房源、订单这些实体的基础操作开发效率高第二MP 的条件构造器LambdaQueryWrapper在做房源多条件筛选区域、价格区间、户型、是否可短租时非常顺手代码可读性远好于拼接字符串 SQL第三MP 的分页插件对 MySQL 的分页处理非常友好毕业论文里写基于 MyBatis Plus 的分页查询优化也算一个可写点。数据库建议直接使用MySQL 5.7 或 8.0字符集utf8mb4引擎 InnoDB。房源表、订单表一定要建好索引特别是对房源表的area、rent_price、status三个字段做联合索引对订单表的landlord_id、tenant_id建普通索引。这个题目的数据量不大但建索引的意识代表你懂性能设计答辩时值得主动提。连数据库连接池Spring Boot 2.x 默认用 HikariCP不需要换。有一点要注意HikariCP 的max-lifetime默认是 1800000 毫秒30分钟connection-timeout默认 30000 毫秒。如果数据库端或云数据库配置了 wait_timeout连接池里的连接可能被服务端断开凌晨跑定时任务时偶发Connection is not available, request timed out after 30000ms。解决办法是在配置里显式设置spring: datasource: hikari: maximum-pool-size: 10 minimum-idle: 5 connection-timeout: 30000 idle-timeout: 600000 max-lifetime: 18000002.3 Redis 缓存和分布式会话Redis 在这个项目中不是必选但加上去会让项目明显加分。我用 Redis 做了两件事房源详情缓存和验证码临时存储。房源详情页是典型的读多写少场景尤其被搜索和推荐后同一个房源在一段时间内会被反复访问。用 Redis 做缓存key 设计为house:detail:{id}value 用 JSON 字符串查询时先读缓存未命中再查数据库并回填。要注意的是房源信息一旦被修改必须主动删除对应缓存否则用户看到的是旧数据。这个逻辑在房东端编辑房源信息的接口里调用redisTemplate.delete(house:detail: id)即可。短信验证码或纯验证码适合用 Redis 的原因是设置了setex过期时间天然解决验证码有效期控制问题。key 设计为captcha:{phone}value 存验证码TTL 5 分钟校验成功后立即删除避免同一个验证码被反复使用。这个设计在论文里也能写出一个小节体现的是数据过期策略的工程意识。3. 六张核心表搞定主业务流程表设计和接口边界很多同学设计表的时候喜欢一张表塞几十个字段看起来功能都在实际上耦合得一塌糊涂。房屋租赁系统我最推荐先做六张核心表把主业务流程跑通再根据细节需求加扩展表。3.1 核心实体与表关系第一张是user用户表字段包括id, username, password, phone, real_name, id_card, avatar, role, status, create_time。注意role用int0表示普通用户1表示房东2表示管理员。为什么不单建角色表因为这个系统的角色是固定的没有动态权限配置需求一个字段足够。第二张是house房源表字段比较密集id, landlord_id, title, cover_image, images, area, address, community_name, house_type, floor, total_floor, area_size, rent_price, rent_type, supporting_facilities, description, status, view_count, create_time, update_time。landlord_id关联user.idimages用 JSON 字符串存储多张图片路径rent_type区分整租/合租status用0待审核、1已上架、2已下架、3已出租四个值。第三张是rental_order租赁订单表id, order_no, house_id, landlord_id, tenant_id, apply_time, visit_time, order_status, sign_time, start_time, end_time, rent_price, deposit, contract_url, create_time, update_time。order_status是整个系统的核心状态机0待房东处理、1待签约、2已签约、3已入住、4已退租、5已拒绝、6已取消。第四张是favorite收藏表第五张是notice公告表第六张是feedback反馈表。这六张表基本覆盖主链路。表关系上特别提醒一点房源表和订单表里同时冗余了房东ID也就是house表有landlord_idrental_order表也有landlord_id。这不是冗余而是查询效率考虑。订单列表页需要频繁按房东ID查询我收到的申请如果每次都要通过house_id - landlord_id二次关联查询会很绕。直接在订单表冗余房东ID查询rental_order WHERE landlord_id 当前用户即可。这种以查询为中心的冗余设计在论文中值得说明。3.2 接口路径设计与权限控制接口路径建议按角色模块化组织。用户端接口以/api/user开头如/api/user/houses/search、/api/user/favorites、/api/user/orders房东端接口以/api/landlord开头如/api/landlord/houses、/api/landlord/houses/{id}/approve管理端接口以/api/admin开头如/api/admin/houses/audit、/api/admin/users。权限控制我不建议引入 Spring Security因为毕业设计引入它会增加大量配置和理解成本而且容易暴露安全漏洞。更实在的做法是用拦截器 注解做一个轻量级权限控制登录时把用户ID和角色写入 Session 或 Redis自定义AuthInterceptor校验未登录请求再配合自定义注解RequireRole(value landlord)去做角色级控制。这样代码量小逻辑清晰答辩时也能把原理讲明白。一个具体场景房东想查看他收到的申请列表接口/api/landlord/orders需要在拦截器放行后从 session 中取userId并把订单表中的landlord_id等于这个userId作为查询条件。这里的关键是前端传入的任何 ID 都不能直接作为数据归属的判断依据必须从服务端会话取当前登录者 ID否则换个参数就能看到别人的订单这是安全教育里经常讲的水平越权问题。毕业设计代码里能体现这个意识是很加分的。4. 把热搜里的几个坑提前拆解字段加密、AJAX数据回传、WebSocket推送、SQL超时热搜词里有几个非常典型的实战问题跟 Spring Boot 房屋租赁系统高度相关。这些不是我编的而是社区里反复出现的求助热点。我逐个拆开讲每个都附上我实际用过的解决方案。4.1 MyBatis 字段级加密后怎么做查询这个问题的典型场景是用户表中的手机号、身份证号需要加密存储防止数据库泄露导致敏感信息暴露。很多人用 MyBatis 的TypeHandler做字段加密写入时加密、查询时解密这是对的。但问题来了——加密后的数据是密文如果业务中需要按手机号精确查找用户比如登录、后台搜索WHERE phone 13800138000永远查不到因为数据库里存的是密文。我的方案是增加一个明文冗余字段的做法要慎用因为它同样泄密。更合理的做法是对需要精确查询的字段采用确定性加密算法。比如 AES 在固定 key 和固定 IV 下同一个明文加密结果相同这样就可以在查询时先用同样的算法把入参加密成密文再去数据库匹配。这样的查询虽然无法走常规索引除非你对密文做哈希索引但在数据量不大的毕业设计里完全够用。具体实现上我在项目里定义了一个EncryptTypeHandlerMappedTypes(String.class) public class EncryptTypeHandler extends BaseTypeHandlerString { private static final String AES_KEY your-16-bytes-key; Override public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException { ps.setString(i, EncryptUtil.encrypt(parameter)); } Override public String getNullableResult(ResultSet rs, String columnName) throws SQLException { String value rs.getString(columnName); return value null ? null : EncryptUtil.decrypt(value); } // 其余两个重载方法略 }然后在实体类的敏感字段上标注TableField(typeHandler EncryptTypeHandler.class) private String phone;精确查询时不要用 lambda 条件直接传明文而是先加密String encryptedPhone EncryptUtil.encrypt(phone); LambdaQueryWrapperUser wrapper new LambdaQueryWrapper(); wrapper.eq(User::getPhone, encryptedPhone);这里有个绕不开的问题此时查出来的对象MyBatis 会自动把密文解密成明文所以返回给前端时不需要额外的解密逻辑。需要考虑的是数据库中明文和密文混存比如历史数据没处理会导致查询不一致所以上线前要写一个一次性脚本把所有历史数据刷成密文。这个细节我在开发时忽略了差点导致线上查询失败写代码时一定留个心眼。4.2 后台已取得数据但 AJAX 拿不到响应的问题这个热词是Spring Boot 无法通过 ajax 的参数后台已取得数据返到前端。典型表现是后端接口在控制台打印的时候数据明明有值但前端 Ajax 拿到的 response 却是空的、404 或者完全没有回调。排查这类问题我的经验是先把后端返回的实际状态和结构打出来不要只盯着数据存在。大概率是以下几类原因。第一类接口返回了void或者没有ResponseBody。Spring Boot 中如果 Controller 方法返回String且方法没有加ResponseBody或者类上没有RestControllerSpring MVC 会把这个字符串当成视图名称去解析结果浏览器收到的是 404 或空白页面。解决办法是把 Controller 类统一标注RestController或者方法上加ResponseBody。如果你用的是Controller 模板引擎混用的项目最容易踩这个坑。第二类ajax 请求类型和后端不匹配。前端用$.ajax({ type: POST, data: {...} })提交表单格式数据后端用RequestBody User接参Spring 会直接报HttpMediaTypeNotSupportedException或HttpMessageNotReadableException但如果你在全局异常处理里悄悄吞掉了异常并返回空对象前端就会傻眼。记住一个原则前端表单格式用RequestParam或 VO 对象接前端 JSON 格式用RequestBody接不要混用。第三类也是最多人问的一类异步请求里拿 response 时没处理好生命周期。比如在success回调里调用了一个依赖外部变量的方法结果数据没回来之前变量已经变了或者跨域请求在 Spring Boot 端没有配置CorsFilter浏览器拦截了响应控制台看不到报错——需要打开浏览器的 Network 面板看请求状态如果是 CORS error 就明确加一个全局跨域配置Configuration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/**) .allowedOriginPatterns(*) .allowedMethods(GET, POST, PUT, DELETE, OPTIONS) .allowCredentials(true) .maxAge(3600); } }这个配置毕业后做前后端分离项目也会一直用到建议直接抄。4.3 Spring Boot 集成 WebSocket 推送租房状态消息房屋租赁系统里有一个非常合适的 WebSocket 应用场景用户提交看房申请或租赁订单后实时推送给房东。传统的做法是房东端定时轮询接口体验差而且浪费资源。用 WebSocket 让后端主动推送是项目的技术亮点。在 Spring Boot 2.x 中集成 WebSocket 不算复杂。首先引入依赖dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-websocket/artifactId /dependency然后写一个配置类注册ServerEndpointExporter再写一个端点类Component ServerEndpoint(/ws/notify/{userId}) Slf4j public class NotifyWebSocketServer { private static ConcurrentHashMapString, Session sessionMap new ConcurrentHashMap(); OnOpen public void onOpen(Session session, PathParam(userId) String userId) { sessionMap.put(userId, session); log.info(用户 {} 建立连接, userId); } OnClose public void onClose(PathParam(userId) String userId) { sessionMap.remove(userId); } public static void sendToUser(String userId, String message) { Session session sessionMap.get(userId); if (session ! null session.isOpen()) { try { session.getBasicRemote().sendText(message); } catch (IOException e) { log.error(推送消息失败, e); } } } }在订单状态变更的业务代码里比如用户提交了申请就调用NotifyWebSocketServer.sendToUser(landlordId, 您有新的看房申请)。房东端的前端页面在onload时建立 WebSocket 连接监听推送消息弹出一个新订单通知即可。这里我要特别提醒几个坑第一ServerEndpoint是单例模式但 WebSocket 多例所以不能用Autowired注入其他 Spring Bean需要用ApplicationContext静态持有或者通过Autowired 静态方法中转的方式解决。**第二**Nginx 代理 WebSocket 需要单独配置Upgrade和Connection头否则浏览器连接一直在握手中。**第三**本地测试时如果用了server.servlet.context-path比如/apiWebSocket 路径也要带上这个前缀否则连不上。4.4 关于SQL 执行 10 秒自动关闭的真相热搜词里有一条jvm 或者 spring boot 会设置一个 sql 执行 10 秒自动关闭吗。这个问题看起来像谣言但背后确实有相关机制。首先要给一个明确回答Spring Boot 默认不会自动关闭执行超过 10 秒的 SQL。HikariCP 的connection-timeout是获取连接的超时时间跟 SQL 执行时间不是一回事MySQL 的wait_timeout是连接空闲超时时间也不是单条 SQL 执行超时。但是如果你的房子和数据库之间有代理层比如使用了某些云数据库的 JDBC 代理或者框架里配置了Spring 的事务超时时间那确实可能存在超时关闭的假象。比如Transactional(timeout 10)设置了事务超时 10 秒如果事务内有一条慢 SQL 超过了这个时间Spring 会抛出TransactionTimedOutException看起来就是 SQL 执行 10 秒后被强制关闭了。还有一种常见原因数据库连接被 Nginx 或网络层断开了。MySQL 的interactive_timeout和wait_timeout默认是 28800 秒8小时但很多云数据库会自动缩到很短。如果连接池里的连接长期不用数据库会先断开连接池不知道下一次查询时拿到的是坏连接报错信息可能包含Communications link failure或者Connection is not available。这也会被错误理解成SQL 执行超时被杀。所以排查这类问题的正确姿势是先看数据库慢查询日志slow_query_log确认是否真的执行了超过 10 秒再检查连接池配置max-lifetime和数据库wait_timeout的匹配情况最后看事务注解上是否误加了timeout属性。毕业设计里如果遇到偶发的查询很慢然后报错80% 是慢 SQL 或者连接失效而不是 Spring Boot 做了超时关闭。这个认知在答辩里被问到你的系统为什么稳定时说出来会很加分。5. 按时间倒排的课题开发计划从零到可演示项目很多同学做毕业设计不是被技术难倒的而是被节奏拖垮的。三月份选题四月份不慌五月份开始熬夜六月份手忙脚乱。如果你已经决定做 Spring Boot 房屋租赁信息系统我建议按下面的时间倒排安排开发。5.1 第一周搭环境和跑通核心模块第一周的目标不是做功能而是让项目能启动、能登录、能连上数据库。具体要做三件事用 Spring Initializr 生成 Spring Boot 2.7 项目引入 MyBatis Plus、MySQL、Redis、Lombok、Spring Web 依赖创建数据库和六张核心表实现用户注册、登录、获取用户信息三个接口并用 Swagger 或 Postman 验证通过。别急着写业务代码先用一个/api/user/register接口把登录链路打通包括前端页面的登录窗口能拿到 token 或者 session。这一步走通后面所有功能都在这个骨架上加。5.2 中期真实房源 Demo 数据和联调第二个阶段是功能爆发期建议按这个顺序推进先做房源模块发布、列表、详情、搜索筛选再做收藏模块然后做订单流程用户提交申请、房东处理、双方确认签约最后做管理后台房源审核、用户管理。整个阶段的核心不是写多少接口而是把业务流程调通特别是订单状态从提交到退租的完整流转。联调时一定要准备一套真实的房源演示数据至少 15 套房源分布在不同的区域、价格段和户型图片可以到免费图库下载。演示数据越真实答辩时越有说服力。我见过有人用 test1test2 当房源标题一打开演示界面老师眉头就皱起来了。5.3 收尾演示脚本、性能自测和论文素材最后一周不要写新功能而是做三件收尾工作。第一写一份演示脚本把用户注册 - 搜索房源 - 收藏 - 提交申请 - 房东端收到消息 - 房东处理 - 用户签约 - 管理员审核房源这条完整链路走一遍每一步记下操作路径和预期结果。第二用 Jmeter 或者 Postman 对房源列表接口做一次简单的并发测试50 个线程并发请求既能提前暴露慢 SQL又能在论文里写一句基于 Jmeter 的简单性能测试表明接口平均响应时间低于 200ms。第三整理论文素材表结构截图、核心接口的时序图、Redis 缓存设计图、WebSocket 推送流程图、遇到的问题和解决方案清单。这些素材在你写论文时会帮你省下大量回看代码的时间。6. 写在最后调试和答辩环节的点滴体会做这个项目的过程里我最大的体会是这个题目真正考验的不是你会不会用 Spring Boot而是你会不会把混乱的现实业务抽象成清晰的数据结构和状态流。房源、订单、用户、角色、权限、缓存、消息推送每一个点单独拿出来都不难但把它们组合成一个能自洽运行的系统需要的是先想清楚再动手的耐心。分享几个具体建议。第一所有状态字段都要在前端显示为中文标签而不是直接显示数字。0、1、2 在数据库里很清晰但演示给老师看的时候界面上全是 0、1、2 会显得很业余。用枚举或字典表做映射前端展示待审核已上架。第二多打印日志。在房源上下架、订单状态变更这类关键操作上用 Logger 记录谁在什么时间对哪条数据做了什么操作答辩时你可以调出日志证明系统行为符合预期。这个细节很能体现工程素养。第三准备几个能主动展示的亮点比如 Redis 缓存命中率的自测结果、WebSocket 推送实时通知的现场演示、字段加密后数据表里手机号确实是密文的截图。这些不是老师重点检查的项但主动展示会让人眼前一亮。最后想说的是毕业设计的核心目标不是做出一个完美无缺的商业系统而是通过一个完整项目证明你具备需求分析 - 系统设计 - 编码实现 - 测试验证的完整工程能力。Spring Boot 房屋租赁信息系统这个题目给了你一个很好的舞台。把它做深把每个技术决策背后的为什么想清楚答辩时你就不会再手足无措。我当初在这个项目上踩过的那些坑希望你能直接绕过。
返回列表