ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Spring Boot房屋租赁管理系统:从设计到答辩的完整实战指南

Spring Boot房屋租赁管理系统:从设计到答辩的完整实战指南 1. 选题价值与整体设计思路为什么房屋租赁系统是毕业设计的“黄金选题”每年到了毕业设计季总有同学在选题上纠结半天。选电商系统烂大街了。选管理系统似乎太简单。选算法研究又怕写不完。我通常的建议是Spring Boot房屋租赁管理系统这个题目的含金量被很多人低估了。细看这套系统的需求——用户角色有租客和管理员核心业务有房源管理、租赁合同、账单水电、报修处理还牵扯到登录认证、权限区分、数据可视化。这些功能点拆开来看几乎覆盖了Java Web开发中80%的常用技能Spring Boot的自动配置、Spring Data JPA或MyBatis的数据访问、RESTful接口设计、前端页面的增删改查、甚至会话管理和权限拦截。做完这个项目你基本就把Java后端开发的主流技术栈完整过了一遍。更重要的是房屋租赁这个场景本身具备真实的业务复杂度。租客要浏览房源、提交看房申请、在线签约、查看账单、发起报修管理员要管理房源上下架、审核租赁申请、生成账单、处理报修工单、汇总经营数据。这种双向角色加多业务流程的设定正好能在毕业设计中体现“系统设计能力”不会像单表CRUD那样显得单薄也不会像高并发秒杀那样超出本科生范围。从答辩的角度来看这个题目也很好讲故事。你可以从“传统租房信息不透明、管理效率低”这个痛点切入引出系统的设计目标和功能规划。面试官或答辩老师问“为什么这样设计”你有需求驱动力问“表结构为什么这样建”你有业务流程做支撑问“技术选型为什么选Spring Boot”你能说出生态成熟、社区活跃、配置简化这些理由。这套思路本身就是拿高分的底子。我特别想强调一点选这个题目不要只把它当成一个“交差用的系统”。房屋租赁管理系统的核心逻辑——合同状态流转、费用结算周期、租客与房源的关联关系——和很多真实商业系统的设计是相通的。毕业后如果从事企业级应用开发你会发现这类“状态机计费角色权限”的组合非常常见。把这套系统的设计逻辑吃透比写十个简单的增删改查都有用。2. 技术选型与项目初始化Spring Boot版本、依赖组合和环境准备2.1 技术栈选择的底层逻辑拿到一个毕设项目第一步不是急着敲代码而是先想明白技术栈怎么选。Spring Boot能成为Java后端开发事实标准是有原因的它把大量的样板配置变成了约定和自动装配让开发者能把精力集中在业务逻辑上。这种“约定优于配置”的思路对于需要快速产出、又要掌握核心原理的毕业设计来说再合适不过了。这套房屋租赁系统的主流技术组合通常是后端框架Spring Boot 2.7.x 或 3.x根据JDK版本决定持久层框架MyBatis Plus 或 Spring Data JPA推荐前者写复杂查询更灵活数据库MySQL 5.7 或 8.0前端模板Thymeleaf前后端不分离或 Vue Element UI前后端分离认证方案Spring Security 或拦截器 Session / JWT如果你做的是纯后端源码很多同学会选择Spring Boot MyBatis Plus Thymeleaf这套组合原因很实在MyBatis Plus的单表操作完全不需要写SQL复杂多表查询可以手写XML对新手非常友好Thymeleaf可以直接在HTML里渲染后端数据不用额外搭前端工程部署就是一个Jar包省掉一堆跨域和打包的麻烦。2.2 版本兼容性预判我在实际项目里最常遇到的问题是Spring Boot版本和JDK版本不匹配。这几乎是毕设阶段翻车率最高的一关没有之一。这里有一个关键的版本对应关系需要记住Spring Boot版本要求的JDK版本对应的Java特性2.7.xJDK 8 ~ JDK 20Java 8语法为主兼容性最好3.0.xJDK 17必须使用JDK 17及以上3.2.xJDK 17官方推荐JDK 17或21如果你的电脑装的是JDK 8直接上一个Spring Boot 3.2的依赖启动时大概率报UnsupportedClassVersionError。反过来如果电脑是JDK 17强上Spring Boot 2.4虽然能跑通但因为版本太老很多新语法和新特性用不了属实没必要。个人建议是本地如果已经装了JDK 8就选Spring Boot 2.7.x它目前仍然是网上教程最多、报错资料最全的版本。如果你愿意为了这个项目升级到JDK 17直接上Spring Boot 3.2.x也没问题只是遇到报错时搜索到的解决方案要以官方文档和较新的博客为准。2.3 Maven/Gradle依赖的坑项目初始化大部分用的是Spring Initializr生成的Maven工程。我看到很多同学因为在IDEA里创建项目时勾选了太多依赖导致启都启动不起来。这里提醒一下毕业设计阶段的依赖精简化比什么都重要。房屋租赁系统真正需要的核心依赖就这几类!-- Web场景启动器 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- Thymeleaf模板引擎 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-thymeleaf/artifactId /dependency !-- MyBatis Plus -- dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.3/version /dependency !-- MySQL驱动 -- dependency groupIdcom.mysql/groupId artifactIdmysql-connector-j/artifactId scoperuntime/scope /dependency !-- Lombok -- dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependencyLombok这个依赖一定要加上它通过注解帮我们自动生成getter、setter、构造函数这些样板代码实体类看起来干净很多。不过这里有个隐藏问题——部分学生用的是IDEA社区版或者没有安装Lombok插件编译时就会报找不到方法。如果你决定不依赖Lombok那就老老实实手写getter和setter或者用IDEA的Generate功能批量生成一样可以。2.4 项目结构设计拿到一个结构混乱的源码改起来非常痛苦。我习惯把Spring Boot工程按照下面这种方式分包com.example.rental ├── config // 配置类拦截器、跨域、MyBatisPlus分页插件 ├── controller // 控制层接收请求、参数校验、返回结果 ├── service // 业务层核心逻辑、事务管理 │ └── impl // 业务实现类 ├── mapper // 数据访问层MyBatis接口或JPA Repository ├── entity // 实体类对应数据库表 ├── dto // 数据传输对象接收前端参数、返回封装数据 ├── common // 常量、统一返回结果、自定义异常、全局异常处理器 └── utils // 工具类日期处理、文件上传等这个分层的思路把代码责任划分得清清楚楚。Controller只做参数接收和结果返回Service写业务规则Mapper只碰数据库。答辩时老师问“你的代码结构是怎样的”你把这个分层结构讲出来配合“高内聚低耦合”的设计原则用两分钟就能让对方明白你不是代码堆积而是有架构意识的。系统初始化阶段还有一件事要做在application.yml里配置数据源和日志级别。很多同学下载源码后第一步跑不起来大概率是配置文件里的数据库账号密码和本地不一致。我一般把日志级别在开发环境调到DEBUG方便排查SQL问题上线或演示时再调回INFO。3. 数据建模与核心表设计关系梳理和数据字典规划3.1 需求分析先行房屋租赁管理系统首先不是技术问题而是理解业务的问题。你需要先画出一张角色和业务线的关系图在脑子里把整个系统的语言模型建立起来。这个系统涉及的主体有管理员、租客、房源、租赁合同、账单、报修工单。核心业务链可以概括成一句话租客浏览房源、申请租房管理员维护房源信息并处理租赁申请双方达成意向后生成租赁合同合同生效后按周期产生水电和租金账单租客缴费使用过程中出现问题可以提交报修管理员处理并反馈。数据建模就是围绕这条业务链展开的。如果这一环节没想清楚就急着建表后面写代码时就会反复改表结构、改实体类导致项目越写越乱。3.2 核心表结构规划基于上面的业务分析这套系统最少需要这几张表用户表t_userid主键自增username用户名唯一索引password加密存储phone手机号avatar头像地址role角色标识ADMIN / USERstatus账号状态启用/禁用create_time、update_time房源表t_houseid主键title房源标题description房源描述address详细地址area面积price月租金bedroom、living_room、bathroom户型信息status房源状态0 待审核 / 1 已上架 / 2 已出租 / 3 下架landlord_id关联用户表中的房东或管理员cover_image封面图create_time租赁合同表t_contractid主键contract_no合同编号唯一house_id关联房源表user_id关联租客start_date合同开始日期end_date合同结束日期monthly_rent约定月租金deposit押金status合同状态0 待签署 / 1 生效中 / 2 已到期 / 3 已解约signed_time签署时间create_time账单表t_billid主键contract_id关联合同bill_type账单类型租金 / 水费 / 电费 / 违约金amount金额start_date、end_date账期status支付状态0 待支付 / 1 已支付 / 2 已逾期create_time、pay_time报修工单表t_repairid主键house_id关联房源user_id报修人description问题描述status处理状态0 待处理 / 1 处理中 / 2 已完成 / 3 已驳回create_time、finish_time这几张表之间的外键关系非常简单合同表关联房源和用户账单表关联合同报修表关联房源和用户。不需要在数据库层面做强外键约束通过业务代码维护逻辑关联即可这样可以避免后续删除数据时遇到外键冲突的问题。3.3 字段设计的细节思考字段设计藏着很多容易忽略的经验。比如金额字段一定用decimal(10,2)而不是float或double浮点数在计算时会有精度损失租金算得不对这在业务上是不可接受的。比如时间字段MyBatisPlus的自动填充功能需要配合TableField(fill FieldFill.INSERT)注解实现如果不做这一步每次插入数据都要手动set创建时间非常繁琐也容易漏。再比如状态字段我给每一个状态都加了注释和默认值例如status TINYINT DEFAULT 0 COMMENT 0待审核 1已上架 2已出租 3下架。善用注释后期维护或者答辩时讲解表结构一目了然。还有一种常见的做法是把房源的配套设施信息用JSON字符串存到一个字段里比如features: {wifi: true, parking: false, elevator: true}。这个方案比建一张配套关联表方便得多查询时只要包含该字段即可。但要注意JSON字段没法在数据库层做精细查询如果后期需要按照“有停车位”筛选房源查询逻辑就会复杂一点。毕设阶段用JSON来存非核心的展示型数据问题不大。4. 核心业务流程与关键代码实现从登录到租赁闭环4.1 统一返回结果与全局异常处理一个设计良好的后端系统接口返回的数据格式应该是统一的。我在common包里定了Result类来封装接口返回包含三个核心信息状态码code、提示消息msg、业务数据data。所有Controller在接口返回时都包装成这个对象前端接数据时只需要解析一种结构即可。Data public class ResultT { private Integer code; private String msg; private T data; public static T ResultT success(T data) { ResultT result new Result(); result.setCode(200); result.setMsg(操作成功); result.setData(data); return result; } public static T ResultT error(String msg) { ResultT result new Result(); result.setCode(500); result.setMsg(msg); return result; } }有统一返回结构还不够还要做全局异常处理器。用RestControllerAdvice注解定义一个类捕获业务自定义异常、参数校验异常和兜底的Exception异常。加上这个之后接口在任何环节抛异常都不会返回乱七八糟的错误页面或错误格式而是自动包装成统一结构的错误信息。这一步在答辩时非常加分因为很多人根本不会做全局异常处理业务代码里到处是try-catch看起来极其凌乱。参数校验方面现在Spring Boot已经支持ValidatedNotBlank这类校验注解。比如新增房源时标题、面积、价格这些都是必填字段直接在DTO上标注即可省去了一堆手写if判断。4.2 登录认证与权限控制方案登录功能是每个管理系统都绕不开的部分。毕设阶段很多同学会选择最简单的方式登录时查询用户表比对密码成功后在Session里存一个用户对象。这种方式实现容易但存在明显的安全问题密码明文存储、Session固定攻击、无权限区分都会成为答辩追问点。我在这个系统里做了两个关键升级密码加盐加密存储和基于拦截器的角色权限控制。密码加密推荐使用BCrypt算法Spring Security框架内置了它的实现不需要把整个Spring Security引进来单独使用BCryptPasswordEncoder这个类就行。// 注册时加密存储密码 BCryptPasswordEncoder encoder new BCryptPasswordEncoder(); String encodePassword encoder.encode(rawPassword); user.setPassword(encodePassword); // 登录时校验密码 boolean isMatch encoder.matches(inputPassword, user.getPassword());权限控制使用HandlerInterceptor拦截器实现。自定义一个AuthInterceptor在进入Controller前检查当前Session中是否有登录用户同时根据访问路径的前缀判断接口的权限要求——/admin/**开头的路径仅管理员可访问/user/**开头的路径普通用户登录后可访问/public/**不需要登录。实现了这一个拦截器整个系统的权限体系就成型了。这里有个操作细节拦截器配置类要实现WebMvcConfigurer接口来注册拦截器同时需要设置excludePathPatterns放行的路径比如/user/login、/house/list、/house/detail这些。不然登录接口被拦掉整个系统就没法正常登录了。这种低级错误我一看到源码就头疼开发时一定要先理清哪些接口需要放行。4.3 房源管理与租赁合同的核心流程房源模块的代码相对直接就是标准的增删改查加条件查询。但几个核心细节值得展开说明尤其是状态流转和多条件组合查询这两个点。房源状态的更新逻辑要封装在Service层而不能直接让Controller去修改状态字段。比如审核通过的逻辑——检查当前状态是否为待审核如果已经是已上架状态再执行审核就会产生状态冲突。用状态机思维去写代码边界会清晰很多演示时每操作一步状态变化都在掌控之中。租赁合同是这个系统里最能体现业务复杂度的地方。合同从创建到生效涉及两个核心方法创建合同和确认签署。创建合同时要校验房源当前状态是已上架才能发起签署时要校验合同状态是待签署。签署完成后要同时把房源状态改成已出租避免同一套房被重复租赁。Transactional public void signContract(Long contractId) { Contract contract contractMapper.selectById(contractId); if (contract null) { throw new BizException(合同不存在); } if (contract.getStatus() ! ContractStatus.PENDING) { throw new BizException(当前状态不允许签署); } // 更新合同状态 contract.setStatus(ContractStatus.ACTIVE); contract.setSignedTime(new Date()); contractMapper.updateById(contract); // 同步更新房源状态 House house houseMapper.selectById(contract.getHouseId()); house.setStatus(HouseStatus.RENTED); houseMapper.updateById(house); }注意这个方法上的Transactional注解——签署合同涉及合同表和房源表两张表的更新任何一个步骤失败都要回滚否则数据会不一致。事务控制是面试和答辩必问的知识点把它放在这个真实的业务场景里讲比背一万字理论都有说服力。4.4 账单生成的定时任务实现账单模块很有意思它引入了定时任务这个进阶技术点。租金和水电费不需要管理员手动创建系统可以按照合同周期自动生成待支付的账单。用Spring Boot自带的Scheduled注解就能实现一个轻量的定时任务。在配置类上开启定时任务开关EnableScheduling。然后写一个定时任务类例如每天早上8点扫描所有状态为生效中的合同检查当前日期是否到了新的账期如果到了就生成一张当月的租金账单和水电账单。这样设计的好处是账单一出租客端“我的账单”就会自动展示待支付项管理员也不用每天盯着系统。这个功能虽然是锦上添花但在答辩演示时直接说“系统支持自动按月生成租金账单”效果比手工创建账单好太多。不过毕设阶段有几项复杂的账单业务可以考虑适当简化。比如水电费通常是先抄表再计费本系统可以做一个简化版本——管理员后台录入本月水电表读数系统根据“本月读数 - 上月读数”自动算出费用退租时的押金退还逻辑、逾期违约金的阶梯计算这些可以作为可选项加入。把主流程做完、保证稳定运行再去扩展这些边缘功能节奏感很重要。5. 前端页面与交互设计让源码真正“能看又能用”5.1 技术选型平衡毕设阶段前端部分两种做法比较主流传统后端模板渲染和前后端分离开发。前后端分离用Vue写出来的界面确实更炫酷简历上也好写。但如果你本身前端基础薄弱折腾Vue脚手架、跨域问题、路由守卫这些环节消耗的时间可能比后端整个系统都多。我的建议是看你的时间预算。如果离答辩还有一个月以上用Vue Element UI做一个管理后台配合ECharts做数据可视化整体档次会明显不同。如果只剩一两周安心用Thymeleaf开发围绕固定模板尽量把页面设计得干净统一也完全够用毕竟毕业设计核心考核的是系统功能是否完整、逻辑是否闭环。5.2 用户端的核心页面用户端租客视角的核心页面是房源列表页、房源详情页、个人信息页。用户方便性优先要把房源检索信息做到位。房源列表页的关键点在于多条件组合筛选。前端页面上有搜索框按小区或标题模糊搜索、价格区间下拉、面积筛选、排序方式。后端用一个自定义的查询对象HouseQueryDTO接收这些参数在Service层构建查询条件拼装到MyBatis的QueryWrapper里public IPageHouse queryHousePage(HouseQueryDTO query) { PageHouse page new Page(query.getPageNum(), query.getPageSize()); LambdaQueryWrapperHouse wrapper new LambdaQueryWrapper(); // 标题模糊查询 if (StringUtils.hasText(query.getKeyword())) { wrapper.like(House::getTitle, query.getKeyword()); } // 价格区间筛选 if (query.getMinPrice() ! null) { wrapper.ge(House::getPrice, query.getMinPrice()); } if (query.getMaxPrice() ! null) { wrapper.le(House::getPrice, query.getMaxPrice()); } // 状态过滤只能看到已上架房源 wrapper.eq(House::getStatus, HouseStatus.ON_SHELF); // 按发布时间最新排序 wrapper.orderByDesc(House::getCreateTime); return houseMapper.selectPage(page, wrapper); }这套查询逻辑的厉害之处在于搜索条件可以任意组合查询条件为空也能正常分页显示全部房源基本覆盖了真实场景。房源详情页展示的信息包括图片、租金、面积、户型、描述、地址。用户可以在这个页面点击“立即租房”系统会判断用户是否已登录、该房源是否已出租然后创建租赁申请或合同草稿。5.3 管理后台的设计重点管理端的页面信息密度高通常采用侧边栏布局。左侧放导航菜单房源管理、合同管理、账单管理、报修管理、用户管理、数据统计右侧是内容区域。房源管理的列表页要支持上下架操作按钮状态发生变化时列表自动刷新。账单管理页面要支持按月筛选、按支付状态筛选管理员要能查看每一笔账的明细。报修管理页面按未处理优先排序处理完成后修改状态并填写反馈说明。数据可视化部分算是加分项。每月新签合同数、已出租房源占比、租金收入趋势这三类数据用ECharts画成柱状图、饼图和折线图放在管理后台首页。前端在页面加载时向后端请求统计接口后端用一条SQL聚合数据返回总共写不了多少代码但整个系统的演示效果立刻不一样。6. 部署与联调实战本地跑通与上线展示指南6.1 本地环境准备源码到手后第一步是把环境准备好。必备的软件有IntelliJ IDEA开发工具、MySQL 5.7或8.0数据库、Navicat或DBeaver数据库可视化工具、Maven 3.6构建工具、JDK 8或17跟随Spring Boot版本。这些环境有任何一个是“绿色版”或“精简版”都可能引出一堆诡异报错建议统一安装官方原版并配置好环境变量。数据库这块大多数人用Navicat导入SQL文件。成功导入的前提是SQL文件的字符集和本机MySQL字符集一致否则会出现中文乱码。只要在导入时选定UTF-8创建数据库时也指定CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci大部分乱码问题都能避免。6.2 配置文件的修改重点拿到Spring Boot源码后几乎所有环境信息都要改成你自己的。最核心的是数据源配置spring: datasource: url: jdbc:mysql://localhost:3306/house_rental?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/ShanghaiuseSSLfalseallowPublicKeyRetrievaltrue username: root password: 你的数据库密码 driver-class-name: com.mysql.cj.jdbc.Driver这里面有两个容易踩的坑。第一个是时区serverTimezoneAsia/Shanghai必须配置否则新版MySQL驱动会返回一个奇怪的时区错误导致应用启动直接失败。第二个是高版本MySQLMySQL 8.0的驱动类名已经从com.mysql.jdbc.Driver改成了com.mysql.cj.jdbc.Driver如果你在旧资料上看到的配置还是前者在MySQL 8下大概率会报加载驱动失败。检查一下MyBatis Plus的日志配置开发阶段建议打开SQL日志。在application.yml里加一行配置mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl有了它控制台会打印每一条实际执行的SQL语句和参数值。排查数据库相关bug时这个输出比任何断点调试都直观。上线演示前把这一行注释掉避免SQL信息暴露在日志中。6.3 启动与联调一切配置完成后运行主类带SpringBootApplication注解的那个类的main方法观察控制台日志。正常启动的日志末尾会出现Started Application in x.xx seconds这种字样随后访问http://localhost:8080就能看到系统首页。联调过程中要重点测试以下几个闭环场景用户注册 → 登录 → 查看房源列表 → 点击房源详情未登录用户尝试租赁时被拦截跳转到登录页管理员登录后台 → 新增房源 → 前台页面能看到该房源租客发起租赁申请 → 合同生成 → 合同签署 → 房源状态变为已出租定时任务到了账期自动生成账单 → 租客模拟支付 → 账单状态变为已支付租客提交报修工单 → 管理员后台看到工单 → 处理后租客端能看到结果任何一个环节断裂都要回到代码里排查。这个联调的过程本质上就是系统验收过程提前完成它答辩时演示就非常有信心。6.4 远程演示的部署思路如果答辩或演示需要把系统部署到服务器上最简单的方案是在一个Linux云主机上安装JDK和MySQL环境然后上传项目构建产物。mvn clean package -DskipTests打包成一个Jar包用nohup java -jar house-rental-0.0.1-SNAPSHOT.jar 启动就完事了。部署阶段要比本地多几个注意事项。MySQL数据库记得把账号密码改成强密码并限制为仅允许特定IP访问避免被扫到爆破。Jar包启动时用--server.port8080参数指定端口然后通过宝塔面板或nginx做一下反向代理和域名绑定。如果服务器没有公网IP还可以用内网穿透工具把本地项目转发到外网进行访问实现不用买服务器就能远程演示的效果。7. 高频报错与排查实录我从源码中走过的弯路7.1 Spring Boot版本太高引发的连锁问题“springboot版本太高”这个热词背后正是无数真实翻车现场的真实写照。项目的Spring Boot版本是3.2而电脑上安装了JDK 8的时候编译阶段就会失败或启动时直接报错。排查方法其实很简单启动后在日志中搜索Exception关键字看到Java.lang.UnsupportedClassVersionError这一类错误要么升级JDK到17要么把Spring Boot降级到2.7.x。我个人更建议毕设阶段保持简单直接换成2.7.x版的依赖因为网上涉及Spring Boot 2.x的教程和解答是最丰富的。还有Spring Boot 3.x虽然很新但它将javax命名空间改成了jakarta很多旧代码中import javax.servlet.*的语句放在Spring Boot 3.x下根本无法编译。如果你拿到的源码是2.x的包结构强行换到3.x会引发一长串“无法解析包名”的报错。7.2 你打开了宽带连接却连接不上数据库应用启动时报Cannot connect to MySQL或Communications link failure这类错误在联调阶段占比极高。通常有四个原因数据库服务本身没启动。MySQL服务平时是手动启动的如果开机后没有初始化服务应用就连不上端口不对。默认都是3306如果你改装过MySQL端口或者用了远程数据库要检查配置文件里的url端口是否匹配账号密码错误。项目配置文件里的密码和你本机MySQL root密码不一致权限问题。MySQL 8.0默认的root账号只允许localhost访问远程连接需要单独授权按这四条顺序排查95%以上连接问题都能解决。剩下一小半是因为本机之前装过多个版本的MySQL导致3306端口被旧版本的实例占用这时要看服务列表把非当前使用的MySQL服务停掉。7.3 接口返回500但控制台没有明显堆栈有时你写了一个接口前端调用正常返回了结果但过了一会发现控制台除了Basic日志什么都没打。这种情况大概率是全局异常处理器把异常捕获了但没打印堆栈信息。其实只需要在全局异常处理器里把异常信息输出到日志中ExceptionHandler(Exception.class) public ResultVoid handleException(Exception e) { log.error(系统异常, e); return Result.error(系统异常请稍后重试); }改动之后所有异常都会完整打印堆栈和行号定位问题从此变得轻松。顺手建议在开发阶段把全局异常处理器的兜底方法暂时只打日志不返回错误提示给前端这样前端报错时你能快速判断是前端问题还是后端问题到演示阶段再统一拦截成友好提示。7.4 MyBatis Plus映射文件与SQL的问题MyBatis Plus提供了很多内置方法但如果写了自定义的XML/注解SQL有几个常见坑值得单独说明com.baomidou.mybatisplus.core.exceptions.MybatisPlusException: Failed to process, please exclude the tableName or statementId通常是因为更新的字段为nullMyBatis Plus默认不会处理null值字段。如果业务需要把某个字段更新为null要在这个字段上加TableField(updateStrategy FieldStrategy.IGNORED)注解。自定义SQL返回的字段列和实体类属性对不上时XML或注解SQL中要写AS别名来对应驼峰命名。比如SELECT price AS monthly_rent FROM t_bill没有别名时MyBatis Plus无法完成自动映射查询结果就会一堆null。分页查询要配置分页插件。MyBatis Plus的selectPage方法如果不配置PaginationInnerInterceptor分页会失效查出来的是全量数据。在配置类中注册该拦截器后分页功能才真正生效。7.5 文件上传路径与静态资源访问做房源图片管理时会上传图片这也是毕设的常见题型。上传项目里如果直接把图片存到本地磁盘的某个路径House表的封面图字段存的是/upload/xxx.jpg前端页面用img src/upload/xxx.jpg展示。但Spring Boot默认不会把磁盘上的upload文件夹映射成可访问的静态资源路径所以图片很可能裂开。解决方案是写一个自定义配置类把本地目录映射为虚拟路径Configuration public class WebConfig implements WebMvcConfigurer { Value(${file.upload-dir}) private String uploadDir; Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler(/upload/**) .addResourceLocations(file: uploadDir /); } }配置类生效后上传到upload-dir目录的文件就可以通过网络访问。注意Windows路径和Linux路径的写法差异Windows下路径写D:/project/upload/Linux下写/data/upload/并且要确保目录有写权限。7.6 定时任务不执行的排查思路写了Scheduled注解但定时任务就是不触发大概率是漏了一个关键步骤——没有在启动类或配置类上添加EnableScheduling注解。Scheduled负责标记方法EnableScheduling负责开启定时任务扫描机制两者缺一不可。还有定期任务是单线程执行的默认情况下多个Scheduled任务会互相阻塞。如果系统同时配了账单生成任务和报表统计任务某个任务执行时间较长另一个就会排队等待。需要并发执行时给Scheduled方法配置Async注解同时在启动类上添加EnableAsync。7.7 常见报错速查表我整理了一份高频问题的排查参考表建议直接保存到项目笔记里备用报错现象可能原因排查方向启动时UnsupportedClassVersionErrorJDK版本低于Spring Boot要求统一JDK版本Cannot connect to MySQL数据库未启动/账号密码错误/端口不对按顺序查服务和网络页面中文乱码数据库字符集不是utf8mb4/连接串缺编码检查建表字符集和URL查询结果全是null字段映射失败/未起别名检查实体属性和SQL别名图片加载不出来静态资源映射未配置配置资源映射分页不生效没有配置分页插件注册PaginationInnerInterceptor定时任务不执行缺少EnableScheduling添加启动注解前端跨域请求被拒绝未配置CORS使用 CrossOrigin 或配置CorsFilter8. 答辩呈现与系统亮点打磨让毕业设计的价值被看见8.1 功能演示的顺序设计毕业答辩的时间通常只有5到10分钟你花了几个月做出来的系统不能把时间浪费在无意义的页面切换上。我建议按“痛点 → 角色 → 流程 → 亮点”四条线来设计演示脚本先用两句话说明传统租房管理的痛点信息不透明、合同纸质化、账单易纠纷再分别用管理员和租客两种身份登录系统。管理员这边演示新增房源 → 审核租客的租赁申请 → 签署合同 → 自动生成账单 → 处理报修工单 → 查看统计图表。租客这边演示注册/登录 → 条件搜索房源 → 查看详情 → 发起租赁申请 → 查看待支付账单 → 模拟支付 → 提交报修工单。整个流程走一遍系统的业务闭环就完整呈现了。中途不要切回代码或打开数据库答辩老师更关心产品能不能跑得通、界面逻辑是否顺畅。演示之前一定要做的事提前在数据库里插入一部分演示数据。房源至少五六套覆盖不同价格和户型账号准备一个管理员的、一个租客的密码统一写好账单准备几张不同状态的报修单也造上两三条。这样做的好处是演示时画面内容丰富不会因为空数据显得寒酸也不会在临时录数据时浪费宝贵时间。8.2 答辩高频问题应对思路答辩老师最喜欢问的不是“你用了什么技术”而是“为什么要这么设计”以及“有没有考虑过XX情况”。我把高频问题整理成一份攻防手册问题一为什么选择Spring Boot核心技术点Spring Boot简化了Spring的配置内置了Tomcat提供了自动配置和起步依赖让开发者聚焦业务非常适合企业级快速开发。可以在回答中强调“Spring Boot是目前Java后端主流的开发框架生态完整”增加说服力。问题二用户密码是怎么存储的核心技术点使用了BCrypt加盐哈希不是明文存储。可以补充说明加盐值是如何生成的以及如何校验用户输入的密码。这个问题考察安全意识能答好非常加分。问题三租赁合同状态是怎么流转的核心技术点用状态机设计把所有可能的状态变换列出来每个操作先做状态校验再执行更新可参考前文合同签署代码的实现。回答时最好能结合具体的代码片段说明。问题四定时任务部署到服务器上会不会出问题可以坦诚地说当前使用的Scheduled是单机版本的定时任务。后续如果想做分布式集群部署会把任务调度升级为XXL-JOB这类分布式调度平台。细心拆分问题之后稳妥地回答“现阶段项目是单机部署单机定时任务完全够用”。这种回答方式的好处是既承认了当前方案的适用边界又展现了你对分布式系统的了解。8.3 几个让项目“加分”的小改进如果系统已经跑通但答辩前还有两天时间我建议优先做这几件投入产出比最高的事给所有表单加上前端校验。必填项没填会弹出提示密码长度不足会标红手机号格式不对会截断输入。这些交互细节会让整个系统看起来精致很多。给管理员首页加上数据看板。ECharts的柱状图展示近六个月租金收入饼图展示房源类型分布数字卡片展示总房源数、在租数、待处理报修数。后端只要一个统计接口聚合查询MySQL数据前端引入一个ECharts的CDN脚本就足够了。把项目的README写好。项目背景、技术栈、功能清单、数据库说明、启动步骤、默认账号全部写进去。答辩前打印一份纸质版评委看一眼就觉得你做事规范。README也是评判你工程素养的窗口很多低级错误在这里一眼就能识破。9. 个人实操心得与后续扩展方向做这个项目最大的收获其实是学会了如何在一个完整的业务场景中做取舍。最初我照着教程把用户表、房源表、合同表建好之后发现账单逻辑远比自己想象的复杂——水电费要算周期、押金要关联退租事件、违约金要根据逾期天数动态计算。如果一开始就把所有规则塞进代码现在的工程量可能翻一倍还不止而且bug会多得让人崩溃。后来我换了一种思路把业务拆分成了“核心闭环”和“边缘功能”两类。核心闭环就是租客找房 → 签约 → 支付 → 报修边缘功能是到期提醒、押金结算、数据统计、图形报表。核心闭环用最稳妥的方式实现边缘功能等主流程稳定后再逐步添加。事实证明这种思路帮我省了大量调整代码的时间也让我对“需求优先级”有了真实感受——这和在企业里做项目的节奏是相似的。另一个让我印象深刻的点是mysql时区问题的排查。Spring Boot 2.7 MySQL 8.0的组合只要连接参数的URL里没写serverTimezoneAsia/Shanghai启动时就会报一个特别唬人的异常看起来像是支持问题实际上就是缺少了一个参数。这个问题我在三个不同项目里都碰过现在已经成为我检查配置文件的固定项了——项目没法运行首先排查数据库时区。最后想说说这个系统后续的扩展方向如果你毕业设计做完还想继续提升建议在三个方向选一个深入下去第一把单机定时任务改成分布式调度平台然后把应用容器化部署起来这会让你的简历里多出“Docker Kubernetes”的关键词。第二接口层面引入Spring Security OAuth2 JWT 做无状态认证替换当前的Session方案这也是企业里最常见的认证模式。第三前端用Vue3重写配合Vite构建后端提供纯REST接口把前后端彻底分离重点去解决跨域、Token刷新这类联调问题。房屋租赁系统的业务模型毕竟是经典的企业级应用模型。把这一套玩明白了以后任何“XX管理系统”的毕业设计对你来说都是换皮加功能而已。我自己做完这套系统之后最大的感受是代码能力不是靠看出来的一定是靠亲手把一个复杂业务逻辑跑通、踩坑、再修正练出来的。提示上面重点强调了版本兼容性、数据库配置、权限拦截和定时任务这四个环节只要你把其中任何一个坑提前预判整个开发过程都会顺利大半。再去打开你的源码工程重启验证一次跑通之后你就能底气十足地站到答辩台前了。
返回列表