SpringBoot+Vue3蛋糕销售管理系统:从零搭建到答辩全攻略

发布时间:2026/10/8 15:04:25
SpringBoot+Vue3蛋糕销售管理系统:从零搭建到答辩全攻略 每年到了春招和毕设季我这边就会集中收到一批类似的咨询Java方向、SpringBoot后端、Vue前端、想做一个电商类管理系统。问得最多、最后交付率也最高的就是基于SpringBootVue3的蛋糕销售管理系统。从选题本身就能看出它为什么受欢迎——业务链路完整商品、购物车、订单、支付、统计全都有但规模又不会大到一个人做不完而且蛋糕这种商品自带好看的图片展示场景做完拿去答辩视觉效果很占便宜。这篇就把我从零搭这套系统、以及帮学生填坑的全过程拆开讲一遍照着做至少能让你少走两三个星期的弯路。1. 项目定位与需求拆解毕业设计到底要做成什么样1.1 一个蛋糕销售系统为什么成了“稳妥之选”很多人一上来就问“哪个毕设题目最容易过”我的回答一直是别找最容易的找最稳的。所谓稳就是技术栈主流、业务逻辑完整、演示效果好、答辩时每个模块都能讲出设计理由。奶油蛋糕销售系统恰好全中。它本质上是个轻量级电商系统核心链路是“用户浏览商品—加入购物车—下单—支付—商家发货—用户确认收货”这条链路每一段都是一个独立的功能点单拿出来都能写一段实现思路。对比传统的图书管理系统、员工管理系统蛋糕销售系统多出了购物车、订单状态、库存扣减、销售统计这些真实业务场景天然更容易展示个人能力。另一个现实因素是这个选题在网上已经有大量开源版本和参考资料初版跑起来不难。难点在于怎么把它做出差异化比如增加会员积分、蛋糕DIY定制、限时折扣、数据大屏、评论功能这些都是评审老师愿意看到的亮点。整套系统做下来功能边界刚好控制在一个人两三周能完成的范围内不会像中台系统那样遥遥无期也不会像图书管理那样让人一眼看穿是“课设级别”。1.2 用户端和管理端的功能边界毕设答辩最忌讳“功能一堆但说不清楚”。我建议开工前先把角色和功能边界画清楚我用得最多的整理方式就是角色-功能对照表。角色核心功能备注普通用户注册登录、浏览商品、分类筛选、关键词搜索、查看详情、加入购物车、下单、模拟支付、查看订单、取消订单、个人信息修改不需要做真实支付用模拟支付状态切换即可管理员登录后台、商品分类管理、商品CRUD、上下架、库存调整、订单管理、发货操作、用户管理、销售数据统计、轮播图管理后台界面用Element Plus搭建表格表单弹窗是主力用户端页面通常包含首页、商品列表、商品详情、购物车、订单确认、订单列表、个人中心这几个页面管理端则是一个带侧边栏的布局里面挂商品管理、订单管理、用户管理和数据统计四个子页面。这套页面结构基本是任何电商类项目的通用模板做蛋糕和做手机没本质区别。还有一点很容易被忽略管理系统里必须内置一个管理员账号并且要在数据库初始化脚本里预置否则答辩老师问“后台怎么登录”就尴尬了。1.3 哪些是必做项哪些是加分项很多同学一上来就想着做秒杀、做优惠券、做消息推送我一般会劝住。毕业设计的核心是完成一个逻辑闭环而不是功能堆砌。必做项是登录鉴权、商品展示、购物车、下单、订单管理、商品管理、数据统计。这七个模块覆盖了“前台用户操作”和“后台管理操作”两条完整链路足够支撑一篇像样的论文和十几分钟的演示。加分项我建议从下面几个方向挑一两个做就够了订单超时未支付自动取消用Spring定时任务或延迟队列实现数据统计维度扩展加入按月份对比、按分类占比用ECharts画趋势图角色权限细化比如普通管理员不能删除订单简单优惠券系统下单时校验券码并抵扣金额。加分项的价值在于答辩时能让老师看到“这个人有扩展思维”而不是说“我只会照着教程敲”。2. 技术选型与架构设计为什么这套组合最省心2.1 SpringBoot和Vue3各自解决什么问题后端选SpringBoot基本没有争议。它内嵌Tomcat、自动配置、生态成熟Java方向的毕业设计选它几乎等于默认答案。具体版本上我建议分两种情况如果你的JDK环境是8就用SpringBoot 2.7.x如果是17以上可以直接上3.x。注意SpringBoot 3.x的包名从javax改成了jakarta网上很多老教程里的import语句会报错这不是你写错了是版本差异。前端选Vue3而不是Vue2也是同样的逻辑。Vue3的组合式APIsetup语法写起来比选项式API更干净配合Vite启动速度极快再加上TypeScript的话项目结构会显得更专业。不过毕设一般不建议强行上TypeScript时间有限JavaScript就够了。选这套组合的核心原因不是为了赶潮流而是因为答案可查、错误可搜。SpringBoot Vue3的社区资料足够多遇到问题搜索引擎基本都能找到答案这对时间紧张的毕设来说比技术本身更重要。2.2 后端代码怎么分层前端目录怎么组织我见过太多学生把所有代码塞进一个Controller里几百行下来自己都看不懂。这里的花不了多少时间但能让答辩印象分差出一截。后端推荐按经典分层结构cakeshop-backend/ ├── src/main/java/com/example/cake/ │ ├── controller/ # 接收请求参数校验 │ ├── service/ # 业务逻辑事务控制 │ ├── mapper/ # MyBatis-Plus的Mapper接口 │ ├── entity/ # 数据库表对应的实体 │ ├── dto/ # 前端传入的参数对象 │ ├── vo/ # 返回给前端的视图对象 │ ├── config/ # 配置类、拦截器注册 │ ├── common/ # 统一返回体、异常处理 │ └── utils/ # JWT、密码加密等工具 └── resources/ ├── mapper/ # 复杂SQL的XML文件 └── application.yml前端目录相对自由但最好也形成习惯cakeshop-frontend/ ├── src/ │ ├── api/ # 每个功能模块的接口请求 │ ├── views/ # 页面级组件 │ ├── components/ # 复用组件商品卡片、分页等 │ ├── router/ # 路由配置 │ ├── store/ # Pinia状态管理 │ └── utils/request.js # axios实例封装分层不是为了好看而是为了让逻辑边界清晰。答辩时老师问“订单金额在哪里计算的”你可以直接回答在Service层而不是Controller层这就是一个加分的细节。2.3 数据库设计订单和商品的表关系一次讲清数据库设计是整个项目的地基。很多项目后期改来改去就是因为表设计不合理。我常用的表结构包含以下几张user用户表id、username、password、nickname、avatar、phone、role、createTime其中role区分管理员和普通用户category分类表id、name、sortproduct商品表id、categoryId、name、description、price、stock、image、status、sales、createTimecart购物车表id、userId、productId、quantity、checkedorders订单表id、orderNo、userId、totalAmount、status、receiverName、receiverPhone、receiverAddress、createTime、payTimeorderItem订单明细表id、orderId、productId、productName、productImage、price、quantity。这里有两个关键设计点。第一订单中要冗余商品名称和商品图片。因为商品信息可能会被修改如果订单明细只存productId之后商品改价或改名历史订单的数据就不对了。第二金额字段不要用float或double用decimal(10,2)。浮点数在计算总价时会出现精度问题这是在毕业答辩里被经常问到的一个基础题也是真实项目中非常重视的点。我建议外键在逻辑上保持关联但不在数据库层面创建物理外键。理由也很直接物理外键在删除和更新时容易产生约束麻烦而且项目中用MyBatis-Plus操作时物理外键反而影响效率。表关系通过Java代码来控制这在现代化开发里是主流做法。3. 核心功能模块实现关键代码思路与细节拆解3.1 登录鉴权JWT和拦截器怎么配合这套系统最核心的公共逻辑就是登录鉴权。方案我推荐JWT而不是传统的Session原因是前后端分离架构下Session天然存在跨域和共享问题而JWT无状态、适合接口鉴权。登录流程大致是用户输入用户名密码后端校验通过后生成一个有效期2小时的token把用户id和role放进token里前端把token存在localStorage每次请求时在axios请求拦截器里带上Header后端写一个拦截器对所有非白名单接口进行token校验校验失败返回401前端路由守卫判断本地有没有token没有就跳转登录页。密码存储这块一定不要用明文或MD5。Spring Security crypto包里自带BCryptPasswordEncoder加盐哈希一个单词就能完成加密和校验比MD5靠谱得多。我见过不少学生把“登录成功”当成token校验其实是两回事。Controller里只要校验用户信息是否正确即可至于token的有效性、过期时间全部交给拦截器统一处理。这样后续加接口时不需要每个Controller都写一遍校验逻辑也便于答辩时讲“统一鉴权”这个设计思路。3.2 购物车和下单核心逻辑购物车不是简单的增删改查里面藏着两个容易忽略的点。第一个是“加入购物车”接口的幂等性。用户反复点击“加入”同一个商品时正确的行为是购物车中该商品数量1而不是插入两条记录。所以后端判断逻辑应该是先根据userId和productId查购物车表有记录就update数量没有记录才insert。第二个是“选中商品”状态。购物车里通常有全选、单选功能订单页只会展示被勾选的商品。所以cart表里的checked字段一定要设计进去否则下单时没法区分哪些商品需要结算。下单接口是整个系统里事务最密集的地方。一个完整的下单需要做四件事根据购物车选中记录组装订单明细创建一个订单主记录计算总金额扣减对应商品库存清空已下单的购物车记录。这四个操作必须放在同一个事务里否则会出现“库存扣了但订单没生成”或者“订单生成但购物车没清空”的脏数据。在SpringBoot里给Service方法加上Transactional注解就行非常简单但非常重要。还有一个经验下单时的总金额一定不能直接信任前端传来的数值必须由后端根据商品当前价格重新计算。这个点经常被答辩老师拿来问也是真实电商里防刷单的基本逻辑。3.3 订单状态流转与事务控制订单状态是用一个整数字段表示的我用的是状态值含义触发动作0待支付下单成功1已支付/待发货用户模拟支付2已发货管理员点击发货3已完成用户确认收货或发货后自动完成4已取消用户取消订单订单状态机的核心是“状态的合法流转方向”。比如待支付订单可以取消已支付订单不能再取消只能走发货流程。实现上可以简单在Service层加if判断也可以写一个状态转换工具类统一管理。我建议毕设用if判断即可但把判断逻辑集中在OrderService里不要散落在Controller各个方法中。另外关于“支付”这个动作毕设不需要对接支付宝或微信支付只需要提供一个“模拟支付”按钮点击后把订单状态从0改成1并记录支付时间。但可以在论文里提一句“预留了真实支付接口”这种话术是合理的扩展说明。定时检查超时未支付订单可以作为加分项用Spring的Scheduled注解实现每30秒扫描一次前5分钟创建的待支付订单把超时订单取消并回滚库存。这个功能实现不复杂但演示效果很酷也算是有真实业务价值的模块。3.4 后台统计怎么用SQL做出销售报表管理后台的统计页面是整个项目最直观的“成果展示区”。我一般用ECharts配合后端统计接口来做。统计接口的SQL写法是核心。比如近7天销售趋势可以按日期分组聚合SELECT DATE_FORMAT(create_time, %Y-%m-%d) AS day, SUM(total_amount) AS amount FROM orders WHERE status IN (1, 2, 3) AND create_time DATE_SUB(CURDATE(), INTERVAL 6 DAY) GROUP BY day ORDER BY day;这就是一个非常典型的“按时间维度统计销售额”的SQL后端返回给前端一个day和amount的数组前端直接用ECharts的折线图渲染。分类销售占比的统计稍微复杂一点需要关联订单明细表和商品表按分类聚合。这个SQL在MyBatis的XML里写比较清晰也不会把业务逻辑塞进Java代码里。后台仪表盘上还会用几个数字卡片展示商品总数、用户总数、今日订单数、今日销售额。这四个指标我都是用简单SQLcount和sum查出来的不需要搞实时计算给答辩演示完全够用。数据统计模块的加分点在于“图表联动的技巧”点击分类占比饼图的一块下面的商品销量排行表格能联动过滤出该分类的数据。前端监听ECharts的点击事件再带着分类ID请求接口大概几十行代码但演示效果能提升一个档次。4. 实操过程从环境搭建到打包演示4.1 环境准备与初始化配置动手前先确认本机环境JDK、Maven、Node.js、MySQL、IDEA、VSCode。版本不一定要最新但必须互相兼容。这里列一份我常用的环境组合照着配基本不会出问题组件推荐版本说明JDK8或17SpringBoot2.7用83.x用17Maven3.6.3配阿里云镜像不然依赖下载很慢Node.js16.20低于16跑不动新版ViteMySQL5.7或8.08.0记得调密码加密规则SpringBoot2.7.18最稳教程最多后端工程初始化用IDEA的Spring Initializr勾选Spring Web、MySQL Driver、MyBatis框架这几个依赖。如果用的是SpringBoot3.xMyBatis依赖要改成mybatis-plus-spring-boot3-starter这里很多人会踩版本坑。前端工程用Vite创建在命令行执行npm create vitelatest选择Vue模板然后依次安装vue-router、pinia、axios、element-plus、echarts。依赖安装完成后先跑一次npm run dev确认项目能启动再开始写代码。不要一上来就复制别人的完整源码连本地环境都没验证过出了问题很难定位。还有一个很容易被忽略的配置前端开发代理。在vite.config.js里加上一段server: { proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } }这样前端请求/api开头的接口会转发到后端8080端口开发阶段不用处理跨域。很多学生卡在跨域问题上其实一个代理配置就解决了。4.2 后端接口开发要点后端开发的顺序建议按照“基础功能-核心链路-统计数据”分阶段推进不要东一榔头西一棒子。我通常先写统一返回体Result和全局异常处理再写登录鉴权然后做商品查询和分类查询最后做购物车和订单。统一返回体的作用是避免每个接口返回格式不一致。一般长这样public class ResultT { private Integer code; private String message; private T data; // 静态方法 success() / error() }配合RestControllerAdvice做全局异常捕获业务里只需要专注写业务逻辑错误处理自动返回统一格式。答辩讲“统一异常处理”时能说出这么一套专业度马上就上来了。接口的路径命名我习惯用资源名词的复数形式比如/api/products、/api/orders/list而不是/api/getProductList。然后注意区分RequestBody和RequestParam前端传JSON对象用RequestBody传单个参数或表单用RequestParam。前后端联调时大多数404和参数丢失问题都出在这。实体类不要直接作为Controller的返回对象。原因很简单User实体里包含password字段一返回就把密码哈希暴露给前端了。正确做法是单独建VO只返回需要的字段。4.3 前端对接后端请求封装与路由守卫前端开发的顺序是先搭好路由和页面框架再封装接口请求然后逐个页面联调。我用axios做了封装核心逻辑在utils/request.js里const request axios.create({ baseURL: /api }); request.interceptors.request.use(config { const token localStorage.getItem(token); if (token) { config.headers.Authorization token; } return config; }); request.interceptors.response.use( response { const res response.data; if (res.code 401) { router.push(/login); } return res; } );请求拦截器加token响应拦截器统一处理业务状态码这套模式几乎所有管理系统都在用。写好之后每个页面的接口调用都会非常干净。路由守卫是另一个容易被忽略的点。在router/index.js里配置全局前置守卫router.beforeEach((to, from, next) { const token localStorage.getItem(token); if (to.meta.requiresAuth !token) { next(/login); } else if (to.path /login token) { next(/); } else { next(); } });这样用户没登录时访问任何需要登录的页面都会被自动弹回登录页。前端路由守卫和后端拦截器配合起来就是一套完整的前后端鉴权体系正好可以当答辩素材。4.4 打包部署最省事的单jar演示方案答辩演示时最怕“环境依赖太多”到了现场电脑上少了某个依赖项目就跑不起来。所以我强烈推荐把前后端打包成单个SpringBoot jar的部署方式。具体做法是前端执行npm run build把生成的dist目录整个复制到SpringBoot项目的src/main/resources/static目录下。然后重新打包后端mvn clean package这样打出来的jar里既包含后端接口又包含前端静态资源部署时只需要一个命令java -jar cakeshop.jar浏览器访问http://localhost:8080就能看到整个系统。这个方案不用装Node环境、不用装Nginx、不用配反向代理对答辩现场的临时电脑来说就是最稳的部署方式。如果你要部署到云服务器上就用稍微正规一点的做法前端dist目录交给Nginx托管Nginx把/api路径反向代理到SpringBoot的8080端口。这样静态资源和接口分开后续更新前端页面时不需要重新打包Java应用维护起来更舒服。5. 常见问题与排查实录联调和答辩的实战经验5.1 联调阶段最容易踩的5个坑前后端联调基本占据了整个项目开发的一半时间我把最容易遇到而且搜不到直接答案的问题整理一下。第一个是跨域报错。虽然vite代理能解决大部分但如果你直接访问后端的非代理接口比如在浏览器里打开localhost:8080/api/products会被CORS策略拦住。解决方式是在SpringBoot的Config里配置一个CorsFilter允许来自localhost:5173的请求。代理方案和CorsFilter只需要选一个就好别两个都用导致配置叠加。第二个是MyBatis-Plus的字段映射问题。数据库里的user_id字段实体类里是userId默认开启驼峰转换才认识。在application.yml里一定要加mybatis-plus: configuration: map-underscore-to-camel-case: true第三个是JSON时间格式。后端返回的Date默认是一串时间戳数字前端显示成“1234567890”非常难看。在实体类时间字段上加JsonFormat(pattern yyyy-MM-dd HH:mm:ss)立即解决。第四个是Vue打包后刷新404。这是因为history路由模式在服务器上没有对应的路径。开发阶段没问题打包部署后就出现刷新空白或404。要么后端配置转发所有非接口路径到index.html要么在前端路由里把history改成hash模式毕设我用后者一个字符串就搞定。第五个是图片资源404。商品图片在后端本机某个目录打包后路径找不到。规范做法是把图片上传路径配置到application.yml里然后加一个WebMvc的资源映射把本地目录映射到/upload/**路径。不要用绝对路径写死否则换机器就废。5.2 部署运行中那些“环境问题”部署阶段的问题往往比开发阶段更让人抓狂因为很多是和本机环境绑定的小瑕疵。端口占用算是最常见的。8080被其他程序占用时启动日志会报端口被占用错误修改application.yml里的端口再重启就行。我习惯改成8090避免和本地其他服务撞车。数据库连接失败也是高发问题。MySQL8.0默认的认证插件是caching_sha2_password而老驱动用的是mysql_native_password连接时会报“Unable to load authentication plugin”。解决办法是创建连接用户时指定ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY 你的密码;另一个坑是数据库连接URL忘记带时区参数导致的日期错误。MySQL8.0要求必须声明serverTimezone我一般用jdbc:mysql://localhost:3306/cake_db?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/ShanghaiuseSSLfalse这个配置要写清楚带utf8字符集和中文字段都没问题否则中文乱码会折腾得很烦。还有一点是SpringBoot版本过高导致Maven依赖冲突。如果你在创建工程时选了3.2以上的版本而项目里又引用了很多自动配置和插件可能遇到接口方法签名找不到的问题。调试成本高不如一开始就用2.7.18把所有精力花在功能开发上。5.3 答辩前要重点准备的设计题答辩时的底层原理问题往往比代码本身更重要。根据我带项目的经验有几个问题几乎必被问到模板和答案我整理成了下面这个表。常见问题推荐回答思路为什么用JWT不用Session前后端分离项目后端无状态JWT不占服务端内存扩展性好Session需要共享存储处理多节点问题。为什么不用数据库物理外键物理外键会导致插入、删除性能开销且分布式场景不适用逻辑外键通过应用层控制灵活性更高。订单金额为什么用BigDecimaldouble有精度误差Money类型一般都用decimal计算都在数据库或后端Java中做不在前端计算。登录密码如何保证安全BCrypt加盐哈希密码不落库哈希不是加密不可逆就算数据库泄露也无法还原明文。项目有哪些可扩展的点可以提优惠券、限时秒杀、消息通知、数据大屏、支付接口真实接入再从订单状态机扩展退款流程。购买商品时库存不足如何处理下单前先校验库存扣库存用乐观锁或where stockquantity的CAS语句防止超卖。这些问题在论文里也有对应章节提前准备好答的时候用三句话讲清原理再补一句“我在项目里是怎么做的”基本就能稳住。最后再分享一个个人经验如果你拿到了一套现成源码不要急着改业务先把它跑起来再按“登录入口-商品列表-购物车-下单-后台管理”的顺序把代码读一遍搞清楚数据流是怎么走的。然后在运行数据上做几笔测试看看库存、订单、统计有没有一致性问题。我自己每次拿到新项目都是这套流程看起来多花了半天实际上后面改起来速度快很多。这个蛋糕销售系统也是一样把核心链路的数据流转理解了剩下的二次开发和答辩准备都只是时间问题。