资讯动态

Spring Boot鲜花预售系统毕设全解析:从状态机到库存预占

发布时间:2026/10/22 8:03:34 来源:尧图企业网站定制
又到毕业设计选题的日子最近收到好几个学弟学妹的私信问的都是同一个题号“基于Springboot鲜花预售系统——毕设附源码57899”。这题在各类毕设资源清单里出现频率很高但我发现大多数人只关心“怎么把源码跑起来”很少有人去拆解这套系统背后的业务逻辑。我帮你把整套项目完整看了一遍从前端页面到后端数据库、从登录流程到预售状态流转今天一次性把该讲的地方全讲透。文章会覆盖项目设计、表结构、核心业务实现、本地运行步骤和答辩高频问题哪怕你之前只写过增删改查我也尽量让你看完之后能独立把项目讲清楚。为什么这个题值得选因为它本质上是“电商系统 预售场景”的组合普通商城该有的用户、商品、购物车、订单它都有但“预售”两个字会带出定金支付、尾款补缴、库存预占、活动上下架这些额外的业务规则。对毕设来说这正好是加分点你既不需要从零设计一个复杂的电商中台又能在一两个核心模块里展示出真正的业务思考。1. 项目定位与整体设计思路1.1 为什么“鲜花预售”是毕业设计的好选题先说一个很多人没注意到的点鲜花是一个强时令、强场景的商品。情人节、母亲节、毕业季、教师节这些特定时间点的需求量会瞬间拉高。如果商家按照“现货买卖”来做备货少了不够卖备货多了卖不完损耗还高得吓人。预售模式正好解决这个问题用户在活动期间先下单锁定价格和数量平台汇总预售数据后再统一采购采购成本更低浪费也更少。放在毕业设计里这个业务场景的价值在于它天然有“状态”和“时间”的概念能自然引出状态机、定时任务、库存扣减等进阶知识点而不是一个纯 CRUD 项目。老师看到你的设计说明书里写了订单状态怎么流转、超时未支付怎么回滚库存、尾款支付窗口怎么控制答辩时能聊的内容就丰富很多。当然它也有地雷预售业务如果只做成“商品表加一个预售字段”那这个系统名不副实答辩大概率被问住。所以后面要重点把预售活动的完整生命周期弄清楚。1.2 整体功能模块与用户角色这个系统从角色上分成两端普通用户端注册登录、浏览鲜花、查看预售活动、提交预售订单、支付定金、支付尾款、订单查询、申请退款、个人资料管理。管理员端鲜花分类与商品管理、预售活动创建与上下架、订单管理、配送管理、用户管理、销售数据统计。把角色拆清楚之后代码结构就很好对应了。后端一般会按controller、service、mapper、entity分层管理端接口和用户端接口分开权限用拦截器或安全框架控制。功能模块里最容易被忽视的是“配送管理”。鲜花不是普通快递它讲时效经常需要同城配送或有指定的自提时间窗。很多从网上下载的源码都把配送做成一个纯备注字段这其实是缺失。你在设计说明里如果能提出“按预售活动设置配送批次、按尾款支付时间分批发货”的方案会显得你对业务场景的考虑比一般人深入。1.3 技术选型解析这套源码使用的技术栈非常主流放到简历上也不会寒碜Spring Boot 2.x负责整个后端骨架依赖管理和自动配置省掉大量重复工作。MyBatis Plus做 ORM 映射单表操作几乎不用写 SQL自带分页查询。MySQL存业务数据表结构清晰事务支持成熟。Redis做缓存和登录令牌存储顺带可以扛一部分并发访问压力。Vue 前端框架后台管理页面通常用 Vue 搭配组件库前端通过接口对接后端。Maven依赖和构建管理。一套主流 Java 毕设配置面试官看了不会皱眉头老师也挑不出硬伤。尤其是 Redis 的存在让“缓存”“并发”这些词都能在答辩里非常自然地讲出来。不过我要多说一句技术栈主流不等于代码质量一定好。有些流传出来的项目Redis 不过是拿来做工具类的装饰实际调用很少。如果你想让项目更有说服力建议重点检查并补上这两处一是登录状态为什么需要 Redis二是库存预占如何借助数据库乐观锁保证不超卖。后面我会逐一展开。2. 数据库与核心表设计2.1 商品与预售活动建模数据库是这类毕设的灵魂表设计对了写代码就是体力活表设计错了后面改起来想哭。核心表通常有以下这些用户表、鲜花分类表、鲜花信息表、预售活动表、订单表、支付流水表、配送信息表。鲜花信息表和普通商品表类似重点字段是名称、分类、封面图、单价、库存、上下架状态。这里有一个坑鲜花通常按“束”“支”计数字段类型用整数没问题但单价一定不要用 float必须用DECIMAL(10,2)否则金额计算会出现浮点误差这是答辩时老师很爱挑的刺。预售活动表才是系统的核心。我建议至少包含这些字段CREATE TABLE tb_presale_activity ( id BIGINT PRIMARY KEY AUTO_INCREMENT, flower_id BIGINT NOT NULL COMMENT 关联鲜花, activity_name VARCHAR(200) COMMENT 活动名称, deposit_amount DECIMAL(10,2) COMMENT 定金金额, final_amount DECIMAL(10,2) COMMENT 尾款金额, total_amount DECIMAL(10,2) COMMENT 预售总价, presale_stock INT DEFAULT 0 COMMENT 预售库存, start_time DATETIME COMMENT 预售开始时间, end_time DATETIME COMMENT 预售结束时间, final_pay_start_time DATETIME COMMENT 尾款开始时间, final_pay_end_time DATETIME COMMENT 尾款截止时间, status TINYINT COMMENT 0未开始 1预售中 2尾款中 3已结束 4已取消, create_time DATETIME DEFAULT CURRENT_TIMESTAMP );注意这里我把“尾款支付时间段”单独拆成了两个字段而不是简单复用预售结束时间。为什么因为在真实鲜花预售业务里定金支付和尾款支付往往是两个窗口期。比如 2 月 1 号到 2 月 10 号交定金2 月 14 号当天零点到晚上十二点补尾款。如果不区分这两个窗口系统就没法自动判断用户当前处于什么阶段。这一处小设计答辩时拿出来讲可以很好地体现你的业务理解力。2.2 订单、支付与配送链路订单表和普通商城订单最大的区别是它需要记录“定金已付、尾款未付”等中间状态。我建议的订单状态枚举是这样的0 待支付下单成功但定金未支付通常是限时状态。1 已付定金定金支付成功等待尾款窗口开启。2 已付尾款尾款已补齐订单进入待发货。3 已发货平台生成配送单或通知用户自提。4 已完成用户确认收货或系统自动确认。5 已取消超时未支付定金或用户在未付尾款前主动取消。6 退款中用户申请退款管理员审核处理。订单表里要至少要有一个订单编号字段并且建立唯一索引这是对账和防重复的关键。支付流水表建议单独建不要和订单表混在一起因为它记录的是每一次支付动作支付单号、金额、支付方式、回调状态、回调时间。有了这张表之后排查“用户明明支付成功了订单却没更新”这种经典问题时才能快速定位。配送信息表可以直接关联订单 ID记录收货人、电话、地址、配送时间窗口、配送批次、配送员备注。如果做的是本地自提模式就把配送地址换成自提点再增加一个“自提码”字段逻辑大同小异。2.3 表设计中的并发与约束细节数据库表不是把字段列出来就完事了约束和索引才决定系统能不能抗住并发。这里有几个非常实用的细节订单号必须唯一。最简单的方式是用时间戳加随机数或者用 Redis 生成自增序列。无论哪种方式数据库层都要加唯一索引防止并发情况下重复插入这是兜底方案。库存字段要加条件更新。直接在代码里select再update会遇到超卖问题更稳妥的做法是依靠一条带条件的 SQL把库存扣减和库存检查合并成一个原子操作。时间字段统一存 datetime。前端传什么格式不重要后端一律转成标准时间再入库避免“2024-03-01 与 2024-03-1“这种格式大乱斗。数据库连接的 url 也要加上serverTimezoneAsia/Shanghai否则时间偏差八小时的坑就等着你踩。金额字段用 BigDecimal。Java 后端接收金额时不要用 double数据库里用DECIMAL前端展示时保留两位小数。涉及定金、尾款、退款、优惠的任何计算都统一走 BigDecimal不该在业务代码里出现浮点数运算。这三条细节并不复杂但很多从网上流传的项目源码本身都没做好。你自己动手改一遍把隐患补上这段经历本身就是答辩素材。3. 核心业务逻辑实现要点3.1 登录鉴权与权限控制用户端和管理员往往共用一个登录接口靠角色字段区分权限。比较省事的做法是使用 Spring Security 配合 JWT 令牌用户登录成功后签发一个 token之后每次请求在请求头里带上Authorization: Bearer xxx后端拦截器校验 token 并解析出用户 ID 和角色。为什么不把会话直接存内存里因为项目里既然引入了 Redis最常见的做法是把登录 token 存一份到 Redis设置过期时间比如 24 小时。这样每次请求拦截器先从 Redis 里查这个令牌是否有效还能快速实现“管理员强制下线用户”这类操作——把对应 token 从 Redis 里删掉就行。如果纯用数据库或内存会话这个功能实现起来会麻烦得多。前端路由也需要配合做一层跳转拦截未登录用户访问个人中心或管理页面时直接跳回登录页管理员角色访问用户接口时后端要返回 403。这层校验前端只能防君子真正的权限判断必须放后端这是安全常识。3.2 预售流程的状态机实现预售的核心流程就是一个状态机你要让程序能根据时间自动判断当前属于哪个状态而不是靠管理员手动改状态。后端可以写一个定时任务活动开始时间到了把状态从“未开始”改为“预售中”。预售结束时间到了把状态改为“尾款中”此时用户才能补尾款。尾款截止时间过了把状态改为“已结束”未支付尾款的订单自动取消。库存不足或管理员手动终止状态改为“已取消”。这里用 Spring Boot 自带的Scheduled注解就能实现配合一个定时任务方法定期扫描活动表判断时间。虽然轮询的精度不是最高但毕设场景足够用。如果你要显得更专业一点可以在数据库记录一个“上次执行状态”每次只对待更新的活动做批量更新减少无谓扫描。用户下单的流程大概是选择预售活动 - 创建订单状态为待支付- 支付定金 - 状态变为已付定金。注意在下单那一刻就应该把活动库存预占掉而不是等定金支付成功再扣库存。为什么我们来想一想活动库存只有 100 份如果 200 个人同时下单而不占库存等活动一开卖瞬间就超售了。预占库存的方案是下单时直接扣减活动库存如果用户超过 30 分钟没支付定金系统定时任务把未支付订单取消同时把库存加回来。3.3 库存预占与超卖规避库存预占是预售系统里最容易翻车的地方。代码上最容易犯的错误是先查询活动库存 判断库存 0 然后执行更新库存减 1这个写法在并发量高的时候两个请求同时查到了库存为 1都会通过判断然后各自执行减 1最终库存变成 -1这就是超卖。正确做法是把判断和扣减放在同一条 SQL 里UPDATE tb_presale_activity SET presale_stock presale_stock - 1 WHERE id #{activityId} AND presale_stock 1这条语句执行后如果返回值是 1说明扣减成功如果返回值是 0说明库存已经不足下单失败。MyBatis Plus 里你可以直接在 Mapper 里写这个注解 SQL非常简单。这个优化是项目的点睛之笔答辩时值得重点讲清楚“为什么之前会超卖加了条件之后为什么不会”。3.4 管理端数据统计管理端通常还要有一个数据统计仪表盘显示今日销售额、订单总数、预售活动参加人数、热销鲜花排行。这些数据在毕设阶段不需要实时精确到秒级最简单的实现方式就是写几条带GROUP BY的 SQL 聚合查询。不建议为了统计功能去引入一套完整的数据分析平台毕业设计也没必要。比较好的做法是首页用几个卡片展示汇总数字再拉一张最近 7 天的订单趋势图前端用图表组件渲染。注意统计数字会随着订单增长变多SQL 要加时间条件全表扫描也可能慢但只要在订单表的时间字段上建好索引数据量在几万条以内完全没有压力。4. 从零跑通整个项目4.1 环境准备与初始化跑这个项目之前先确认环境缺一不可JDK 8 及以上推荐 8 或 11。Maven 3.6用来拉取后端依赖。MySQL 5.7 或 8.0用于导入数据表和数据。Redis 6.x本地启动好默认端口 6379。Node.js 14 以上如果前端是 Vue 项目需要用它来安装依赖和启动前端开发服务器。IDEA 或其他 Java IDE后端代码建议直接通过 IDE 打开。第一次见到一整套源码时不要急着双击运行先看目录结构。通常后端是一个 Maven 工程源码里会有pom.xml前端如果带源码会多一个包含package.json的文件夹。如果只有后端没有前端打包文件那大概率项目里用的是 Thymeleaf 这类服务端渲染模板前端页面直接放在templates目录下连 Node.js 都不用装。4.2 数据库初始化先创建一个数据库名字和源码里的配置保持一致。比如mysql -u root -p CREATE DATABASE flower_presale DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; exit;然后把源码里的.sql文件导入。导入时可以指定库名mysql -u root -p flower_presale flower_presale.sql导入成功后建议先看一眼表数量和核心表的字段确认整套脚本执行成功。如果导入报错最常见的原因是 SQL 文件里的库名和现有库冲突或者是 MySQL 版本语法不兼容比如旧脚本用了unsigned zerofill、ENGINEMyISAM这类较老的写法需要手动改成ENGINEInnoDB。还有一点务必要注意字符集是否统一成utf8mb4否则中文数据可能出现乱码。4.3 配置文件修改修改application.yml或application.properties把数据库地址、账号、密码改成你本地环境的值server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/flower_presale?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver redis: host: localhost port: 6379 database: 0这里有个很容易忽略的坑数据库密码如果是123456开发环境无所谓但如果你要把项目上到服务器演示一定要用环境变量或单独配置文件注入密码不要直接写死在打包后的配置里。另外别忘了启动本地的 Redis不然后端启动时可能不会报错但真正执行到登录或缓存逻辑时就会抛异常。4.4 启动与验收启动顺序是先 Redis、再后端、最后前端。后端启动后在浏览器里访问 Swagger 或接口文档地址确认接口在线。启动前端后输入账号密码登录跑一遍“浏览鲜花 - 下单 - 支付定金 - 管理端发货”的完整链路。我第一次帮学弟排查这个项目时典型症状是前端能打开但一登录就报网络错误。检查之后发现不是接口写错而是后端端口是 8080前端通过代理转发却配成了 8088。如果你也遇到类似情况先别急着改代码按下面顺序排查后端是否启动、端口是否正确、前端代理配置是否指向后端地址、Redis 是否启动、数据库能否正常连接。这几项检查完百分之八十的启动问题都能解决。5. 常见问题与排查技巧5.1 Redis 没启动导致登录失败登录接口看起来一切正常但跑起来就报Unable to connect to Redis。原因是登录成功后的令牌写入 Redis 失败事务或异常直接拦截了后续返回。解决办法很简单先启动 Redis。本地开发也可以把 Redis 的配置调成失败降级但在毕设里没必要直接启动它就好。如果你用的是 Windows下载一个免安装的 Redis 版本双击redis-server.exe即可。检查 Redis 是否正常用命令行执行ping返回PONG就说明通了。5.2 数据库连接报错或时区问题启动后端时报Access denied for user十有八九是配置里的数据库密码和本地不一致。报Public Key Retrieval is not allowed这是 MySQL 8 的认证插件问题可以在连接 URL 后追加allowPublicKeyRetrievaltrue。最经典的问题是时间差八小时订单时间显示成西半球时间。解决方案就是在连接 URL 里加serverTimezoneAsia/Shanghai同时数据库连接驱动如果是 MySQL 8要确认使用的是com.mysql.cj.jdbc.Driver而不是旧的com.mysql.jdbc.Driver。5.3 前端页面能开但数据加载不出来这种问题多半是前后端接口没通。Vue 项目里一般会在vue.config.js中配置 devServer 的 proxy 代理你需要检查请求的地址是不是转发到了后端端口proxy: { /api: { target: http://localhost:8080, changeOrigin: true } }前端请求路径里的/api前缀和后端RequestMapping的路径要保持一致任何一个多一层少一层都会导致 404。让浏览器打开开发者工具切到 Network 面板看具体请求返回的状态码比对着代码猜要高效得多。5.4 订单支付状态更新失败用户支付成功后订单状态没变。先查支付回调日志再查支付流水表。很多项目用的是本地模拟支付回调代码里用线程延迟几秒模拟异步通知如果这个逻辑写在定时任务里要确认定时任务是否开启。如果是真实第三方支付问题可能出在回调验签或回调地址配置。毕设阶段建议先用本地模拟支付通道跑通业务流答辩时讲清楚“怎么模拟回调、回调失败如何补偿”远比直接接入真实支付更能展示思考深度。5.5 前端启动依赖安装过慢或失败执行npm install时网络慢或者报错优先检查 npm 镜像配置可以用国内镜像源一般会快很多。装完依赖后如果还报依赖缺失可以把node_modules目录删掉重新安装一次。前端开发服务器默认端口经常是 8080 或 3000和后端端口撞了的话在vue.config.js里修改port即可。最后分享一点个人体会这套鲜花预售系统如果只是把源码下载、导入、启动、截几张图放进论文那你其实浪费了它一半的价值。它真正值钱的地方在于“预售”这个场景逼你去思考订单状态、库存预占、时间窗口、支付回调这些电商系统里绕不开的问题。我在帮学弟调试时发现他花了三天终于把整套流程跑通但当我问他“如果同一个用户重复提交两次预售订单怎么办”时他答不上来。后来他认真补了一个幂等校验在创建订单接口里对“用户 ID 活动 ID 订单状态”做了唯一约束这一个改动就成了他答辩时最有亮点的一段经历。如果你也准备拿这个题目做毕设我的建议是不要一上来就闷头改需求先看懂项目里订单表和数据字典把主流程彻底跑通再动手改一个自己真正感兴趣的模块。预售系统的状态机、库存预占、登录鉴权、数据统计这四块随便挑一块深入研究都能成为你毕业设计里最有说服力的原创内容。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑