最近在整理手头一套房屋交易信息管理系统,SpringBoot 后端 + Vue 前端 + MySQL 数据库,前后端联调整体跑通,实测可以直接运行。这类需求在中小型房产公司、房屋中介工作室里非常普遍:房源登记、客户跟进、成交进度、佣金核算,信息全堆在 Excel 和微信聊天记录里,查重靠眼睛,跟进靠记忆,稍微有点量就乱成一团。这篇文章我就把这套系统的技术选型、功能拆解、运行步骤、踩坑记录完整梳理一遍。如果你正准备做 Java 课程设计、毕业设计,或者公司内部想上一套轻量级的房产管理工具,完全可以照着这篇文章的思路复现。
1. 项目整体设计与技术选型思路
1.1 这套系统到底解决什么问题
房产交易的核心痛点是信息不对称和管理分散。房源从挂盘到成交,中间要经历登记、核验、带看、议价、签约、过户多个环节,每个环节都涉及不同的人和状态。没有系统之前,经纪人可能要同时维护五六张表:房源表、客户表、带看记录表、合同表,每张表还有不同的更新节奏,漏改一个状态,后续的跟进动作全乱套。
这套房屋交易系统要解决的就是三件事:
- 房源信息统一入库,维护上架、下架、审核状态,价格变动留痕。
- 客户信息集中管理,区分购房需求和售房意向,做匹配和跟进记录。
- 交易流程可追踪,从意向单、签约到定金、尾款,每一步都有状态节点和操作时间。
从实际使用效果看,这套系统真正替代掉的是人工台账和口头交接,让一个门店的日常业务能在一套系统里闭环跑完。尤其是带看记录和交易进度这两个功能,用起来之后效率提升非常明显,不用再翻聊天记录去回忆上次带客户看了哪套房。
1.2 为什么选 SpringBoot + Vue + MySQL 这个组合
这个问题我在接手项目时也认真想过。团队规模不大、部署环境有限,又不希望引入太重的基础设施,所以技术栈的选择逻辑其实很朴素:
后端用 SpringBoot,理由首先是生态成熟。SpringBoot 内置 Tomcat、自动配置、约定优于配置,一个带注解的启动类就能把整个后端工程带起来,不像 SSH 时代要手动拼一堆 XML。对于房屋交易这种典型 CRUD 业务,SpringBoot 的 JPA 和 MyBatis 支持都做得很顺手,开发效率远高于传统 Java Web 开发。
前端用 Vue,看重的是响应式数据和组件化开发。房屋管理页面上有大量表单、列表、状态切换,用 Vue 的双向数据绑定,数据变化会直接反映到 DOM,不需要手动操作节点。Vue 的组件生态还能把“房源卡片”“客户表单”“交易进度条”拆成公共组件,多个页面复用。
数据库用 MySQL,核心原因就是零成本起步。MySQL 是开源免费的,部署简单,运维资料多,单机性能对房屋交易这种量级完全够用。即便后期数据量上来,也只需要在 SQL 层面做索引优化和分页调整,暂时不需要上分布式数据库那套复杂度。
选型时还有一个隐藏考量:这套源码的定位是“可直接运行”,意味着别人拿到项目后要能快速部署起来。SpringBoot + Vue + MySQL 是三样受众最广的技术,遇到问题基本都能搜到解决方案,这对使用者非常友好。
2. 核心业务模块与数据库设计
2.1 业务模块拆解与角色设计
整套系统按业务角色分成三类用户:管理员、经纪人、客户(访客)。权限设计不需要搞得太复杂,用最简单的角色字段区分即可。
- 管理员:负责系统基础数据维护、房源审核、用户管理、数据统计。能查看所有房源和全部交易记录,可以对违规或重复房源执行下架操作。
- 经纪人:系统的主要使用人群。录入和管理自己名下的房源、录入客户信息、创建带看记录、发起交易流程。
- 客户(访客):前台用户可以浏览挂牌房源、查看房源详情、提交购房或卖房需求,也可以看到自己被经纪人关联的看房记录。
前端路由按角色做了简单的登录拦截:Vue Router 的 beforeEach 钩子里判断本地存储的 token 和角色信息,未登录用户只能访问公共房源列表和详情页,后台管理页面做了路由元信息 meta 的角色限制。后端通过 SpringBoot 拦截器对接口做认证校验,需要登录的接口统一从请求头读取 token,解析出用户信息后放行。
2.2 房源、客户、交易三大核心表设计
房屋交易系统表结构设计的核心是三个字:可追溯。房源状态变化、交易节点推进、客户跟进记录,都要留下历史痕迹。源码数据库里一共设计了 11 张表,最核心的是用户表(user)、房源表(house)、客户表(customer)、交易表(trade)和带看记录表(visit_record)。
先看用户表:
| 字段 | 类型 | 说明 |
|---|---|---|
| id | bigint | 主键自增 |
| username | varchar(50) | 登录账号,唯一 |
| password | varchar(100) | BCrypt 加密后的密文 |
| real_name | varchar(50) | 姓名 |
| phone | varchar(20) | 手机号 |
| role | tinyint | 1-管理员 2-经纪人 3-客户 |
| status | tinyint | 0-禁用 1-启用 |
| create_time | datetime | 创建时间 |
这里要强调一点:密码字段存储的是 BCrypt 加密密文,不是明文,更不是简单的 MD5。SpringBoot 集成 Spring Security 或直接引一个 jBCrypt 依赖就能实现,BCrypt 每次加密同一个密码会生成不同的盐值密文,即使数据库泄露,也无法通过反查哈希表还原密码。
房源表是整个系统的数据主体,字段设计上要留意状态机和价格逻辑:
| 字段 | 类型 | 说明 |
|---|---|---|
| id | bigint | 主键 |
| title | varchar(100) | 房源标题 |
| community_name | varchar(100) | 小区名称 |
| area | decimal(10,2) | 面积(平米) |
| total_price | decimal(12,2) | 总价(万元) |
| unit_price | decimal(10,2) | 单价(元/平米) |
| house_type | varchar(20) | 户型,如 3室2厅1卫 |
| floor | varchar(20) | 所在楼层 |
| decoration | varchar(20) | 装修情况 |
| status | tinyint | 1-待审核 2-在售 3-已下架 4-已成交 |
| owner_id | bigint | 业主(经纪人录入的是卖家) |
| agent_id | bigint | 负责经纪人 |
| create_time | datetime | 挂盘时间 |
交易表(trade)记录每一单的进展:
| 字段 | 类型 | 说明 |
|---|---|---|
| id | bigint | 主键 |
| house_id | bigint | 关联房源 |
| customer_id | bigint | 关联买家客户 |
| agent_id | bigint | 负责经纪人 |
| trade_status | tinyint | 1-意向 2-已签约 3-已付定金 4-过户中 5-已完成 6-已取消 |
| deal_price | decimal(12,2) | 成交价 |
| commission | decimal(12,2) | 佣金金额 |
| sign_time | datetime | 签约时间 |
| finish_time | datetime | 完成时间 |
带看记录表则是经纪人的“作业日志”,字段主要包括看房时间、房源、客户、陪同人、客户反馈意见。这部分数据对后续复盘和客户维护价值很高,也是很多入门项目容易忽略的内容。
2.3 数据库索引与数据关联的细节
表之间的关系设计,重点在两个地方。一是 house 表同时存在 owner_id 和 agent_id,这在语义上是两回事:业主是房屋产权人,经纪人是跟进服务的内部人员,不能混淆。二是 customer 表里同时维护了买家和卖家的意向字段,通过意向类型(demand_type)区分,避免为买家和卖家各建一张客户表造成数据冗余。
索引方面,房源表的 status 和 create_time、交易表的 house_id 和 trade_status、用户表的 username 都建议建索引。实际测试中,数据量在 10 万级以内,单表查询加上这几个索引,响应基本都在毫秒级。前端列表页的分页 SQL 用 LIMIT 控制返回行数,配合后端的 PageHelper 分页插件,即使数据量翻倍也不会把接口拖垮。
3. 从零跑通项目:环境配置与启动实操
3.1 开发工具与版本选择
拿到源码后第一件事,是把环境准备好。版本匹配是很多人卡住的第一个坑,我的建议是:JDK 使用 1.8 或 11,Maven 用 3.6 以上,Node.js 用 14 或 16 LTS 版本,MySQL 使用 5.7 或 8.0。SpringBoot 版本如果是 2.x,配合 JDK 1.8 是最稳定的组合,没必要一上来追新版本。
具体工具清单列一下:
- 后端 IDE:IntelliJ IDEA(个人学习用社区版也够)
- 前端 IDE:Visual Studio Code
- 数据库工具:Navicat 或 MySQL Workbench
- 接口调试:Postman 或 Apifox
启动之前,先确认本地已经装上 JDK、Maven、Node、MySQL 四个基础件。在命令行分别执行 java -version、mvn -v、node -v、mysql --version,能正常输出版本就说明环境没问题。
3.2 数据库初始化与后端启动步骤
源码里通常自带一个 sql 目录,里面是初始化脚本,一般在项目根目录或 db 目录下,文件名叫 house_db.sql。启动后端前必须先把数据库初始化好。
我习惯的操作顺序是:
- 用 Navicat 新建一个数据库,命名 house_db,字符集选 utf8mb4,排序规则选 utf8mb4_general_ci。
- 右键运行 SQL 文件,选择脚本里的 house_db.sql,执行后能看到 11 张表和部分测试数据。
- 打开后端工程的 application.yml 或者 application.properties,把数据库连接信息改成自己的账号密码。
application.yml 的核心配置如下,这里标注了注释方便按实际情况调整:
server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/house_db?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: Asia/Shanghai mybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.example.house.entity server.servlet: context-path: /api这里有几个关键点必须提醒:MySQL 8.0 以上驱动类名是 com.mysql.cj.jdbc.Driver,MySQL 5.7 用 com.mysql.jdbc.Driver 也行,但建议统一用 cj 驱动。url 里必须带 serverTimezone 参数,否则可能报时间时区相关的错误。context-path 配成 /api 是为了方便前端代理,所有后端接口统一带这个前缀。
后端启动非常简单:用 IDEA 打开后端工程,等待 Maven 下载完依赖,然后找到标注了 @SpringBootApplication 的启动类,右键运行。看到控制台打印出 Tomcat started on port(s): 8080 就表示启动成功。
提示:如果 Maven 依赖下载特别慢,先在 Maven 的 settings.xml 里配置阿里云镜像仓库,能节省大量等待时间。
3.3 Vue 前端启动与接口代理配置
前端工程一般是独立目录,比如 house-vue。启动前先安装依赖:
cd house-vue npm install npm run devnpm install 如果卡在某个包上,大概率是网络问题,可以把 registry 切到国内镜像:
npm config set registry https://registry.npmmirror.com前端启动后,默认地址一般是 http://localhost:8081,Vite 或 Vue CLI 的 devServer 需要配置代理,把 /api 开头的请求转发到后端的 8080 端口。这里以 Vue CLI 的 vue.config.js 为例:
module.exports = { devServer: { port: 8081, proxy: { '/api': { target: 'http://localhost:8080', changeOrigin: true } } } }配置好代理后,前端请求 /api/house/list 时,实际上会由 devServer 转发到后端 http://localhost:8080/api/house/list,前端页面里就不需要写完整的后端地址,避免跨域问题。
启动完成后,浏览器访问前端地址,用源码里带的测试账号(管理员 admin / 123456、经纪人 agent01 / 123456)登录,能看到控制台页面正常加载房源列表数据,就说明整套系统已经跑通了。
4. 运行阶段高频问题与排查技巧
4.1 MySQL 连接不上与时区报错
这是启动后端时遇到概率最高的问题。报错信息通常是:
Access denied for user 'root'@'localhost' (using password: YES)或者:
The server time zone value '???ú±ê×??±??' is unrecognized第一个报错,九成是密码配置不对,检查 application.yml 里的 username 和 password 是不是和本地 MySQL 一致。第二个报错是时区问题,在连接 url 末尾加上 serverTimezone=Asia/Shanghai 就能解决。
还有一种情况是 MySQL 服务本身没启动。Windows 上打开服务管理器确认 MySQL 服务状态,Mac 上用 brew services list 查看。源码用 Navicat 能连上数据库,后端却连不上,多半就是配置里的端口或密码写错了。
4.2 前端 npm install 失败或卡住
npm install 失败的原因基本集中在两点:一是 Node 版本与前端工程依赖不兼容,二是默认源访问慢导致超时。
Node 版本太高,比如直接用 Node 20 跑老项目,vue-cli 或者 node-sass 这类依赖会编译不过。排查时先看 package.json 里的 engines 字段,或者直接看报错里的 node-modules 相关提示。解决方式是安装一个 nvm,在项目目录下切换 Node 版本。
如果确定版本没问题还是装不上,按优先级做三件事:
- 切换 npmmirror 镜像源;
- 删除 node_modules 和 package-lock.json,重新 npm install;
- 用 cnpm 或者 pnpm 再试一次,但不要把 npm、cnpm、yarn 混用,会用出更多问题。
4.3 登录后接口 404 或跨域请求失败
后端能启动,前端也能打开,但登录后数据列表是空的,控制台报 404,这时候先别急着怀疑代码。浏览器 F12 打开 Network 面板,看请求路径是不是变成了 http://localhost:8081/api/house/list。
如果路径带上了 8081 端口却没有走代理,就是 devServer 代理没生效,检查 vue.config.js 文件位置是否正确,改完配置需要重启 npm run dev,devServer 配置修改不会热更新。如果请求成功但返回 401 或 403,那就是 token 没带上,检查前端 axios 实例里是否统一在请求拦截器里配置了 Authorization 请求头。
4.4 后端能跑但页面没有数据
页面空白、接口正常返回却渲染不出数据,大概率是字段名对不上。比如后端实体类属性是 totalPrice,前端拿到的字段也叫 totalPrice,但表格里绑定的是 total_price,Vue 模板里显示就会是空。这是前后端联调最常见的坑。
遇到这种情况,先打开 Network 看接口返回的 JSON 长什么样,再对照前端代码里绑定的字段名。要么在后端实体上统一做 camelCase 命名,要么让前端按实际返回字段调整绑定。源码里后端接口返回的数据结构会自动把下划线转成驼峰,前端只要按照文档字段绑定即可。
我在实践里的做法是:先理清接口文档再写页面,页面绑定字段时直接复制接口示例里的 JSON 字段名,坚决不手打,避免人为拼写错误。
4.5 常见问题速查表
| 症状 | 大概率原因 | 处理办法 |
|---|---|---|
| 后端启动报 port 被占用 | 8080 端口被其他进程占用 | 换端口或杀进程,命令行 netstat -ano 查 PID |
| Maven 依赖下载异常 | 仓库源较慢或配置错误 | 配置阿里云镜像,删除本地仓库重下 |
| 前端登录时提示账号密码错误 | 数据库用户没有初始化 | 确认执行了 house_db.sql,并检查账号角色状态 |
| 房源列表分页错乱 | 前端页码从 0 开始与后端不一致 | 统一页码起点,让后端删除 PageNum-1 逻辑或前端调整 |
| 上传房源图片不显示 | 静态资源路径映射缺失 | 后端配置资源映射,或前端直接使用绝对 URL |
5. 二次开发方向与我的个人体会
5.1 这套源码适合扩展什么方向
系统基础功能完整,扩展性也预留了空间。如果你拿了这套源码不只是交作业,而是想做一个能实际落地使用的工具,我建议优先考虑这几个方向:
- 图片与附件管理:当前房源图片只是存了一个 URL 地址,可以进一步接入本地文件上传或对象存储,增加图片压缩和缩略图生成。
- 数据看板:管理员首页目前是最简单的统计数字,有精力可以加一个成交量趋势图、经纪人业绩排行,前端用 ECharts 就行。
- 房源匹配推荐:根据客户的购房需求(预算、区域、户型)和房源字段做规则匹配,自动推荐适合的房源列表。这个功能对中介来说价值特别高,实现也不复杂,写一个多条件打分函数即可。
- 合同 PDF 生成:根据交易数据生成标准购房合同 PDF,可以结合模板引擎或者报表组件,省去手写合同的麻烦。
5.2 动手改过之后的几点经验
这套系统我实际改过不止一轮,过程中有几条经验值得拿出来分享。
第一,数据库字段不要随手用 JSON 串存。早期版本为了省事,把房屋配套信息(地铁、学区、车位)拼成一个 JSON 字段存在表里,结果后续要按“学区房”条件筛选时,SQL 写起来极其痛苦。后来改成独立字段,查询效率和代码可读性都好了很多。
第二,房产系统的核心是“状态流转”,不是“增删改查”。前后端都要围绕状态机的概念来设计。比如房源有“待审核、在售、已下架、已成交”几个状态,前端每次展示状态标签时,不要硬编码文案,而是抽一个状态枚举映射表,这样以后加状态只改一处,不会出现前端显示“已售”、后端状态却是“已完成”这种不一致。
第三,debug 时先用接口层定位问题。很多新人一碰到页面数据不对,就先改前端代码,改了半天结果发现是后端的 SQL 或者返回字段问题。我的排查顺序是:看 Network 响应 → 调 Postman 直接请求后端接口 → 看后端控制台 SQL 日志 → 最后才动页面代码。这样能快速把问题锁定在前后端某一侧。
第四,日志务必分级别用。业务日志用 info,排查问题用 debug,不要在一个方法里连续打十几个 System.out.println。SpringBoot 自带的日志框架足够用,把控制台 SQL 日志打开,mybatis 执行语句一眼就能看到,排查问题效率能翻倍。
最后再说一个小技巧:如果接手这套项目,建议先完整跑一遍业务流程——管理员建账号、经纪人录房源、客户注册账号、经纪人带看、发起交易、完成交易。把这条链路走通,你对整套系统的理解深度远比你只看代码要高得多。我自己在部署类似系统时,习惯把这条主流程的测试脚本写好,每改一次代码就回归一遍,确保核心链路不被改坏,这比单测覆盖率更实在。