新闻详情

新闻详情

首页 / 资讯中心 / 详情

基于Spring Boot的大学生房屋租赁系统全解析:从JavaWeb到Docker部署

发布时间:2026/10/1 18:27:52来源:尧图网络
基于Spring Boot的大学生房屋租赁系统全解析:从JavaWeb到Docker部署
Spring Boot 的大学生房屋租赁系统前前后后我做过好几个版本有给毕设做的也有给实际业务改造的。这个“基于 JavaWeb 的大学生房屋租赁系统的设计与实现”属于非常典型的 Java 全栈入门偏进阶项目。放到今天来看它不算新潮但恰恰是因为它不新潮反而特别适合用来把 Spring Boot 的核心链路吃透——从 Maven 构建、MyBatis 持久层、拦截器鉴权、文件上传到前后端联调、Docker 部署整条线走完你对“一个 JavaWeb 项目到底是怎么跑起来的”会有非常踏实的理解而不是停留在“跟着视频敲了一遍”的层面。这篇文章我就按我实际做这类项目的顺序来写从整体设计思路、技术选型、核心模块的代码落地到数据库表设计、部署配置、常见坑的排查方法尽量把“为什么这样做”也讲清楚。内容会比较多建议收藏着慢慢看。1. 项目整体设计与思路拆解1.1 这个系统的定位与核心需求大学生房屋租赁系统说白了就是一个“房源信息发布 租客找房 在线沟通/预订/合同管理”的内容管理类系统。目标用户很明确在校大学生和学校周边的房东或者二房东。这类用户群体的特点决定了系统功能和传统租房平台差异很大价格敏感、信息透明大学生预算有限对价格、距离学校的位置、合租室友情况非常在意。租期灵活寒暑假、实习、考研二战租期往往不是标准的一年而是几个月甚至按周计算。流程相对简单不要求像链家那样复杂的电子签约、押金托管核心是“看到房源 → 联系房东 / 发起预订 → 线下看房 → 成交确认”。管理员干预要少系统需要一个后台做基本审核比如房东身份验证、房源信息合规性但不需要太重的审批流。基于这些分析系统可以拆成三大端租客端前台注册登录、浏览房源列表、按区域/租金/户型筛选、查看房源详情、收藏房源、发起租房申请或在线预订、管理自己的订单/合同、个人信息维护、浏览公告。房东端前台角色之一房源发布、房源上下架、编辑房源信息标题、图片、租金、户型、配套设施、地址、处理租客的租房申请同意/拒绝、查看自己的合同和收款记录。管理员端后台用户管理禁用/启用、房东资质审核、房源审核、公告管理、投诉与反馈处理、数据概览比如房源数、注册用户数、订单数。注意毕设或者课程设计里很容易把结构做成“普通用户 管理员”两端。但“大学生房屋租赁”这个场景下把“房东”独立成一个有业务操作权限的角色会让项目的业务逻辑丰富很多答辩时也更好讲。用户表里用一个 role 字段区分0 普通用户 / 1 房东 / 2 管理员即可没必要拆成三套用户体系。1.2 为什么用 Spring Boot JavaWeb 这套组合这个问题我经常被问。标题里“基于 JavaWeb”和“Spring Boot”同时出现很多同学会觉得矛盾——JavaWeb 不是 Servlet JSP 的老技术吗Spring Boot 不是新框架吗其实不矛盾。JavaWeb 是范畴广义的 JavaWeb 指“用 Java 语言开发 Web 应用”的整个技术体系包括 Servlet、HTTP 协议、Session/Cookie、Filter/Interceptor、MVC 分层模型这些基础概念。这些是面试常问、也是理解框架底层绕不开的东西。Spring Boot 是工具它把传统的 Spring MVC Spring MyBatis 整合过程简化了内嵌 Tomcat自动装配让你从“配置地狱”里解放出来。但它底层跑的还是 Servlet 规范那一套——DispatcherServlet 还是继承自 HttpServlet你写的 Controller 最终还是被 Servlet 容器调用。所以用 Spring Boot 做这个项目等于“站在 JavaWeb 基础之上用现代的开发效率去实现业务”。这也就是为什么绝大多数高校毕设题目都是“基于 Spring Boot 的 XX 系统”——既有理论深度JavaWeb 基础又有工程实践价值Spring Boot 全家桶。技术栈选型方面我的建议是不要贪新稳为主技术组件推荐选型说明后端框架Spring Boot 2.7.x用 2.7.x 而非 3.x原因后面专门讲持久层MyBatis或 MyBatis-Plus比 JPA 好讲好懂SQL 可控性强数据库MySQL 5.7 / 8.0免费、资料多、面试常问前端Thymeleaf Bootstrap / Layui不推荐 Vue理由见下文构建工具Maven别用 Gradle毕设答辩老师不一定熟权限控制Spring Boot Interceptor Session简单直接够用文件上传本地存储后面可升级 MinIO减少部署复杂度不推荐上 Vue 前后端分离的原因很简单大学生的房屋租赁系统业务复杂度撑不起前后端分离的架构优势却要承担双倍的开发量和部署成本。你用 Thymeleaf 模板引擎后端渲染页面一套 Spring Boot 应用直接跑完本地开发、服务器部署都简单。前后端分离适合多人协作、接口复用要求高的大型项目单人或双人做的课程设计老老实实服务端渲染最省事。1.3 为什么 Spring Boot 版本不能乱选这其实是个直接影响“能不能跑起来”的问题。做毕设/课设最常见的悲剧创建项目时选了 Spring Boot 3.x然后怎么也跑不起来报各种依赖冲突。原因很简单Spring Boot 3.x 最低要求 JDK 17很多同学的机器还是 JDK 8直接跑不了。Spring Boot 3.x 用的是 Jakarta EEjavax 改成了 jakarta 包名很多网上的老教程里的代码直接粘贴过来会报“程序包 javax.servlet 不存在”。国内大量教学资料、毕业设计论文模板、博客代码都是基于 Spring Boot 2.x 写的你选 3.x 意味着几乎所有的参考代码都要自己改。所以老老实实用 Spring Boot 2.7.182.x 最后的一个版本JDK 1.8MyBatis 用 mybatis-spring-boot-starter 2.2.0 或 2.3.0。这个组合经过了无数人的验证网上资料最全出问题最好搜。等这个项目做完了想体验新特性再单独去学 3.x 不迟。2. 核心功能模块设计与编码要点2.1 用户注册、登录与权限拦截这个模块是整个系统的地基。注意几个关键点密码不能明文存。我见过太多课程设计代码是明文密码答辩老师一问“你这个密码安全吗”就卡壳。用 Spring Security Crypto 或者自己写个 MD5 加盐都行。最简单靠谱的姿势// 引入 spring-security-crypto 依赖用 BCrypt 加密 // 依赖坐标org.springframework.security:spring-security-crypto:5.7.11 String encodedPwd new BCryptPasswordEncoder().encode(rawPassword); // 校验时 boolean matches new BCryptPasswordEncoder().matches(rawPassword, encodedPwd);BCrypt 的好处是每次加密结果都不一样内置随机盐而且计算速度慢能抗暴力破解。比自己手写 MD5 固定盐要安全得多。虽然毕设项目对安全要求没那么高但用上这个答辩时算是一个亮点。登录状态用 Session 还是 JWT对于服务端渲染的项目直接用 HttpSession 即可不需要引入 JWT 增加复杂度。登录成功后把用户对象放进 SessionPostMapping(/login) public String login(String username, String password, HttpSession session, Model model) { User user userService.login(username, password); if (user null) { model.addAttribute(error, 用户名或密码错误); return login; } session.setAttribute(loginUser, user); // 根据角色跳转到不同首页 if (user.getRole() 2) { return redirect:/admin/index; } return redirect:/index; }权限拦截器是必须的。否则用户直接访问http://localhost:8080/admin/index就绕过了登录系统等于裸奔。用一个 HandlerInterceptor 实现Component public class LoginInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 放行登录注册相关的 URL String uri request.getRequestURI(); if (uri.startsWith(/login) || uri.startsWith(/register) || uri.startsWith(/css) || uri.startsWith(/js) || uri.startsWith(/images) || uri.startsWith(/fonts)) { return true; } HttpSession session request.getSession(); User user (User) session.getAttribute(loginUser); if (user null) { // 没登录跳回登录页 response.sendRedirect(/login); return false; } // 已登录进一步做角色校验 if (uri.startsWith(/admin) user.getRole() ! 2) { response.sendRedirect(/index); return false; } return true; } }注册到 WebMvcConfigurer 里Configuration public class WebConfig implements WebMvcConfigurer { Autowired private LoginInterceptor loginInterceptor; Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(loginInterceptor) .addPathPatterns(/**) .excludePathPatterns(/login, /register, /static/**, /error); } }注意一个细节Thymeleaf 的静态资源路径如果不做放行CSS/JS 全部 404页面难看得没法看。在 application.properties 里配置 Spring Boot 2.x 默认静态资源路径是classpath:/static/所以资源引用路径写/css/xxx.css拦截器放行/css/**、/js/**、/images/**即可。2.2 房源信息的发布、展示与图片上传房源模块是整个系统的核心业务。几个关键设计图片上传不能存 Base64 到数据库。数据库只存图片的访问路径URL文件本身落到本地磁盘目录或后续换成 MinIO 对象存储。做法PostMapping(/house/add) public String addHouse(House house, MultipartFile[] files, HttpSession session) throws IOException { User loginUser (User) session.getAttribute(loginUser); house.setUserId(loginUser.getId()); // 归属于当前房东账号 // 上传主图 户型图等 ListString urls new ArrayList(); String uploadDir D:/upload/; // 生产环境换成服务器绝对路径不要用相对路径 for (MultipartFile file : files) { if (file.isEmpty()) continue; // 生成不重复的文件名时间戳 随机数 扩展名 String originalFilename file.getOriginalFilename(); String ext originalFilename.substring(originalFilename.lastIndexOf(.)); String filename System.currentTimeMillis() _ new Random().nextInt(1000) ext; file.transferTo(new File(uploadDir filename)); urls.add(/upload/ filename); } house.setImages(String.join(,, urls)); // 多张图逗号分隔存储 houseService.save(house); return redirect:/house/list; }丰富房源筛选条件是个加分项。列表页除了分页按区域、价格区间、户型、出租方式整租/合租、朝向筛选对应的就是后端一个带动态 SQL 的查询。这正好能体现 MyBatis 的最强场景——动态 SQLselect idsearchHouses resultTypecom.example.entity.House SELECT * FROM house WHERE status 1 !-- 只查已上架 -- if testdistrict ! null and district ! AND district #{district} /if if testminPrice ! null AND price gt; #{minPrice} /if if testmaxPrice ! null AND price lt; #{maxPrice} /if if testtype ! null and type ! AND house_type #{type} /if if testrentType ! null and rentType ! AND rent_type #{rentType} /if ORDER BY create_time DESC /select注意 XML 中小于号lt;不能直接写否则 XML 解析直接报错。这个坑几乎每个人都要踩一次。为什么图片地址要返回/upload/xxx.jpg而不是D:/upload/xxx.jpg因为前端页面渲染时浏览器拿D:/upload/xxx.jpg是访问不了的——那是服务器磁盘路径不是 URL。你需要把本地的 upload 目录映射成一个可访问的静态资源路径。Spring Boot 里一行配置Configuration public class UploadConfig implements WebMvcConfigurer { Value(${file.upload-path}) private String uploadPath; Override public void addResourceHandlers(ResourceHandlerRegistry registry) { // 把 /upload/** 映射到磁盘路径浏览器就能直接访问图片了 registry.addResourceHandler(/upload/**) .addResourceLocations(file: uploadPath); } }2.3 租房申请、订单状态流转与合同生成这个模块是业务深度的体现。一个完整的租房流程状态要闭环状态机设计用整数存状态扩展性好待看房(0) → 已看房/待确认(1) → 已签约(2) / 已取消(3) 从已签约 → 已到期(4) / 已退租(5)租客在房源详情页点“申请看房”/“立即预定”生成一条订单记录状态为待确认同时通知房东可以在房东端的“我的订单”里看到待处理列表。房东点击“同意”状态变为已看房/待签约房东点击“拒绝”直接流转到已取消。订单状态变更的 Update 语句必须带状态条件// 防止并发下状态错乱只允许从当前状态流转到目标状态 // SQL: UPDATE orders SET status #{newStatus} WHERE id #{orderId} AND status #{oldStatus} // 返回值 int 为 0 说明状态已经变了前端提示“操作失败请刷新后重试” int rows orderMapper.updateStatus(orderId, fromStatus, toStatus); if (rows 0) { throw new BusinessException(操作失败订单状态已更新请刷新查看最新状态); }合同生成有两种做法一种是在线预览/打印 HTML 合同Thymeleaf 模板渲染另一种是直接用 Java 生成 PDF 文件。毕设建议选 HTML 合同预览简单得多——你只要在合同页面把订单信息双方姓名、房屋地址、租金、租期、押金渲染出来再提供一个“打印”按钮让用户自己打印。用 PDF 的话要引入 iText 或者 OpenPDF字体问题中文不显示、文字乱码能折腾一整天性价比太低。合同的核心字段合同编号可以用时间戳随机数生成、出租方房东、承租方租客、房屋信息、租金、押金、起止日期、签订日期、双方同意条款。存一张 contract 表即可状态跟订单绑定。2.4 管理后台的数据概览与审核操作管理后台不要做得太复杂但一定要有“数据统计”“审核操作”两块。数据概览页用一个简单的 Dashboard展示房源总数、用户总数、今日新增订单、待审核房源数。Mapper 里写几个 count 查询即可Select(SELECT COUNT(*) FROM house) int countHouse(); Select(SELECT COUNT(*) FROM user) int countUser(); Select(SELECT COUNT(*) FROM orders WHERE DATE(create_time) CURDATE()) int countTodayOrders();房源审核房东发布的房源默认状态为待审核status0管理员审核通过后变为已上架status1驳回则填入驳回原因status2租客前台只能看到已上架房源。这个流程简单但在业务上非常合理——避免垃圾房源直接出现在列表里。用户禁用admin 后台可以直接把某个用户状态改为 0禁用被禁用的用户登录时提示账户已被禁用。登录逻辑加一个判断if (user.getStatus() 0) { model.addAttribute(error, 该账户已被禁用请联系管理员); return login; }3. 数据库设计这 6 张核心表怎么建才合理3.1 用户表、房源表、订单表的核心字段数据库设计是答辩时老师必问的环节也是后续写代码的地基。建表语句不要用逆向生成的自己手工设计能讲清楚每张表为什么这么建。用户表t_userCREATE TABLE t_user ( id INT NOT NULL AUTO_INCREMENT COMMENT 用户ID, username VARCHAR(50) NOT NULL COMMENT 登录用户名, password VARCHAR(100) NOT NULL COMMENT BCrypt加密后的密码, real_name VARCHAR(30) DEFAULT NULL COMMENT 真实姓名, phone VARCHAR(20) DEFAULT NULL COMMENT 手机号, email VARCHAR(50) DEFAULT NULL COMMENT 邮箱, role TINYINT DEFAULT 0 COMMENT 角色0普通用户/学生1房东2管理员, status TINYINT DEFAULT 1 COMMENT 状态1正常0禁用, create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT 注册时间, PRIMARY KEY (id), UNIQUE KEY uk_username (username) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT用户表;注意chatset 必须用 utf8mb4 而不是 utf8。utf8mb4 才能存 emoji 表情和冷僻字而且这是 MySQL 5.7 的主流配置。用老 utf8 后面插入特殊字符直接报错。房源表t_houseCREATE TABLE t_house ( id INT NOT NULL AUTO_INCREMENT, user_id INT NOT NULL COMMENT 发布者ID房东, title VARCHAR(100) NOT NULL COMMENT 房源标题, description TEXT COMMENT 房源描述, images VARCHAR(1000) DEFAULT NULL COMMENT 图片地址逗号分隔, district VARCHAR(30) DEFAULT NULL COMMENT 区域如海淀区, address VARCHAR(200) DEFAULT NULL COMMENT 详细地址, price DECIMAL(10,2) NOT NULL COMMENT 月租金元, house_type VARCHAR(20) DEFAULT NULL COMMENT 户型如一室一厅、两室一厅, area INT DEFAULT NULL COMMENT 面积平方米, rent_type TINYINT DEFAULT 0 COMMENT 出租方式0整租 1合租, orientation VARCHAR(10) DEFAULT NULL COMMENT 朝向南/北/东/西, status TINYINT DEFAULT 0 COMMENT 0待审核 1已上架 2已驳回 3已下架, view_count INT DEFAULT 0 COMMENT 浏览量, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY idx_user_id (user_id), KEY idx_status (status) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT房源表;订单表t_ordersCREATE TABLE t_orders ( id INT NOT NULL AUTO_INCREMENT, order_no VARCHAR(32) NOT NULL COMMENT 订单编号, house_id INT NOT NULL COMMENT 房源ID, tenant_id INT NOT NULL COMMENT 租客ID, landlord_id INT NOT NULL COMMENT 房东ID, start_date DATE DEFAULT NULL COMMENT 租期开始日期, end_date DATE DEFAULT NULL COMMENT 租期结束日期, monthly_rent DECIMAL(10,2) DEFAULT NULL COMMENT 成交月租金, deposit DECIMAL(10,2) DEFAULT NULL COMMENT 押金, status TINYINT DEFAULT 0 COMMENT 0待确认 1待签约 2已签约 3已取消 4已到期, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uk_order_no (order_no), KEY idx_house_id (house_id), KEY idx_tenant_id (tenant_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT租房订单表;其它表收藏表t_favoriteuser_id house_id 联合唯一、公告表t_notice标题内容时间、合同表t_contract关联订单、反馈表t_feedback。这些表结构相对简单按业务字段填充即可。我个人习惯是每张表都要有 id 主键和 create_time 字段这是基本素养。3.2 表关系怎么讲才清楚答辩时老师爱问“你讲讲表与表之间的关系”。涉及到的关系用户房东→ 房源一对多t_house.user_id 关联 t_user.id。用户租客→ 订单一对多t_orders.tenant_id 关联 t_user.id。房源 → 订单一对多一个房源可以被多个租客先后预订但同一时间只能有一个有效订单这个可以在业务层判断查询该房源是否存在 status in (0,1,2) 的订单。用户 → 收藏 → 房源多对多通过 t_favorite 中间表关联。为什么要存冗余的 landlord_id 在订单表里因为订单列表页要频繁按房东查订单如果不冗余每次都要先查房源再反查房东SQL 写得啰嗦性能也差。适度冗余在业务表设计里是常见做法能讲出来说明你有实战经验。4. 实操过程从 IDEA 创建项目到跑通第一个页面4.1 IDEA 创建 Spring Boot 项目时的正确配置用 IDEA 的 Spring Initializr 创建项目注意几个容易踩的选择项Project SDK 选Java 81.8Language 选 Java。如果初始化时让你选 Spring Boot 版本一定要选2.x 系列的最高版本2.7.18不要默认选 3.x。Dependencies 里勾选Spring Web、Thymeleaf、MyBatis Framework注意来自 mybatis.org 那个不是 MyBatis Spring Boot Starter、MySQL Driver、Lombok可选减少样板代码。如果初始化时没有 MyBatis 选项就在 pom.xml 手动加dependency groupIdorg.mybatis.spring.boot/groupId artifactIdmybatis-spring-boot-starter/artifactId version2.3.0/version /dependency为什么要 MyBatis Framework 又要 mybatis-spring-boot-starterIDEA 里默认给的 “MyBatis Framework” 其实是早期版本的 starter坐标会写成org.mybatis:mybatis这个只是 MyBatis 核心库不会被 Spring Boot 自动配置。你需要的是org.mybatis.spring.boot:mybatis-spring-boot-starter它把 SqlSessionFactory、DataSource 的装配都搞定了。如果不小心只加了核心库一运行就会报Invalid bound statement (not found)之类的问题。4.2 IDEA 运行 JavaWeb 项目的配置细节IDE 配置这块很多新手卡在“明明代码没问题但跑不起来”。几个关键配置1. Maven 配置Settings → Maven → Maven home path 选你自己解压的 Maven3.6.x 或 3.8.x不要用 IDEA 自带的也行但建议手动配。User settings file 指向conf/settings.xmlLocal repository 指向你自定义的仓库目录。settings.xml 里加阿里云镜像mirror idaliyunmaven/id mirrorOf*/mirrorOf name阿里云公共仓库/name urlhttps://maven.aliyun.com/repository/public/url /mirror不加镜像的话Maven 中央仓库的下载速度会让人怀疑人生。2. 配置 Application 启动类Edit Configurations → 点 → Spring Boot → 选择主类带上SpringBootApplication的那个类。Working directory 建议选$MODULE_WORKING_DIR$模块目录否则如果配错工作目录读不到相对路径的配置文件。3. 端口配置application.properties里server.port8080 spring.datasource.urljdbc:mysql://localhost:3306/house_rent?useUnicodetruecharacterEncodingutf-8serverTimezoneAsia/ShanghaiuseSSLfalse spring.datasource.usernameroot spring.datasource.password你的密码 spring.datasource.driver-class-namecom.mysql.cj.jdbc.Driver mybatis.mapper-locationsclasspath:mapper/*.xml mybatis.type-aliases-packagecom.example.entity logging.level.com.example.mapperdebugserverTimezoneAsia/Shanghai必须加。MySQL 8.x 的驱动默认时区是美国不加这个数据库连接直接报 CST 时区错误页面数据全是乱的。4. 一个把 Java 源文件直接放 classpath 的坑MyBatis 的 Mapper 接口和 XML 文件分开两个目录时接口在src/main/javaXML 在src/main/resources/mapper如果不把src/main/java下的.xml文件也打进 classpath运行时会报Invalid bound statement (not found)。最省心的做法是 XML 统一放 resources并且 pom.xml 加配置resources resource directorysrc/main/resources/directory includes include**/*.xml/include include**/*.properties/include include**/*.yml/include /includes /resource resource directorysrc/main/java/directory includes include**/*.xml/include /includes /resource /resources4.3 跑通“注册 → 登录 → 发布房源 → 前端展示”全链路不要等所有代码写完再一次性测试。我建议按下面这个顺序每完成一个环节就跑通一次创建 Spring Boot 项目写一个HelloController访问http://localhost:8080/hello能看到字符串证明环境是好的。引入 MyBatis配置 datasource创建 user 表完成注册接口浏览器提交用户名密码 → 后台写入数据库 → 用 Navicat 能看到记录。写登录接口查数据库 → 比对密码 → Session 存入用户 → 跳转首页。加拦截器验证未登录访问/house/add会被重定向到登录页。创建 house 表完成房源发布表单提交包含图片上传再写一个/house/list页面展示数据库里的房源记录。最后再完善订单、收藏、后台审核、公告等模块。这样每个环节的问题都被限制在很小的范围内排查起来极快。如果一口气写完所有代码再启动报错之后你根本分不清是配置问题还是代码问题。5. 常见问题与排查技巧实录5.1 启动失败的几类典型原因现象一Failed to configure a DataSource: url attribute is not specified启动类上多了SpringBootApplication(exclude DataSourceAutoConfiguration.class)但你没配数据源——这是最常见的误操作。或者你根本没有引入 JDBC/MyBatis 的依赖但 Spring Boot 还是会自动装配数据源。排查思路确认 application.properties 里 datasource 三件套url/username/password都配了且驱动依赖已经在 pom 里。现象二Table house_rent.xxx doesnt exist数据库建了但表不存在。检查方式确认你连接的库名是不是真的叫 house_rent确认表名、字段名和实体类/mapper XML 里完全一致注意大小写和下划线MySQL 在 Linux 下区分表名大小写Windows 下不区分所以本地跑得好好的代码部署到 Linux 服务器就报这个错。避免方式建表全部用统一小写下划线。现象三Whitelabel Error Page404三种可能Controller 的RequestMapping路径没写对静态资源和模板页没放对位置Thymeleaf 模板必须在templates目录下Controller 类没有被 Spring 扫描到启动类不在com.example包的上级或者 Controller 没加Controller。现象四MyBatis 的Invalid bound statement (not found)Mapper 接口方法和 XML 里的 id 名称不一致XML 文件没有在mapper-locations指定路径下接口没有加Mapper注解或没在启动类加MapperScan。我一般直接用MapperScan(com.example.mapper)一次性扫描省得每个接口加注解。5.2 前端页面调试的几个技巧Thymeleaf 页面热更新Spring Boot 2.x 里修改 HTML 模板后默认要重启才能生效。本地开发想省事在 pom.xml 加dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-devtools/artifactId optionaltrue/optional /dependency并且在application.properties里配spring.thymeleaf.cachefalse这样改完 HTML、ControllerIDEA 里按下 CtrlF9Build Project就能热更新不用反复重启。模板路径引用不要写错src/main/resources/templates/login.html对应的 Controller 返回值是login返回路径不能带templates/前缀也不能写/login.html。Thymeleaf 的 ViewResolver 会自动拼 prefix 和 suffix。页面静态资源用th:href普通 HTML 里写死/css/style.css没问题但如果项目配了 context-path比如server.servlet.context-path/house所有静态资源路径都要加前缀。我建议本地开发不配 context-path部署时用 Nginx 做二级路径转发省去这个麻烦。5.3 部署到服务器时最容易踩的 3 个坑坑一上传图片路径问题本地是D:/upload/部署到 Linux 之后不存在这个路径。建议把上传路径做成外部配置file.upload-path/data/house-rent/upload/并且在 Linux 上执行mkdir -p /data/house-rent/upload给权限。绝对不要把上传目录放在项目包里面因为重新打包部署时目录会被覆盖图片全丢。坑二打包成 jar 还是 warSpring Boot 默认打成 jar 包直接运行这是最简单的方式。不要折腾 war 包丢到 Tomcat 的 webapps 下除非你的部署环境强制要求外部 Tomcat。打 jar 包命令mvn clean package -DskipTests java -jar house-rent-0.0.1-SNAPSHOT.jar --server.port8080用nohup java -jar xxx.jar 后台运行。生产环境建议加--spring.profiles.activeprod区分不同环境配置。坑三数据库时区再报错本地配了serverTimezoneAsia/Shanghai服务器上也一定要配否则 MySQL 连接串里的时区问题会再次出现。另外 MySQL 8.x 需要在 my.cnf 里加上[mysqld] lower_case_table_names1这样表名大小写不敏感Windows 开发、Linux 部署切换才不会有“表不存在”的诡异问题。5.4 版本和依赖冲突的排查套路如果项目里某些依赖版本异常Spring Boot 启动时会给BeanCreationException或者奇怪的 NoSuchMethodError。排查流程按顺序来mvn dependency:tree看依赖树找有没有同一个包出现两个版本比如 mybatis 3.5 和 4.0 共存。检查是否混用 Spring Boot 2.x 和 3.x 的 starter。某些网站下载的 pom 可能自动带了 3.x 的传递依赖和 2.x 冲突。确认 JDK 版本Spring Boot 2.7 支持到 JDK 17但你本地是 JDK 8 的话编译时用-source 1.8 -target 1.8即可Spring Boot 3 直接要求 JDK 17装个 JDK 17 就得全套换。依赖冲突的终极方案删C:\Users\你的用户名\.m2\repository下对应的包目录重新 mvn 依赖拉取或者 mvn clean reimport。很多时候 IDEA 的 Maven 索引没刷新你以为依赖有问题其实本地仓库里是脏的。6. 进阶优化让这个项目从“能跑”到“像样”6.1 MinIO 做文件存储从本地磁盘走向对象存储房源图片放本地磁盘好处是简单坏处是应用多实例部署时图片不一致、磁盘满了不好管理、服务器迁移麻烦。如果想让项目在答辩上更出彩可以引入 MinIO开源对象存储兼容 S3 协议。核心思想图片上传时直接传到 MinIO 服务器返回一个 URL 存数据库。本地开发用一个 Docker 起的 MinIOdocker run -p 9000:9000 -p 9001:9001 \ -e MINIO_ROOT_USERadmin \ -e MINIO_ROOT_PASSWORDadmin123456 \ -v /data/minio/data:/data \ minio/minio server /data --console-address :9001Spring Boot 引入依赖dependency groupIdio.minio/groupId artifactIdminio/artifactId version8.5.7/version /dependency上传代码核心Autowired private MinioClient minioClient; public String upload(MultipartFile file, String bucket) throws Exception { // 检查 bucket 是否存在不存在则创建 boolean found minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucket).build()); if (!found) { minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucket).build()); } // 生成文件名时间戳随机数避免重名 String filename System.currentTimeMillis() _ file.getOriginalFilename(); // 上传 minioClient.putObject(PutObjectArgs.builder() .bucket(bucket) .object(filename) .stream(file.getInputStream(), file.getSize(), -1) .contentType(file.getContentType()) .build()); return /minio/ bucket / filename; }这就解释了为什么热词里有“minio加入到springboot”——因为这个内容确实踩过坑MinIO 的 SDK 版本新旧 API 差异大网上搜出来的代码可能互相矛盾。建议直接用官方文档别用博客里粘贴的老代码。6.2 Linux 下 Docker 部署 Spring Boot 应用的完整流程Docker 部署对这个项目而言最大的价值是“环境一致性”——本地跑的和线上跑的完全一样。写一个 Dockerfile放在项目根目录FROM openjdk:8-jdk-alpine MAINTAINER yourname VOLUME /tmp COPY house-rent-0.0.1-SNAPSHOT.jar app.jar ENV TZAsia/Shanghai RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime echo $TZ /etc/timezone ENTRYPOINT [java,-Djava.security.egdfile:/dev/./urandom,-jar,/app.jar]打包部署命令mvn clean package -DskipTests docker build -t house-rent:1.0 . docker run -d --name house-rent \ -p 8080:8080 \ -v /data/house-rent/upload:/data/upload \ --restartalways \ house-rent:1.0这里-v挂载目录特别重要上传的图片必须放在宿主机持久化目录否则容器删了图片就丢了。6.3 撰论文时的模块结构建议如果这个项目是毕设论文的目录结构不是代码结构可以参考第1章 绪论背景、国内外研究现状、研究内容第2章 相关技术介绍Spring Boot、MyBatis、MySQL、Thymeleaf第3章 系统分析可行性分析、需求分析、用例图、功能模块分析第4章 系统设计总体架构、功能模块设计、数据库设计、ER图、表结构第5章 系统实现每个功能模块的界面和核心代码第6章 系统测试测试用例、功能测试、兼容性测试论文里的图表比文字重要。ER 图用 MySQL Workbench 的逆向功能生成即可流程图和用例图可以用 Process On 或者 draw.io 画别手画。核心代码贴最有代表性的拦截器、动态 SQL、订单状态流转不要贴整段 Controller。一点过来人的经验整个系统从零开始一个人做节奏控制好的话两个礼拜能出完整的第一版。最容易拖慢进度的地方不是代码而是“不知道怎么改才能跑起来”的调试环节。我的建议是遇到报错先冷静读最后几行日志把异常信息原文复制到搜索引擎搜大部分坑都有人踩过。不要自己瞎改配置改了三处之后你根本不知道到底是哪里生效的。另外强烈建议用 Git 做版本管理每完成一个功能点就 commit 一次。我见过太多人做毕设代码写崩了之后没法回退只能全部重来。Git 不是加分项是这个规模项目的生存刚需。最后再多说一句做一个完整系统真正值钱的不是你用了多新的技术而是你清楚每张表为什么这么设计、每个拦截器的时间复杂度是什么、每个状态的流转为什么会走到那一步。把这些想明白了写出来的代码自己心里有底答辩老师一问一个准因为你真的做过。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

旅游推荐系统实战:从数据采集到排序模型的大数据全链路解析 2026/10/1 22:59:02

旅游推荐系统实战:从数据采集到排序模型的大数据全链路解析

1. 从“千人一面”到“千人千面”:旅游推荐系统遇到的真实问题 打开任何一家旅游App,首页推荐无非是“热门景点TOP10”“周边游推荐”“XX网红打卡地”,刷三天内容基本一样。这不是旅行App偷懒,而是绝大多数推荐系统只解决了一个问…

阅读更多 →
上海靠谱的AI搜索排名优化服务商推荐用户力荐 2026/10/1 22:59:02

上海靠谱的AI搜索排名优化服务商推荐用户力荐

上海企业如何选择靠谱的AI搜索排名优化服务商在数字化营销的浪潮中,AI搜索排名优化已成为企业获取流量、提升品牌影响力的关键手段。随着人工智能技术的快速发展,传统的搜索引擎优化正在向生成式引擎优化演进,这为企业带来了全新的获客机遇。…

阅读更多 →
本地AI任务拆分优化:L0硬规则+L1模型兜底的两级流水线实践 2026/10/1 22:59:02

本地AI任务拆分优化:L0硬规则+L1模型兜底的两级流水线实践

本地AI做任务拆分,最忌讳的就是让模型每件事都亲力亲为。我最近在搭本地部署的大模型应用时,被这个老问题反复摩擦:一个任务拆分的请求丢给7B模型,动辄三四秒、输出还经常带飘,真要接了上游的自动化流程,整…

阅读更多 →
YOLOv8工业滤袋破损检测实战:轻量部署与高精度落地 2026/10/1 22:58:56

YOLOv8工业滤袋破损检测实战:轻量部署与高精度落地

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
2026年GPU AI训练与推理优化改造实战:从驱动兼容到多卡异构的完整指南 2026/10/1 22:58:49

2026年GPU AI训练与推理优化改造实战:从驱动兼容到多卡异构的完整指南

1. 从一张显卡的两种身份说起:为什么2026年的GPU优化不再是单点问题如果你最近打开过任务管理器,看到一台笔记本上同时挂着 Intel UHD Graphics 和 NVIDIA GeForce RTX 4060 Laptop GPU,然后心里冒出一个问题——“我到底该用哪个来跑模型&am…

阅读更多 →
Parse Server 8 迁移指南:邮件验证 Token 化改造与数据库索引自动创建 2026/10/1 22:58:49

Parse Server 8 迁移指南:邮件验证 Token 化改造与数据库索引自动创建

后端认证鉴权 【免费下载链接】parse-server Parse Server for Node.js / Express 项目地址: https://gitcode.com/gh_mirrors/pa/parse-server 点击查看 免费下载 本篇技术指南聚焦 Parse Server 8(当前仓库即 Parse Server 源码)中两项需要…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉