SpringBoot+Vue免税商城全栈实战拆解:从数据库设计到部署上线

发布时间:2026/10/20 1:30:51
SpringBoot+Vue免税商城全栈实战拆解:从数据库设计到部署上线
SpringBoot Vue 的免税商品优选购物商城单看标题就知道这是一个典型的 Java Web 全栈毕业设计。它不像纯前端项目那样只写页面也不像纯后端项目那样只写接口而是把用户端、管理端、数据库、部署脚本全部串成一条线。我最近帮人梳理过这类项目说实话源码量不算特别大但信息密度并不低一个商品模块、一个购物车、一个订单流程、一套后台管理再加权限校验和税价展示几乎把大学阶段学到的 Java 技术栈全部揉进去了。这篇文章的定位很直接给那些准备拿同类商城做毕设、或者想彻底搞懂全套业务闭环的同学一份“能落地”的拆解从数据库怎么建表到接口怎么设计从前端页面怎么对接后端到部署时最容易翻车的位置我都会按实际跑通项目的顺序来讲。1. 项目全貌拆解它到底解决了什么问题1.1 从标题里挖出来的功能清单“免税商品优选购物商城平台”这个命名每一段都是有含义的不是随便拼出来的。“免税商品”决定了业务场景不是普通超市电商而是带有税价展示和价格对比的跨境购物场景。体现在数据层面商品表里通常需要有原价、免税价、税费、折扣等字段体现在结算层面订单金额需要能区分商品总额、优惠金额、实付金额这就比普通的小卖部项目多了一个可讲价的点。“优选”这两个字意味着平台上要有“精选推荐”这类运营逻辑技术上可以做成首页轮播图、热门推荐位、按销量排序、按点击量推荐等。你不需要真的实现一套复杂的推荐算法但至少让首页不是一张静态图片堆出来的而是能从数据库里动态查一批商品出来展示面试时能说清楚推荐位的排序规则就够用了。“购物商城”是核心闭环用户登录后浏览商品把商品加入购物车生成订单完成支付最后在个人中心看到订单状态。管理端则负责商品上架、分类维护、订单发货、Banner管理。这套闭环覆盖了增删改查、权限控制、状态流转、前后端联调、文件上传这些高频考点所以它才这么受毕设选题欢迎。“平台”这个词说明项目通常不只是一个用户端还会带一个后台管理端也就是前端有两套界面后端要区分普通用户和管理员角色。所有接口都要做登录拦截和权限校验管理员接口不能裸奔在公网上。我拿到这类项目时第一步不是看代码而是先把功能列成一张模块清单对照着检查它的完整性。一个能拿出去答辩的商城项目至少要有下面这些模块模块功能点角色首页Banner轮播、商品分类导航、热门商品推荐用户商品分类检索、关键词搜索、商品详情、分页列表用户购物车加入购物车、修改数量、删除商品、全选/单选、金额合计用户订单创建订单、订单列表、订单详情、取消订单、确认收货用户支付模拟支付页、支付回调、支付状态变更用户个人中心登录注册、个人信息、修改密码、地址管理用户后台管理商品管理、分类管理、订单管理、轮播图管理、用户管理管理员如果标题里的项目对应的源码缺少其中某一项比如只有商品展示没有购物车或者只有用户端没有管理端那不仅答辩容易被追问到难堪功能闭环也是不完整的。拿到项目后别急着跑先对着这张表过一遍缺什么补什么。1.2 为什么选 SpringBoot Vue 这套组合如果是五六年前Java Web 毕设的主流组合还是 JSP Servlet 或者 SSM 框架加一堆 JSP 页面。现在再做那种单体 JSP 项目不是说不可以而是大多数人对“前后端分离”的掌握程度已经成了基本预期。SpringBoot Vue 之所以霸榜不是因为技术最新而是因为它在“复杂度可控”和“技术栈完整”之间找到了一个很舒服的平衡点。后端用 SpringBoot省掉了 Spring 那一堆 XML 配置起步就是一个可以跑的 Web 项目。再配上 MyBatis-Plus连单表的 CRUD SQL 都省了大半写代码效率非常高。接口风格做成 RESTful返回统一 JSON前端拿数据直接渲染。数据库用 MySQL事务、关联查询这些基本功都在里面练到了。前端用 Vue不管是 Vue2 还是 Vue3它的核心思路都是一样的数据驱动视图。你定义一个变量把它渲染到页面上用户操作触发事件事件里调用后端接口返回的数据再更新变量。对毕设来说Vue 的单文件组件和官方生态已经很成熟文档也多遇到问题基本都能搜到答案。有人会问那用 Spring Cloud 微服务架构不是显得更高级吗我的建议很明确不要为了“显得高级”去上微服务。毕设的项目体量就那么大一个商品模块一个订单模块微服务拆出来只会给自己找麻烦服务注册、配置中心、网关、分布式事务哪一个都够喝一壶的。SpringBoot Vue 是刚好能把一个完整的商城业务讲清楚又不至于被架构本身拖死的选择。2. 环境搭建与数据库设计决定项目上限的部分2.1 开发环境与版本选型拿到一个 SpringBoot Vue 项目第一件事不是看业务代码而是把环境先对齐。很多新手项目跑不起来的第一个原因就是 JDK、Maven、Node 版本哪个都对不上。先说后端。JDK 建议用 8 或者 11这两个版本在 Java 生态里兼容性最好。如果你拿到的源码用了更高版本的语法特性比如 var 或者 switch 表达式那就要 JDK 11 以上。SpringBoot 版本也要看一眼2.x 和 3.x 差别不小主要是 javax 命名空间变成了 jakarta如果源码是 3.x 而你本地用的是 JDK 8那是编译不过去的因为 SpringBoot 3 最低要求 JDK 17。Maven 的话用 IDEA 自带的 Maven 或者单独安装 3.6 以上的版本都可以重点是要把镜像仓库配置好不然第一次拉依赖能等到让人怀疑人生。Node 版本要特别注意Vue2 配 Node 14、16 问题不大Vue3 配 Node 16 以上更稳。如果项目是用 Vite 构建的Node 版本太老会直接报错。数据库这块MySQL 5.7 和 8.0 都常见我更建议用 8.0因为字符集、时区、身份认证方式都更现代。需要注意的是 MySQL 8 的驱动包和连接 URL 都要带 cj 前缀时区参数也要处理不然会碰到 8 小时的时区差问题。开发工具方面后端用 IDEA前端用 VS Code数据库用 Navicat 或者 DataGrip。没有强制要求但这些工具最顺手遇到问题也最容易搜到对应解决方案。2.2 数据库表结构与核心字段设计数据库设计是这个项目里最不该偷懒的部分。我见过不少同学的商城项目商品表就五六个字段订单表只有一个总金额字段表面上功能跑得通但只要面试官问一句“订单详情怎么查”立刻就露馅了。一个标准的商城项目核心表至少有这些用户表user用户表字段不必过于复杂但要有角色区分用户ID、用户名、密码加密后、昵称、头像、手机号、邮箱、角色0用户/1管理员、状态、注册时间角色字段很关键它决定了登录后的权限。管理员不是单独建一张表而是用角色的方式去区分这在 JWT 鉴权时非常方便。商品表goods商品表是信息量最大的表至少要包含商品ID、商品名称、商品副标题、分类ID、主图URL、轮播图URL、原价、免税价、库存、销量、点击量、是否上架、是否推荐、创建时间、更新时间这里我特别说一下价格字段。普通商城一个价格字段就完了但免税商品场景下我用的是“原价 免税价”双字段前端商城详情页可以做一个对比展示结算时按免税价计算。如果项目里还提到税费那就再加一个税率字段或者用“是否含税”来标记这样“免税”这个概念就有数据支撑了而不是只在页面上写两个字。分类表category分类表字段简单分类ID、分类名称、父分类ID、排序、图标。这里用父分类ID是为了支持二级分类比如“美妆”下面可以分“护肤”“彩妆”如果项目不打算做二级分类父分类ID 也可以留着以后扩展时不用改表结构。购物车表cart购物车表不能只存商品ID要考虑用户、商品、数量、选中状态这几个维度购物车ID、用户ID、商品ID、数量、是否选中、加入时间看到“是否选中”这个字段你可能觉得多余但前端购物车页面的全选功能、单选功能、结算时只计算选中商品全靠这个字段配合实现。购物车数据如果不加这个字段前端就只能用临时变量管理选中状态刷新页面就丢了。订单表orders订单表是核心业务表需要记录快照信息订单ID、订单编号、用户ID、商品总额、优惠金额、实付金额、收货人、手机号、收货地址、订单状态、创建时间、支付时间、发货时间为什么说快照信息因为订单生成之后商品可能改价、可能下架如果订单里只存商品ID那么后续查历史订单时会发现价格对不上。所以至少要把“当时的下单价”冗余到订单明细表里这是业务开发里的常见习惯。订单明细表order_item一张订单对应多个商品所以需要明细表明细ID、订单ID、商品ID、商品名称快照、商品主图快照、下单单价、数量商品名称和主图在明细表里再存一份这样即使商品后来改名、换图历史订单仍然能看到下单时的信息。这是很普通但很容易被忽略的细节写的时候多敲四五个字段用的时候省一大堆麻烦。轮播图表banner轮播图表字段包括BannerID、标题、图片URL、链接地址、排序、是否展示。这些表建好之后一个完整商城的数据库骨架就出来了。我还建议把建表脚本里加上测试数据具体原因下一段讲。2.3 SQL脚本里容易被忽略的初始化数据很多网上流传的项目源码SQL脚本只建了表结构一行数据都不带。你把它跑起来前端页面空荡荡的首页没商品后台没管理员连登录都进不去第一印象就垮了。正确做法是 SQL脚本里除了建表还要插入必要的基础数据管理员账号密码要存加密后的值不能存明文几个测试用户方便演示登录若干测试商品覆盖不同分类、不同价格段至少让首页“优选推荐”有东西可展示几条轮播图记录让首页Banner区域看起来像样初始化数据这块有个非常容易踩的坑密码加密。如果后端用的加密方式是 BCrypt那你不能直接在 SQL 里写一个明文密码再指望登录时自动加密因为 BCrypt 每次加密结果都不同。正确做法是先写个小测试类把密码加密后的字符串打印出来再复制到 SQL 脚本里。MD5 虽然简单但毕设答辩时基本都会被问一句“密码怎么存储”建议还是用 BCrypt 这类带盐的加密方案答起来更有底气。3. 后端业务与接口实现别把接口写得像“数据库透传”3.1 用户认证从 Session 到 JWT 的选型逻辑前后端分离的项目里用户登录状态怎么维持是个绕不开的问题。传统的 Session 方案需要服务器保存会话前端通过 Cookie 携带 SessionID但这样做会碰到跨域时 Cookie 携带不便的问题对部署也不友好。现在主流的做法就是用 JWT把用户信息加密后放到一个 Token 里前端每次请求在请求头里带上 Token后端校验通过就放行校验不通过就返回 401。JWT 的结构是三段式的Header、Payload、Signature。Header 里声明加密算法Payload 里存用户ID、用户名、角色、过期时间这些信息Signature 是对前两段的签名防止 Token 被篡改。后端代码里要做的事情很简单登录时生成 Token拦截器里校验 Token。实际做毕设时我建议把 JWT 的过期时间设成 2 小时或者 4 小时太长不安全太短影响使用体验。实现方案在 SpringBoot 里通常用一个拦截器或者过滤器统一处理放行登录接口和商品浏览接口拦截需要登录的接口管理员接口还要额外检查角色。注意JWT 不是存在服务器上的所以它没法主动“失效”。用户登出这个操作前端把 Token 丢掉就行真正的安全性靠过期时间兜底。如果你做的项目要求更严格就需要引入黑名单机制或者改用 Redis 保存会话状态但毕设场景里 JWT 前端清理 Token 已经够用了。3.2 统一响应结果与异常处理前端拿到的不该是裸JSON很多后端新手写的接口返回什么就是什么查询成功就返回一个对象失败了就返回 null异常直接抛到前端连错误码都没有。前端拿到一堆乱七八糟的响应格式联调的时候只能到处写判断苦不堪言。我的习惯是定义统一返回结构 Result 包含三个字段状态码、消息、数据体。成功状态码用 200失败用自定义错误码比如 500 表示服务器异常401 表示未登录403 表示没有权限。前端拿到响应后只看状态码再做对应操作。配合统一返回结构还要有统一异常处理。SpringBoot 用 RestControllerAdvice 加 ExceptionHandler 就能完成全局异常捕获把业务异常、参数校验异常、系统异常分别处理。参数校验用 Validated 注解请求体里加 NotBlank、Email、Min 这些校验注解校验失败时由全局异常处理器统一返回错误信息而不是让框架默认的报错页面出现在前端。这一步做完后端接口的“边界感”就出来了答辩时可以说自己考虑了健壮性。3.3 商品模块与检索接口的设计思路商品列表页是商城项目的门面接口设计直接影响前端页面的复杂度。我建议商品列表接口至少支持这些参数当前页码、每页条数、分类ID、关键字、排序方式。排序方式可以支持综合排序、价格从低到高、价格从高到低、销量排序。这里我用 MyBatis-Plus 作为 ORM 框架它自带分页插件配合 LambdaQueryWrapper 写查询条件非常简洁。比如按分类和关键字查询商品用 LambdaQueryWrapper 的 eq 方法加分类条件再用 like 方法加模糊搜索关键字最后排序字段用 orderBy 方法动态拼接。比起手写 XML 里的动态 SQL这种方式写起来快出错率也低。“优选推荐”商品的实现也不复杂。我在商品表里加一个 is_recommend 字段后台管理时勾选推荐首页接口就查 is_recommend 为 true 的商品再按销量或者点击量倒序取前几条。这样既不需要搞复杂的推荐算法又能让首页内容动态变化每次刷新可能看到不同推荐结果业务逻辑上说得通实现成本也低。商品详情的接口除了返回商品基本信息还可以顺便返回同分类的热门商品这样前端详情页底部就能渲染一个“相关推荐”区域页面更饱满。同时也给商品点击数加一的更新操作虽然简单但至少商品是有“活跃度”概念的而不是死数据。3.4 购物车与订单状态机的实现重点购物车模块的接口非常固定查询购物车列表、加入购物车、修改数量、切换选中状态、删除购物车项。这里有一个隐藏的业务点就是加入购物车时如果该商品已经在购物车里应该做数量累加而不是新增一条记录否则用户反复点击加入购物车购物车里会出现好几条同商品记录体验很差。订单模块是整个项目的核心。创建订单时后端按这些步骤走第一步根据前端传过来的商品ID和数量查出商品当前价格第二步把购物车里的选中商品整理成订单明细计算出商品总额第三步生成订单主表订单编号用时间戳加随机数生成保证唯一性第四步保存订单明细第五步扣减商品库存第六步清理购物车中已下单的商品第七步返回订单号给前端。这一步里最容易被问到的就是事务。上述操作要么全部成功要么全部失败不能出现订单生成了但库存没扣或者库存扣了订单没了的情况。解决办法就是在创建订单的方法上加 Transactional 注解让 Spring 帮我们管理事务边界。需要提醒的是事务要放在 public 方法上才生效同类内部通过 this 调用方法时事务是不起作用的这是新手经常踩的坑。订单状态我习惯用这几个值0 表示待支付1 表示已支付2 表示已发货3 表示确认收货4 表示已取消。状态流向要符合业务逻辑待支付订单可以取消已支付订单可以发货已发货订单可以确认收货。在订单管理的列表查询里用状态字段做筛选让管理员能快速看到待发货的订单整个流程就清晰了。3.5 支付环节用回调而不是前端“口头通知”毕设项目对接真实支付平台需要商户号、密钥等资质对学生来说门槛较高所以最合理的做法是做一个模拟支付流程。我的实现思路是用户提交订单后后端生成订单订单状态是待支付前端跳转到“收银台页面”展示应付金额和订单编号。页面上放一个“确认支付”按钮点击后调用后端一个支付接口支付接口里模拟支付成功逻辑更新订单状态为已支付。这里要强调一个设计原则订单状态必须由后端修改不能让前端在页面里“假装支付成功”然后直接改状态。就算没有真实支付平台我们也要模拟出回调的语义。前端调用了支付接口才是真的完成了支付动作。抄别人的项目时尤其要注意这个问题有些简化版的代码里订单创建后直接就把状态置为已支付这个逻辑在答辩时说不过去。支付完成后后端返回最新的订单状态前端跳转到订单详情页展示支付成功。个人中心的订单列表里用户可以对已支付订单发起“模拟发货”流程角色不同操作不同管理员发货后状态变为已发货。这一串状态流转走通业务闭环就成立了。4. 前端 Vue 页面开发页面很多但套路是固定的4.1 前端项目结构与路由设计前端项目拿到手先看目录结构。规范一点的项目里src 下面会有 views 存放页面组件、components 存放公共组件、router 存放路由配置、api 存放接口请求封装、store 存放全局状态、utils 存放工具函数。如果项目里没有 api 目录所有接口请求都写在页面组件里那说明项目结构比较乱二开起来会非常痛苦。路由设计上首页、商品列表、商品详情这三个页面是可以公开访问的购物车、订单、个人中心需要登录后才能访问后台管理页面需要管理员权限才能访问。Vue Router 提供了路由守卫在 beforeEach 里判断用户的登录状态没登录的话跳转到登录页并带上回跳路径登录成功后自动回到之前的页面。这个细节很实用用户体验好也容易在答辩时讲。4.2 Axios 请求封装与 Token 携带前后端联调最关键的一步是封装 Axios。我会在 utils 目录建一个 request.js创建一个 Axios 实例设置基础请求地址、超时时间然后用请求拦截器把 Token 放到请求头里。响应拦截器做的事情更多根据后端返回的状态码做统一处理200 就直接返回数据401 就清除本地登录信息并跳转到登录页500 就弹出错误提示。Token 在 localStorage 或者 Vuex/Pinia 里存一份。刷新页面后登录状态不会丢因为路由守卫里会去 localStorage 读取 Token 来判断用户是否登录。4.3 商品与购物车页面的关键逻辑商品列表页和详情页相对简单主要把接口返回的数据渲染到页面上注意图片地址为空时要有默认占位图价格格式化要保留两位小数这些细节虽然小但影响观感。购物车页面是前端业务比较重的一块尤其是金额计算。购物车里每一项可以单独选择也可以全选页面底部要实时显示选中商品的合计金额和总件数。我的做法是在 Cart 页面维护一个本地数组每一项记录商品信息和选中状态然后用 Vue 的计算属性 computed 对选中项做遍历累加数量和金额。这样用户勾选任何一项下面的合计数字都会同步变化。结算时把选中项的ID和数量组装成数组传给后端创建订单接口。订单详情页展示订单状态、收货人信息、商品列表和金额明细。这时后端返回的订单金额就是最终金额前端不需要再做计算因为价格以后端计算为准前端只负责展示这也是前后端分离的一个原则凡是金额相关的操作都要以后端为准前端不能也不应该去“算总价”。4.4 后台管理端商品维护与订单处理的实现管理端页面从布局上用左侧菜单加右侧内容区路由用嵌套路由实现。商品管理页是一个表格带分页和搜索点击新增或者编辑时弹出弹窗或者跳转到表单页表单里用 Upload 组件上传商品图片。上传功能基于后端的文件上传接口前端把文件传给后端后端保存到服务器磁盘返回图片访问 URL前端把这个 URL 拼进商品信息里一起提交。这里有个容易出问题的地方本地开发时后端返回的图片地址可能是 localhost:8080 开头的绝对路径但前端跑在 localhost:5173如果路径写死就会跨域拿不到图。我的处理方式是后端保存图片后只返回相对路径前端在渲染图片时用当前环境的基础地址拼接这样本地和部署到服务器后路径都不会错。订单管理页对管理员来说主要做两件事查看订单列表和处理发货。列表用表格展示订单编号、用户、金额、状态、时间状态用标签样式区分颜色未发货的订单给一个“发货”按钮点击后调用后端接口修改状态并更新发货时间。5. 接口文档与 SQL 脚本交付别让源码栽在这些细节上5.1 一份能跑的接口文档要写清楚什么拿到带接口文档的项目先看文档质量。很多所谓的接口文档就是复制了几段 controller 代码既不完整也不规范。一份合格的接口文档至少要对每个接口写清楚六项内容请求地址、请求方式、是否需要登录、请求参数名称、类型、必填、说明、成功返回示例、错误码说明。对毕设项目来说接口文档建议写成 Markdown 表格目录按模块分好用户模块、商品模块、购物车模块、订单模块、管理模块。前端开发时可以照着一个接口一个接口对接省去反复问后端的麻烦。更重要的是答辩时评委通常会翻一眼文档一份整理过的接口文档能很快挂住印象分。举个例子商品列表接口的文档可以这样写参数类型必填说明pageint是当前页码pageSizeint是每页条数categoryIdint否分类ID不传查全部keywordstring否搜索关键字sortstring否排序default/priceAsc/priceDesc/sales返回内容里要写明每条商品记录包含哪些字段特别是图片地址和价格字段的数据类型前端才能正确渲染。5.2 SQL 脚本交付时的发布规范SQL脚本交付这件事看起来简单实际上特别容易出问题。我建议 SQL 脚本文件分成三层第一层是建库语句包括数据库名和默认字符集第二层是建表语句每个表带上 drop table if exists 前缀保证可以重复执行第三层是初始化数据包括管理员、测试用户、分类、商品、轮播图。字符集方面建库时明确指定 utf8mb4排序规则用 utf8mb4_general_ci不然中文可能出现乱码。表之间如果有外键关系建表顺序要注意先主后从虽然 MyBatis-Plus 项目里通常用逻辑关联而不是数据库外键但建表顺序还是会影响到导入时的报错。导入 SQL 时还容易遇到一个问题如果 SQL 文件里有特殊字符或者表情符号比如商品描述里带了一个 emoji而字符集不是 utf8mb4导入时会直接报错。这些细节在项目上线部署、数据库迁移时都会被放大提前处理好能省很多事。6. 部署上线与常见问题排查实录6.1 跨域问题本地联调和服务器部署两种处理方式前后端分离项目最典型的问题就是跨域。本地开发时前端跑在 5173 端口后端跑在 8080 端口端口不一样浏览器就会拦截跨域请求。有两种常规解决办法。第一种是后端写一个配置类实现 WebMvcConfigurer重写 addCorsMappings 方法允许指定来源跨域访问。这种方式写起来简单适合没有前端构建工具的本地调试或者后端接口要对外提供服务的场景。第二种是前端在开发服务器配置里做转发Vite 项目在 vite.config.js 里设置 server.proxy把 /api 开头的请求转发到后端地址。这样对浏览器来说前端页面和后端接口是同源的浏览器就不会产生跨域拦截。生产环境部署时一般由 Nginx 统一接管。前端构建出的静态文件放到 Nginx 的 html 目录后端在服务器上启动在某个端口Nginx 配置里把 /api 路径的请求转发到后端端口其他路径走静态文件。这套部署方式是当前前后端分离项目的标准姿势熟悉一遍对以后工作也有帮助。6.2 前端路由刷新 404最经典的部署坑如果你把前端项目部署到 Nginx然后直接访问某个子路由页面比如 /cart刷新一下可能就出现 404。原因是 Vue Router 默认用 history 模式URL 里没有 # 号看起来像真实路径但 Nginx 里并没有这个物理路径所以就报了 404。解决办法是在 Nginx 配置的 location / 里加上 try_files让它找不到对应文件时回退到 index.html。这样前端路由自己会匹配对应的页面组件问题就解决了。这个知识点几乎是部署类问题的必考项网上源码的部署文档里如果没写配置你大概率会踩这一脚。6.3 数据库连接与端口占用问题跑通项目时常见的报错有几个。第一个是数据库连不上报 Access denied for user检查数据库密码和配置文件里的密码是否一致检查 MySQL 服务是否已经启动。第二个是端口被占8080 端口被其他程序占用可以通过改后端配置文件端口或者找出占用进程来解决。第三个是时区问题报错里出现 server timezone 字样在 JDBC 连接串后面加上 serverTimezoneAsia/Shanghai 即可。还有一个特别容易忽略的问题就是数据库版本和驱动版本不匹配。如果 MySQL 是 8.0而 pom.xml 里的驱动是 5.1 系列的旧版本启动时也可能报通信链路异常。解决办法是把连接驱动版本换成和数据库对应的版本。6.4 免税商品场景的税价逻辑演示这个项目的业务背景是免税商城那演示时就要让这块有存在感。我的做法很简单商品详情页同时展示原价和免税价免税价的字体更大更显眼原价加上删除线放在旁边形成直观对比。购物车结算页里列出“商品总额”和“优惠金额”优惠金额就是原价总额减去免税价总额的差值这个数据在创建订单的接口里已经算好并传给前端了。答辩时如果被问到“免税价是怎么算的”回答思路可以这样组织商品表里存有原价字段免税价字段是在上架时由运营人员根据规则填写的相当于业务规则前置后端在下单时不关心价格是怎么来的只关心最终生效价是哪个字段。这套逻辑虽然简单但它把业务和系统解耦了就算题库规则怎么变订单系统都不需要跟着改。还有一点值得提库存扣减的并发处理。秒杀这类场景我建议不要在这个项目里实现但可以在论文里提一句“未来可以引入 Redis 缓存和分布式锁来处理高并发下的库存扣减”这样既不会增加开发工作量又能体现你的思考深度。我个人在实际操作中的体会是这类项目真正拉开差距的往往不是功能多少而是边界处理。你看很多源码主流程都通一提交订单就崩一删数据就报错一上传图片就找不到路径全是细节问题。另一个体会是拿到任何源码先补数据再跑起来把测试数据做好准备把演示路径想好答辩时就能从容很多。最后再分享一个扩展方向如果你时间充裕可以在现有商城基础上加一个 Redis 缓存热门的接口加一个消息队列处理订单通知或者用定时任务自动取消超时未支付订单。这几个点任何一个做出来都比换个前端框架更有含金量而且它们都是真实业务里会用到的东西对你后续找工作面试也有实实在在的帮助。