做 Java 全栈方向的课程设计或者毕业设计,选型的时候经常在“纯后端管理系统”和“带移动端的完整项目”之间来回犹豫。后端管理系统开发快、逻辑清晰,但演示起来缺少亮点;移动端项目视觉冲击力强,可是从 0 到 1 的工作量往往超出预期。我最近正好把一个基于 Spring Boot 和微信小程序的房地产销售管理系统完整整理了出来,附带源码、设计文档、运行视频和讲解视频,这算是全栈实战里很典型的一个项目样本:后端用 Java Spring Boot 提供接口,前端不写 App,而是用微信小程序承接购房用户的浏览、预约、认购操作,另外再配一个 Web 管理端给售楼处人员做楼盘、房源、订单和客户数据的管理。
这篇文章我会把房地产销售管理系统的整体设计、核心模块拆解、关键代码实现、部署联调过程和排坑经验完整讲一遍。不管是准备拿它做毕业设计、课程项目,还是想找一个能写到简历上的全栈练手项目,这份拆解都能帮你少走很多弯路。有些细节属于做的时候踩过坑、后来补上的经验,常规的项目文档里基本不会写,建议重点看第 4 章和第 6 章。
1. 系统定位与核心功能全景拆解
1.1 这个系统解决了什么问题
房地产销售,尤其是新房销售,流程上有很强的线下属性,但也存在大量重复性的信息登记和状态流转工作。传统做法是销售顾问拿纸质台账或者 Excel 记录客户看房记录、意向房源、认购信息,数据分散、容易丢失、统计效率低,管理层想看实时销售情况还得等日报。这个系统的核心目标,就是把“楼盘展示、在线预约看房、认购登记、销售跟进、数据统计”这条链路搬到线上,让购房用户通过微信小程序就能看到楼盘信息和可选房源,让销售团队通过管理后台维护房源状态和客户跟进记录。
从项目的完整性角度看,它不是一个只有增删改查的 demo,而是覆盖了真实业务场景里比较关键的状态流转:房源从“可售”到“被预约”再到“认购锁定”或者“已售出”,每一步都有据可查。这样做的好处是,当你要拿这个项目去面试或者答辩时,能讲清楚的不只是“我写了 CRUD”,而是“我理解业务状态如何映射到系统设计上”,这个差别在评审眼里是很明显的。
从学习路径的角度看,这个系统的技术栈组合也很有代表性。后端是 Java Spring Boot,负责业务逻辑和接口输出;小程序端使用了微信官方的小程序框架,负责用户触达和交互;两者之间通过 JSON 格式的 HTTP 接口通信。这里有 RESTful API 设计、数据库表关系设计、会话登录态维护、文件上传、权限区分等常见开发场景,一套流程走下来,对全栈开发的认识会完整很多。
1.2 角色划分与业务流程梳理
任何管理类系统,第一件事就是把角色理顺。房地产销售管理系统一般拆成三类用户,对应三种不同的界面和权限边界。
购房用户,也就是 C 端,通过微信小程序进入系统。他需要刷一刷楼盘列表,看看每个楼盘下面有哪些户型、价格区间、开盘状态、户型图,选中意向房源后可以提交预约看房申请。用户首次进入时会做微信授权登录,后续再看房记录、我的预约、我的认购状态,都是围绕这个登录身份展开的。小程序端的设计重点不是“功能多”,而是路径短、信息直观,让用户三步内能找到房源并发起预约。
销售顾问和管理员,对应 Web 管理后台。销售顾问登录后看到自己名下的客户和预约单,可以给客户录入跟进记录、登记认购订单;管理员偏向全局视角,可以维护楼盘信息、楼栋单元、房号数据、价格参数,审核预约,统计销售数据。这里的权限设计没必要做得太复杂,基于角色的判断就够用了,管理员和销售在菜单和数据范围上做区分,避免越权操作。
在业务流程上,我建议你用一条主链路去理解这个系统:管理员录入楼盘和房源 → 小程序端展示可售房源 → 用户浏览并发起看房预约 → 销售顾问在后台处理预约 → 用户到访后认购下单 → 房源状态变为已售或保留。这个链条里的每一个节点,都对应着数据库里某张表的状态变化。把这个流程画清楚后,后面的代码开发顺序基本就排出来了。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术选型与整体架构设计
2.1 后端为什么选 Spring Boot 而不是其他框架
Spring Boot 在 Java 生态里已经属于绝对主流的快速开发框架,尤其适合这类单体应用。选它首先不是因为“新”,而是因为它解决了 Spring 早期繁琐的 XML 配置问题,通过自动配置和 starter 机制把开发重心拉回到业务代码上。对于课程设计和中小型项目,Spring Boot 内置的 Tomcat、默认的配置策略,以及和 MyBatis Plus、Redis 等组件的整合方案都相当成熟,社区资料也多,遇到问题基本都能搜到解决方案。
这套系统里用到的后端组件包括:Spring Boot 负责 Web 层和依赖管理,MyBatis Plus 做 ORM 映射和数据操作,MySQL 存储业务数据,Redis 做验证码缓存和用户会话状态维护,Swagger 生成接口文档,Maven 做项目构建。有的同学会纠结“要不要用微服务”,我的建议很直接,除非你有十个人以上的开发团队或者需要独立扩容某个模块,否则单体应用就是最合理的方案。为了技术而技术,结果就是把自己绕进分布式事务和链路追踪的坑里,得不偿失。
还有一点需要强调,Spring Boot 的版本选择会影响后续开发体验。如果是为了跑通项目和配合文档,不要一上来就追最新大版本,因为最新版本可能对 JDK 版本有要求,部分第三方 starter 还没来得及适配。建议使用 Spring Boot 2.7.x 配合 JDK 1.8,这是当前兼容性最稳的组合。等到项目跑通了,再考虑要不要升级到 Spring Boot 3.x,而不是在项目起步阶段就给环境适配增加变量。
2.2 小程序端与后端接口如何配合
微信小程序的开发语言虽然长得像前端三件套,但它不是直接跑在浏览器里的,有自己的一套运行环境,所以和后端接口打交道时需要特别关注几个细节。小程序通过 wx.request 发起网络请求,但是请求地址必须是 HTTPS 或者已在开发者工具中开启“不校验合法域名”。正式上线前,你需要在微信公众平台把后端接口的域名配置到 request 合法域名里。如果赶时间只想做本地演示,那么后端接口用 HTTP,并在开发者工具里勾掉域名校验即可。
前后端的数据交互统一使用 JSON 格式,RESTful 风格比较清晰。我做这个项目时,小程序端的请求工具单独封装了一个 request.js,统一处理 baseURL、请求头 token 注入、响应码拦截和错误提示。这样业务页面里只需要写具体的接口路径和参数,不用重复处理登录过期或网络异常的逻辑。接口响应统一设计成 { code: 200, message: "success", data: ... },前后端约定好这个 envelope 结构后,联调时能省掉不少口头沟通成本。
关于跨域问题也提醒一句。小程序端不像浏览器那样受同源策略的严格限制,但 Web 管理后台如果部署在另一个端口或域名,就会出现跨域请求。后端可以通过配置跨域过滤器或者直接使用 Spring Boot 的 @CrossOrigin 注解处理,注意要在网关层统一配置,不要让每个 Controller 都写一遍。
2.3 项目整体目录结构与分层职责
后端代码我习惯按经典的三层结构组织:Controller 层接收请求参数并返回统一响应,Service 层处理业务逻辑,Mapper 层通过 MyBatis Plus 操作数据库。这个分层方式看起来“老”,但是对中小型项目来说收益最高,因为每层的职责单一,出了问题时能快速定位。如果你用了 MyBatis Plus,那么 Mapper 层的常规单表查询基本不需要手写 SQL,只有涉及多表关联或复杂统计时才需要自定义 XML 文件。
entity 包里放的是和数据库表字段一一对应的实体类,vo 包里放的是面向接口输出的视图对象,dto 包处理前端传入的参数对象。为什么要分开?因为直接拿实体类去接收前端参数,很容易把不该暴露的字段也暴露出去,比如用户表的密码。虽然这个系统用户密码主要存在管理端,但尽早养成接口隔离的习惯肯定没坏处。
小程序的代码结构也很重要。pages 目录按业务模块拆分:home 首页、houseList 房源列表、houseDetail 房源详情、reserve 预约、user 个人中心。公共的 utils 目录放请求封装和日期格式化方法,components 目录放可复用组件,比如房源卡片组件。这块结构在项目开头就要定好,不然后面页面多了,找文件都费时间。
3. 数据表设计与业务模型拆解
3.1 核心表和字段设计背后的思路
房地产销售管理系统涉及的实体,包括用户、楼盘、房源、预约单、认购单、跟进记录、管理员。数据库设计是这个项目真正见功夫的地方,评审或者面试官经常先从表结构切入提问。
我列一下核心表的设计思路:
building(楼盘表):楼盘名称、区域、地址、均价、开盘日期、建筑类型、楼盘封面图、描述、状态。这里的状态可以区分“即将开盘”、“在售”、“售罄”,方便小程序首页做筛选。house(房源表):关联楼盘 ID,房号、楼栋、单元、楼层、户型、建筑面积、总价、单价、朝向、装修状态、房源状态。房源状态建议用整数枚举,比如 0-可售、1-预约中、2-认购锁定、3-已售。这个状态是整个系统的核心状态位。user(用户表):微信用户的 openid、昵称、头像、手机号、注册时间。注意 openid 是用户在小程序生态里的唯一身份标识,它不能当密码用,也不能暴露在接口响应里,但在后端却是判断用户身份的关键字段。reserve(预约看房表):关联用户 ID、房源 ID、预约时间、联系人、联系电话、状态(待处理/已确认/已取消/已完成)、备注。order(认购单表):关联用户 ID、房源 ID、销售员 ID、认购金额、定金、认购时间、状态。follow_record(跟进记录表):关联客户 ID、销售员 ID、跟进内容、下次跟进时间。这张表主要服务于销售人员的日常管理。
看房预约和认购在表关系上是一对多的关系,一个用户可以预约多个房源,但最终一条认购订单只能针对一个确定的房源。房屋状态变迁时要考虑并发问题,比如两个用户同时点击同一套房源的预约按钮,如果不加控制就可能出现重复预约。处理办法有两种:一是数据库层面给房源状态加上乐观锁判断,二是在后端 Service 层加分布式锁。考虑到项目复杂程度,我在实现时用了一个很朴素的方案:更新房源状态的 SQL 语句里加上 WHERE state = 0 这样的条件,如果影响行数为 0,说明状态已经被别人改了,直接提示“房源已被预约”。
3.2 字段设计上容易踩的坑
关于价格字段,很多人习惯用 double 或者 float,这在涉及金额计算的场景里是禁忌。由于二进制浮点数无法精确表达大部分十进制小数,累计或者比较时会出现微小误差,比如 0.1 加 0.2 不等于 0.3。正确做法是使用 Decimal 类型,Java 端用 BigDecimal,数据库字段用 DECIMAL(10,2),这样可以最大限度地避免金额精度问题。如果考虑将来有分账或者高精度计算需求,甚至可以直接用 DECIMAL(10,2) 存储元,或者用整数存“分”。这个细节在答辩时讲出来是很加分的。
关于时间字段,建议直接用 datetime 存储业务时间,Java 端使用 LocalDateTime 接收。不要用字符串存时间,排序和范围查询都会出问题。创建时间和更新时间这类字段,可以在 MyBatis Plus 的实体类上使用 @TableField(fill = FieldFill.INSERT) 和 @TableField(fill = FieldFill.INSERT_UPDATE) 注解配合 MetaObjectHandler 自动填充,避免每张表的 insert 语句都要手动 set 一遍。
关于软删除,用户下的预约记录、房源维护记录这些数据不建议物理删除,因为业务上经常需要追溯历史。我一般会统一加一个 deleted 字段,默认 0,删除时执行 update 而不是 delete。MyBatis Plus 里有现成的 @TableLogic 逻辑删除注解,配置好后所有查询都会自动带上 deleted = 0 条件,使用成本很低。
4. 核心业务模块的完整实现过程
4.1 登录鉴权:从微信登录到后端 session 维护
小程序端登录流程和传统网页登录有本质区别。小程序里没有用户名密码输入框,而是通过微信的 wx.login 接口获取一个临时凭证 code,然后把这个 code 发给后端。后端拿到这个 code 调用微信的 jscode2session 接口,换取用户的 openid 和 session_key。这里 openid 是用户在该小程序下的唯一标识,session_key 是微信会话密钥,用于解密用户手机号等敏感信息。
拿到 openid 后,我建议不要每次请求都去微信那边交换信息,而是自己维护一套会话机制。常见做法是生成一个自定义 token(比如 UUID),以 token 为 key、用户 ID 为 value 存到 Redis,并设置过期时间为 7 天,然后把 token 返回给小程序。小程序每个请求都在 header 里带上这个 token,后端用一个拦截器统一校验。这个方案的好处是,拦截器只要判断 Redis 里 token 是否存在,就能快速识别用户身份,不用频繁查询数据库,也能在服务端主动控制会话失效。
写这个模块时有几个容易遗漏的点。第一个是 wx.login 的 code 有效期只有 5 分钟,而且只能用一次,所以后端要做异常捕获,用过的 code 再请求微信接口会报 invalid code。第二个是用户首次登录后,如果数据库查不到记录,要自动注册一条用户数据,并把用户的昵称头像从默认值更新为微信资料。第三个是手机号的获取,现在微信平台已经不建议通过前端传手机号到后端保存,而是需要用户点击授权按钮,由前端把动态令牌(phone code)传给后端,后端再用 access_token 调用微信接口解密手机号,这个接口需要在小程序后台申请开通。
4.2 楼盘与房源管理:后端数据维护的细节
楼盘和房源的管理主要发生在管理后台上。管理员录入一个新楼盘时,除了基础文本字段,还要处理封面图上传,这里涉及文件上传功能。Spring Boot 处理文件上传很简单,MultipartFile 接收文件后,存储到本地磁盘或者云存储即可。做课程设计或者本地演示时,我建议存本地目录,然后通过配置静态资源映射把 /upload/** 路径映射到实际磁盘目录,小程序端显示图片时只需要拼接域名和相对路径。
房源录入时,比较适合用批量生成的方式处理。如果一个几十层的楼盘每层有八户,一栋楼就有几百套房源,一套一套手工录入显然不现实。我做了楼层和房号规则配置,管理员输入楼栋号、起始楼层、结束楼层、每层户数后,由后端逻辑循环批量生成房源记录。每套房源的面积和价格可以按楼层调整系数自动计算,也可以在生成后再单独编辑。
小程序首页要展示楼盘列表,我建议在这个模块里做一个按“热销中”和“最新开盘”排序的逻辑。销量数据可以从认购单表统计,但每次实时统计对数据库压力有点大。做这个项目时,我在 building 表里加了冗余字段 sold_count 和 view_count,每次订单状态变为已认购时同步更新楼盘的已售数量。这种冗余方式虽然不够“范式化”,但实际开发中非常常用,可以显著减少联表查询的次数。
4.3 预约看房与认购状态流转
预约看房是小程序端的核心动作。用户进入房源详情页看到“立即预约”按钮后,小程序端会弹出一个表单,要求选择参观时间并填写联系手机。提交前前端要做手机号格式校验,后端也要再校验一遍,防止绕过前端直接调用接口传入非法数据。
后端处理预约请求时,顺序是:判断用户是否登录、判断房源是否存在且可售、检查是否已经预约过同一房源、插入预约记录、更新房源状态为预约中。这里如果用户取消了预约,房源状态需要回滚为可售。销售顾问在后台看到待处理的预约记录后,可以手动确认,也可以取消预约,被取消时系统需要把原因推送给用户。消息推送这块如果不想接入微信订阅消息,可以先做成在小程序“消息中心”里展示通知记录的形式,实现成本低且效果直观。
认购订单流程相对更复杂。用户到售楼处实地看房后,如果确定要买,销售顾问会在后台代用户创建认购单,并选择房源和关联的预约记录。创建认购单时后端必须再次校验房源状态,避免订单操作期间房源被别人锁定。认购成功后,房源状态变为认购锁定,用户能在小程序端“我的认购”中看到该订单。如果用户在约定时间内未支付定金,后台可以手动解锁房源,让它重新进入可售池。
我在做这一步时发现,设计状态机是很有用的。定义一个状态流转枚举,把房源所有允许的状态变化集中管理起来,比如可售只能变到预约中或认购锁定,预约中只能变回可售或变为认购锁定。这样在代码里只要一个方法的判断,就能避免到处散乱的条件分支。
4.4 管理端数据看板与统计报表
系统还有一个不可忽视的模块,就是首页数据看板。管理员登录后,需要直观地看到本月新增客户、预约到访率、认购数量、成交金额、楼盘去化率等核心指标。这些数据如果每个指标都单独去数据库做聚合查询,SQL 写起来会非常琐碎,而且多个统计维度叠加后性能也不好。
我在实现时做了一个折中方案。针对核心统计指标,比如总楼盘数、可售房源数、累计认购数,使用聚合 SQL 在 house 和 order 表上直接计算;针对历史趋势数据,比如近 7 天预约量,则通过日期分组查询。后端返回给前端的数据结构在一个 Map 或者专门的 StatVO 对象里,避免页面多次请求。如果你想做得更“专业”一些,也可以每天晚上用一个定时任务把日报结果生成到一张独立的统计表里,查询时直接读统计表。但这属于可扩展项,不是第一步需要实现的内容。
值得留意的是,管理端的权限控制不能只依赖前端隐藏按钮,所有涉及删除、修改状态的接口,在后端都需要根据当前登录用户角色做校验。我在这个系统里用一个简单的注解和拦截器处理了 @RequireRole("admin"),如果角色不匹配,直接返回无权限提示,而不是走业务逻辑。这种防御式编程让系统更安全,面试中也值得单独提一下。
5. 部署联调与服务上线要点
5.1 本地开发环境如何快速跑起来
要把这个项目从源码变成本地可运行的系统,环境准备顺序很重要。我按自己的实操经验整理了几个步骤,每一步卡住都可能让你花费大量时间。
第一步是安装 JDK 1.8 并配置环境变量,配好后在命令行执行 java -version 能正常输出版本号才行。第二步是安装 MySQL 5.7 或 8.0,创建数据库并导入项目提供的 SQL 文件,注意数据库编码为 utf8mb4,否则小程序端存用户昵称里的表情符号时会报错。第三步是安装 Redis,启动 Redis 服务后要确认 6379 端口能连通。第四步是用 IDEA 打开后端源码,等待 Maven 下载依赖。此时要确保 Maven 的 settings.xml 配置了国内镜像源,不然下载 Spring Boot 依赖时速度会让人崩溃。第五步是修改 application.yml 里的数据库连接、Redis 连接、文件上传路径等配置,然后启动项目,看到 Spring Boot 启动成功的日志就说明后端已就绪。
如果你在本地没有安装 Redis 也没有关系,可以临时把验证码缓存和 token 存储相关代码配置成本地内存模式,但这个修改只建议开发环境使用,项目默认配置还是要保留 Redis 方案。用 IDEA 开发时,热部署插件 spring-boot-devtools 建议打开,改完代码按 Ctrl+F9 能自动重启,开发效率提升明显。
5.2 小程序端登录配置与接口联调
小程序端在正式联调前,有两个地方必须配置。一个是在 app.js 或者配置文件中把 baseUrl 改成你本机的局域网 IP,比如 http://192.168.x.x:8080,不要用 localhost。因为小程序开发者工具模拟器和手机真机预览连接的不是同一个网络环境,如果手机和电脑在同一局域网,用局域网 IP 才能让真机访问到后端的接口。另一种是如果我们只做开发者工具预览,那直接填 http://localhost:8080 也能跑通。
第二个配置是微信公众平台的 AppID。注册一个个人小程序,拿到 AppID 后填入开发者工具的项目配置里。登录模块调 wx.login 时,只有真实 AppID 才能获取到 code,再用 code 去后端换取 openid。如果只是纯测试,也可以使用测试号,但测试号换取的 openid 会和正式 AppID 不一致,这一点在后续管理后台看用户数据时要留意。
前后端联调时建议先把 Swagger 接口文档打开,对照文档检查每个接口的参数名和返回结构。Spring Boot 项目集成 Swagger 后,访问 /doc.html 或 /swagger-ui/index.html,就能看到所有接口定义,比前端开发自己去翻后端代码高效得多。
5.3 服务器部署可以考虑的两种方案
项目做完了要部署给别人演示或者上线,通常有两个方向。
一种方案是直接在云服务器上部署,适合正式的演示环境和毕业设计答辩。具体步骤是:用 Maven 打包后端项目,执行 mvn clean package -DskipTests,得到 jar 包后上传到服务器,使用 nohup java -jar xxx.jar & 命令后台运行。前端小程序本身不需要部署,它是托管在微信平台的,只要提交审核发布就可以。管理后台如果也是 Web 端,打包后的静态文件可以放到 Nginx 里并配置反向代理,把 /api 开头的请求转发给后端服务。服务器上还要安装 MySQL 和 Redis,并将数据库初始化脚本导入。
另一种方案是使用 Docker 做容器化部署,适合简历上想写容器化经验的场景。编写 Dockerfile 把后端镜像构建好,再用 Docker Compose 编排 MySQL、Redis、后端服务这几个容器。springboot 项目打成镜像后发布,只要服务器上装了 Docker,就能做到一键启动。需要注意的一点是,容器里的服务之间要使用服务名通信,例如后端服务连接数据库的地址要写成 jdbc:mysql://mysql:3306/xxx,而不是 localhost。
无论选择哪种部署方案,都要记住一个配置原则:配置文件里的环境变量通过 -D 参数或者环境变量注入,不要把服务器上的密码直接写在源码里再提交到代码仓库。源码和文档交付时,可以在文档里写上默认密码,但实际部署还是要修改成自己的强密码。
6. 常见问题排查与避坑指南
6.1 后端启动和接口访问问题
这个项目最容易出现的问题之一,是 Spring Boot 启动时报数据库连接失败。常见原因包括 MySQL 没有启动、密码错误、数据库名不一致。排查方法很简单:先在命令行用 mysql -u root -p 登录数据库,确认密码和服务地址正确,再检查 application.yml 中的 url 是否带了 useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai 参数。时区参数如果缺失,MySQL 8.x 连接时会报时区错误。
另一个常见问题是访问接口时报 404 或 405。404 一般是路径写错,可以对比 Swagger 文档和前端请求路径;405 通常是用错了请求方法,比如前端用 POST 请求了本来定义为 GET 的接口。Spring Boot 的 Controller 层注解要仔细检查,这种错误一般看控制台日志就能发现。
还有一类问题出在 MyBatis Plus 的 SQL 上。如果接口报 Invalid bound statement,往往是 Mapper 接口和 XML 文件没有对应上,查看 XML 的 namespace 和 mapper 文件的路径是否配置到 mybatis-plus.mapper-locations 中。如果执行 update 语句影响行数为 0,不要先怀疑语法,优先检查查询条件是否拼错,特别是带有逻辑删除的表,MyBatis Plus 会自动追加 deleted = 0 条件,如果 SQL 里手动加了别名,就可能导致条件拼错。
6.2 小程序调用后端接口失败的典型场景
开发者工具里最常见的报错是 request:fail,这通常意味着后端根本不可达。排查顺序是:先在浏览器直接访问后端接口的 Swagger 页面看服务是否启动,如果浏览器能访问但小程序请求失败,那就检查小程序工具里面是否勾选了“不校验合法域名、web-view(业务域名)、TLS 版本以及 HTTPS 证书”。开发阶段勾选这一项,很多域名校验的问题就消失了。
真机调试时有一个大坑。手机如果开了蜂窝数据,就无法访问你电脑上的局域网后端,因为不在同一个内网里。解决办法是:让手机连接和电脑同一个 Wi-Fi,并且在微信开发者工具右上角打开“真机调试”,此时手机会通过扫码方式建立一个调试通道,能访问开发机上的接口。如果用了云服务器部署后端,直接用公网 IP 访问,就不用担心局域网问题了。
小程序里还有一个常用问题,是使用 wx.request 请求时没有设置请求头导致后端无法识别 JSON。如果你后端用 @RequestBody 接收参数,小程序请求必须加上 Content-Type: application/json,否则后端会把请求体里的 JSON 当成 Form 表单数据,最后参数解析成 null,接口报参数缺失。这个小问题我曾经排查了半小时,看上去简单,但极易被忽视。
6.3 数据状态不一致和金额显示问题
房源状态不一致的情况主要出现在预约和认购的并发场景里。如果你发现同一个房源被预约了两次,需要检查 update 语句是否带了状态条件。不要只在 Service 里先查询再判断,并发情况下两条线程可能同时读到“可售”状态,然后都执行后续逻辑。最稳妥的解法就是我在 3.1 节里提到的:将判断和更新放在一条 SQL 中执行,在 Mapper 层写带条件的 update。
金额显示问题则要注意前后端的数据类型匹配。MySQL 的 DECIMAL 字段用 BigDecimal 接收后,返回给前端时如果直接序列化成数字,会有精度丢失风险。建议在字段上使用 @JsonSerialize(using = ToStringSerializer.class) 转换为字符串输出,前端展示金额时再按需格式化。这个做法在涉及订单金额数据时是很有必要的,不要偷懒省略。
6.4 项目答辩演示时的几个加分操作
答辩时与其机械地演示增删改查,不如有意识地展示几个亮点功能。比如可以现场操作小程序端预约一个“可售”房源,然后打开管理后台看到预约记录变成“待处理”,管理员确认后回到小程序看状态变化。这种从前端到后端再到前端的状态联动,能直观体现出你理解数据流的完整性。
还可以做一个小实验来展示你对并发控制的理解:开两个浏览器窗口同时进入管理后台,对同一套房源点击认购。一个会成功,另一个会提示房源状态变更。这个现象解释起来很加分,因为很多同学根本没想到并发问题。
如果想要进一步展示你的系统设计能力,可以现场打开数据库,执行几条 SQL 做统计查询,比如“每个楼盘的房源去化率”“近一个月的认购趋势”,配合图表展示。虽然这些功能在系统里可能已经有页面了,但当众演示你能熟练操作时,观感会完全不一样。
7. 代码之外的交付物和心得建议
源码、文档、运行视频、讲解视频,这几个交付物在这个项目里其实各司其职。源码是核心,文档负责讲清楚系统怎么跑起来、模块怎么设计的,运行视频是为了让人在没搭建环境前就快速预览效果,讲解视频则是用来梳理设计思路和关键代码实现。如果你是用它做毕业设计,建议把运行视频提前录好,因为答辩现场经常出现服务器没启动或者网络不通的意外,有一个提前录制的无卡顿演示视频可以兜底。
写开发文档时,不要只写操作步骤,要把核心表结构、接口清单、环境配置、常见问题这四块都带上。很多同学的文档就写了一个“怎么导入项目”,这远远不够。评审老师可能会翻你的文档看数据库设计是否合理,看接口设计是否规范,所以文档里至少要有数据表的设计说明和核心接口的 curl 示例,这样才能充分体现工作量。
在完整梳理这个项目的过程中,我自己的体会是:选一个有业务纵深的全栈项目去练手,比做十个简单的待办清单都有用。房地产销售管理系统的业务链条足够长,从 C 端小程序到后台管理,从预约状态流转到认购订单,每一步都能逼着你去做设计上的取舍。你做完一遍后,再去学 Redis 缓存、消息队列、分布式锁这些进阶知识,就会自然地想到“之前的系统哪里可以用到”,而不是生硬地背面试题。课程的代码看十遍不如亲手调通一遍,真出问题时学到的东西,一定比顺利跑通时更多。
