资讯详情

SpringBoot多商户潮鞋商城:从选题到答辩的完整毕设实践

📅 2026/10/19 15:11:11 | 华诺云谱 👁 阅读
SpringBoot多商户潮鞋商城:从选题到答辩的完整毕设实践
把“基于SSM的学生管理系统”“JSP图书商城”这类题目从毕业设计备选列表里划掉的那一刻我才真正开始琢磨什么项目值得花大半个学期认真做。最终我确定的方向是SpringBoot线上潮鞋商城一个多商户多用户购物平台既有用户端、商户端又有平台管理端业务链路完整技术点也不浮夸。做完之后回头看这个题目最大的价值在于它不只是一个“会CURD就行”的增删改查系统而是能把电商核心流程、多商户数据隔离、权限控制、订单状态流转这些面试常问的东西全部串起来。如果你也在纠结毕业设计选题或者想找一个能写进简历的SpringBoot项目这篇内容基本覆盖了从选题、设计到落地、答辩的完整过程源码也整理在文末说明里。1. 这个选题到底香在哪从“烂大街管理系统”到“多商户潮鞋商城”1.1 为什么年年有人栽在“管理系统”上每年到了毕业设计开题季总有大量同学选择“某某信息管理系统”“某某后台管理平台”这类题目。不是说管理系统不能做而是这类题目的同质化太严重评委一眼就能看出工作量和技术含量。做过的人都知道大部分管理系统的核心就是一张表、几个页面的CURD难点几乎没有答辩时能讲的内容也非常有限。更麻烦的是这类项目很难展示你对业务的理解因为“管理”本身不是一个具体场景缺乏可以深挖的规则。我见过一个比较典型的翻车案例某同学选了一个“健身房会员管理系统”代码写了不到两千行数据库就三张表答辩时老师问“会员过期续费是怎么处理的”他只能答“手动修改到期时间”。这种项目就算功能能跑也谈不上设计更谈不上亮点。相比之下电商商城类项目天然带有用户行为、商品状态、订单流转、库存扣减、资金结算这些有逻辑深度的场景任何一个点都可以展开讲出东西来。1.2 潮鞋商城的两层巧思场景熟悉 多商户结构为什么是潮鞋而不是普通商品原因很简单潮鞋商品有明确的SKU属性鞋码、配色、发售批次有“限量”“热门”这类标签天然适合做商品筛选和详情展示演示效果比卖图书、卖日用品要好看得多。更关键的是潮鞋领域的用户心智是“多品牌、多店铺”这正好支撑了“多商户”的设计前提不同商户上传自己的鞋款平台做统一流量和交易管理商户之间互不可见、独立经营。多商户结构也就是常说的B2B2C模式是区分“毕业设计普通货”和“有一定设计感项目”的分水岭。单商户商城只需要考虑一个卖家而多商户商城必须回答几个问题不同商户的商品怎么隔离存储用户一次购买多个商户的商品订单怎么拆分商户登录后怎么保证只能看到自己的商品和订单平台方怎么审核商户入驻、怎么结算货款这些问题的答案会直接体现在数据库设计和接口设计里答辩时每一条都能拿出来讲。这也是我把题目的最终形态定为“SpringBoot线上潮鞋商城多商户多用户购物平台”的原因。1.3 功能范围的收敛不要一上来就想做“淘宝”很多同学做毕设最大的问题不是不会做而是想要的太多。今天想加秒杀明天想加直播后天想加推荐算法结果做到最后期中期都过不了。我当时给自己定了一条硬规矩核心链路必须完整非核心功能一律砍掉。最终收敛出来的功能范围是这样的用户端注册登录、浏览商品、商品搜索筛选、购物车、提交订单、模拟支付、查看订单、收货确认、评价商品。商户端商户入驻申请、商品管理上下架、库存、SKU、订单发货、查看营收数据。平台端商户入驻审核、商品类目管理、平台数据看板、用户管理。砍掉的东西包括秒杀、优惠券、拼团、直播、推荐算法、物流轨迹对接。原因是这些功能要么对基础设施要求极高比如秒杀要搞Redis队列要么需要第三方接口配合比如物流查询在毕业设计周期内很容易失控。做减法不是偷懒而是确保每个保留的功能都能做到“能演示、能讲清、能扛住提问”。这十条也是我给准备做商城类项目的人最真诚的建议。2. 系统架构与角色权限多商户多用户的“多”到底怎么落地2.1 三种角色和他们的边界多商户商城最核心的不是代码写得多花哨而是角色边界是否清晰。系统里一共有三类用户平台管理员、商户、普通用户。这三个角色对应的业务操作完全不同权限控制是系统的第一道关卡。平台管理员负责审核商户入驻申请管理商品类目查看全平台订单和数据统计。理论上平台管理员不应该去修改商户的商品否则就破坏了平台的中立性。商户只能操作自己店铺范围内的东西包括商品管理、SKU维护、订单发货、店铺信息。商户之间是隔离的A商户不能看到B商户的商品库存更不能处理B商户的订单。普通用户只能操作自己账号下的数据包括购物车、订单、收货地址、收藏和评价。用户也不能越权查看他人的订单信息。这三个角色我用了一套用户表 角色字段来区分登录后根据角色返回不同的菜单和可用接口。用户表和商户表在物理上是分开的商户有独立的审核状态字段待审核、已通过、已驳回、已冻结这样处理比在用户表里塞一个“商户类型”字段干净得多。2.2 技术栈选型为什么是SpringBoot打底整个项目的技术栈选择是基于“毕业设计既要能写明白又要扛得住追问”这个原则来定的。层次选型选它的理由后端框架SpringBoot 2.7.x简化配置、生态成熟、简历上最常见ORM层MyBatis-Plus单表CRUD效率高分页插件好用多表SQL手写灵活鉴权方案JWT 拦截器无状态、前后端分离友好能讲清楚Token校验逻辑缓存Spring Data Redis首页轮播、商品热门榜、Token黑名单有一定技术含量数据库MySQL 5.7/8.0最常用的关系型数据库事务支持可靠前端Vue3 Element Plus用户端和商户端都用组件齐全演示效果好构建工具Maven最主流的Java构建方式当时我也纠结过要不要用Spring Cloud Alibaba加个Nacos、Feign什么的显得体系庞大。后来想明白了一个道理你不是在做一个生产级微服务平台你是在做毕业设计。单体应用完全能支撑这个体量微服务反而会让答辩焦点从业务逻辑转移到“为什么拆服务”“拆了有什么好处”这种你未必能讲清楚的问题上。单体优先是务实的选择。2.3 前后端分离和“后台三件套”的布局项目前端用的是Vue3 Element Plus后端只提供JSON接口前端通过Axios调用生产环境打包后由SpringBoot的Static目录托管。这样做的好处是答辩的时候既能展示“我懂前后端分离的开发模式”又不需要真的去运维一套Nginx加两台服务器——本地演示一个SpringBoot进程就能全部跑起来。用户端页面主要包含首页轮播、推荐潮鞋、商品列表页分类筛选、关键词搜索、按价格/热度排序、商品详情页SKU选择、尺码库存展示、购物车多商户商品统一展示、按商户拆分结算、订单确认页、个人中心订单列表、收货地址、评价入口。商户端是独立的后台界面登录后进入店铺工作台商品列表上架/下架/编辑、商品发布图片上传、SKU设置、库存填写、订单管理发货操作、查看订单明细、数据概览订单数、销售额、商品数。平台端同样是一个后台界面商户审核列表、类目管理、全平台订单查询、用户管理、数据统计。三个前端界面可以打包成同一个前端工程通过路由守卫和动态菜单区分角色这也是比较标准的企业后台做法。Configuration public class WebMvcConfig implements WebMvcConfigurer { Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new JwtInterceptor()) .addPathPatterns(/api/**) .excludePathPatterns(/api/user/login, /api/user/register, /api/public/**); } }3. 核心业务流程拆解下单、结算、发货、入驻背后的实现逻辑3.1 登录与鉴权JWT拦截器和ThreadLocal的配合先聊登录。用户、商户、管理员共用一个登录接口参数是账号和密码后端校验通过后生成一个JWT Token返回给前端。Token里面只放userId和role不敏感。前端把Token存在localStorage里每次请求在Header中带上Authorization: Bearer xxx。后端拦截器干两件事第一解析Token如果解析失败或过期直接返回401第二解析成功后把userId、role放到ThreadLocal里这样Controller里面调LoginUtil.getUserId()就能拿到当前登录人非常方便。public class JwtUtil { private static final SecretKey KEY Keys.hmacShaKeyFor(your-secret-key-please-change-in-prod.getBytes()); public static String generateToken(Long userId, Integer role) { return Jwts.builder() .claim(userId, userId) .claim(role, role) .setExpiration(new Date(System.currentTimeMillis() 7 * 24 * 3600_000L)) .signWith(KEY) .compact(); } }权限校验这里有个容易忽略的坑拦截器只解决“你是否登录”不解决“你能不能操作这份数据”。商户删除商品时SQL里必须带上merchant_id 当前登录商户id这个条件否则一个商户就能操作别家商品。这是典型的数据权限问题我是在开发中后期被一个测试同学点醒才彻底补齐的后面在踩坑章节会展开讲。3.2 购物车和结算拆分一个订单还是多个订单用户加购的时候购物车条目会同时记录商品SKU信息和所属商户ID。因为不同商户的商品归属不同结算时就必须做拆分用户勾选购物车里的多个商品如果涉及三个商户系统会创建三个订单每个订单包含一个商户的商品集合。实现方式不复杂前端把勾选的购物车条目ID传给后端后端查出所有条目后按merchantId分组然后循环创建订单头订单主表和订单明细表。为了保持简单一个交易批次里每个商户只会生成一笔订单订单状态统一流转。这里还有一个细节订单表里需要冗余存一个merchant_id字段而不是只通过订单明细反查。因为订单列表页需要按商户维度过滤冗余字段能省一个子查询而且逻辑上也直观。多商户系统的日常开发里“该冗余的字段就要冗余”这是和单商户系统不太一样的地方。3.3 扣库存与下单的顺序问题先校验还是先锁潮鞋商城最怕的就是“超卖”也就是库存只剩1双结果同时有三个人下单成功。我采用的方案是乐观锁 条件更新重点是扣减库存时加上“当前库存大于等于购买数量”这个条件。UPDATE product_sku SET stock stock - #{count} WHERE id #{skuId} AND stock #{count}MyBatis-Plus的update方法返回受影响行数如果返回值是0说明库存不足代码里直接抛出“库存不足”异常并让事务回滚。这里我额外加了Transactional保证“扣减库存”和“创建订单”两个操作要么都成功要么都失败。这个写法我在答辩前重点准备了面试问“你怎么防止超卖”就是照这个思路回答。3.4 模拟支付与平台结算毕业设计也要讲清楚钱怎么分真实支付需要接入微信支付/支付宝毕业设计没必要也不会给你通过审核。我做的方案是“模拟收银台”用户下单后进入支付页点击“模拟支付”后端生成一条支付流水将订单状态从未支付改为已支付同时通知商户。比较有意思的是平台结算逻辑。多商户商城必须回答一个问题用户付的钱怎么分我设计得比较简练支付成功后订单金额拆成“商户可结算金额”和“平台服务费”两部分平台服务费比例在商户入驻时就约定好比如5%。平台端有一个结算单列表记录每笔订单平台应收多少、商户应收多少管理员可以执行“确认结算”此时订单的结算状态变为已结算。这一整套逻辑并不复杂但能体现你对多商户电商业务的理解。答辩的时候老师很可能会问“平台赚什么钱”“商户怎么提现”这两个问题能立刻回答清楚项目档次就不一样了。3.5 商户入驻和审核只有“审核通过”才能开张商户入驻的流程走了一个标准闭环用户提交入驻申请填写店铺名称、联系人、手机号、经营品类系统生成一条入驻申请记录状态为“待审核”。平台管理端看到申请后点击通过商户账号的状态变为“已通过”此时该商户才能发布商品。如果被驳回会记录驳回原因申请者可以修改后重新提交。这里有一个隐蔽的需求点普通用户注册之后并没有商户后台的入口。只有审核通过的账号登录后返回的角色才是“商户”前端才会展示商户端菜单。所以那个“审核状态”字段不只是在商户表里放着好看它是登录后返回不同页面权限的依据。4. 数据库表设计多商户商城的地基怎么打才稳4.1 核心表清单和表之间的关系表结构是答辩时高频被翻出来的内容我整理成了下面的主要表数据域表名说明用户user账号、密码BCrypt加密、昵称、手机号、角色商户merchant店铺名称、联系人、审核状态、平台服务费率类目category潮鞋类目比如篮球鞋、跑步鞋、板鞋商品product商品基本信息、所属商户、类目、上下架状态库存product_sku尺码、颜色、库存数、价格一个商品多个SKU购物车cart_item用户ID、SKU ID、数量、选中状态订单order订单号、用户ID、商户ID、总金额、状态、支付时间订单明细order_item订单ID、SKU ID、商品快照、单价、数量支付流水payment订单ID、支付金额、支付状态、支付时间结算单settlement订单ID、平台服务费、商户结算金额、状态收货地址address用户ID、收货人、电话、省市区、详细地址平台轮播banner图片URL、跳转链接、排序值一个商品对应多个SKU这是潮鞋类目的刚需。以一双热门球鞋为例可能有40码到45码六个尺码有经典配色和限量配色两种SKU每个SKU价格和库存不同。订单明细表里保存的是“商品快照”——包含商品名、图片、SKU描述、单价原因是商品后续可能改名、改价但订单作为交易凭证必须保留当时的信息。4.2 为什么不滥用外键为什么金额必须用decimal多商户系统里跨表查询特别多如果每个表都加物理外键插入和更新会有额外性能损耗而且在分库分表场景下外键基本不可用。我实际设计时表与表之间只保留逻辑关联也就是merchant_id、sku_id、order_id这些普通索引字段关联关系写在SQL的JOIN条件里。这样开发灵活数据量上来后也方便拆表。金额类型是另一个经常被忽视的点。刚开始有个同事把订单金额设计成了double结果计算总价时出现了一长串小数原因就是浮点数的二进制精度问题。所有金额字段统一使用DECIMAL(10, 2)Java实体类用BigDecimal接收。这是电商项目里非常基础但重要的一个规范写进设计文档里会显得你很专业。4.3 订单号的生成规则时间戳加随机数不只是为了好看订单号我采用的格式是yyyyMMddHHmmss 4位随机数 用户ID后四位长度大概20位。为什么不能只用自增ID因为订单号在支付、对账、客服沟通里是要给人看的自增ID会暴露订单量而且跨系统通信时自增ID太容易猜测。用时间戳加随机数既保证了大致有序也让每个人都能从订单号里读出下单时间演示时也更好解释。如果以后要做高并发这个方案会产生重复风险可以换成雪花算法。但在毕业设计这个场景时间戳加随机数已经足够而且答辩时你可以主动说出“如果订单量大可以升级为雪花ID”这个加分项是白给的。5. 开发过程中踩过的坑超卖、越权、文件图片存储这类问题5.1 数据权限漏洞看似只能看到自己的其实能操作别人的这个坑说出来挺丢人的但很值得写。最初我在商户端删除商品时只写了deleteById(productId)没带商户ID条件。理论上登录商户B只要知道商品ID就能把商户A的商品删掉。虽然前端菜单根本不显示别人的商品但只要打开控制台手动调接口立刻越权。后面我花了一个晚上把所有商户接口、用户接口全部梳理了一遍统一改成“先查出归属再判断当前登录人是否有操作权限”的写法。比如商户修改商品Product product productService.getById(productId); if (!product.getMerchantId().equals(currentMerchantId())) { throw new BusinessException(无权操作该商品); }这条经验换成一句话就是前端隐藏按钮不是权限控制后端接口校验才是。答辩时主动提到这一点评委大概率会追问你怎么做的权限控制正好可以把JWT、ThreadLocal、数据权限三层讲一遍。5.2 库存为负数乐观锁解决了超卖但别忘了校验商品状态超卖问题用乐观锁解决之后我又遇到了一个次生问题一个已经下架的商品如果用户在商品详情页停留了很久再下单接口还是会去扣库存。因为扣库存SQL只看库存条件没检查商品状态。后来在下单接口里增加了前置校验商品必须处于上架状态、SKU必须是启用状态、库存充足、商户状态正常四条校验都通过才允许创建订单。这个顺序必须放在扣库存之前否则会出现“扣了库存但订单创建失败”的尴尬情况。事务可以保证数据一致性但提前拦截无效请求能让用户的体验好很多。5.3 图片上传本地目录存储加虚拟路径映射商品图片是电商项目的门面一开始我把图片转成Base64塞到数据库字段里结果商品列表接口返回的数据量大到页面明显卡顿。后来改成文件上传方案后端接收MultipartFile保存到本地的/upload/目录文件名用UUID 原扩展名然后把文件路径返回给前端。为了让前端能通过URL直接访问图片SpringBoot里要配置一个虚拟路径映射把请求路径/images/**映射到本地磁盘目录Configuration public class WebMvcConfig implements WebMvcConfigurer { Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler(/images/**) .addResourceLocations(file: System.getProperty(user.dir) /upload/); } }这个方案在小体量项目里完全够用部署时也只需要多拷一个upload目录。如果是大项目就得考虑OSS或MinIO了不过我建议毕业设计阶段就到本地存储为止讲清楚“生产环境可以换对象存储”就足够了。5.4 跨域问题和缓存设计的两个小坑前后端分离开发时前端开发服务器运行在5173端口后端在8080端口直接请求接口会被浏览器拦截。解决方式是后端加一个全局CORS配置允许指定来源访问。这里注意一个细节allowedOriginPatterns别用*加allowCredentials(true)的组合浏览器会直接报错要用具体的来源列表或带通配的Pattern。Redis缓存我最初只缓存了首页banner和商品分类后来商品搜索列表也加了Redis缓存还会在商品上下架时手动删除对应的缓存key。当时看效果不错但实际上碰到过一个问题发布新商品后商品列表迟迟不显示新数据因为列表缓存的key没有和商品变更联动。所以我把缓存key设计成包含“商户ID 类目ID 页码”的格式并在商品上下架接口里主动清理相关列表缓存。因为毕业设计的数据变更频次不高这种“主动失效”的方案比设置复杂过期策略要直接得多。6. 拿到源码后怎么跑起来答辩怎么讲才有亮点6.1 源码结构和初始化步骤一个合格的SpringBoot项目源码拿到手后应该可以“三步跑起来”创建数据库、改配置文件、启动项目。我的项目目录结构大致是这样的shoe-mall ├── sql/ # 数据库初始化脚本 │ └── shoe_mall.sql # 建库、建表、演示数据 ├── upload/ # 上传图片本地目录 ├── src/main/java │ ├── config/ # 跨域配置、拦截器注册、Redis配置 │ ├── controller/ # 用户端、商户端、平台端接口 │ ├── service/ # 业务逻辑层 │ ├── mapper/ # MyBatis-Plus的Mapper接口 │ ├── entity/ # 实体类 │ ├── common/ # 统一返回结果、异常处理、工具类 │ └── ShoeMallApplication.java ├── src/main/resources │ ├── application.yml # 数据源、Redis、文件上传配置 │ └── mapper/ # 复杂SQL的XML文件 ├── frontend/ # Vue3前端工程 │ ├── src/views/ # 用户端页面 │ ├── src/views/merchant/ # 商户端页面 │ ├── src/views/admin/ # 平台端页面 │ └── vite.config.js # 本地开发代理配置 └── README.md # 项目说明和部署文档数据库脚本里预置了三类演示账号一个平台管理员、两个审核通过的商户、几个普通用户还造了一些潮鞋商品数据和订单数据。这样演示的时候不用现场注册、现传图片打开首页就能看到效果。6.2 本地启动会遇到的两个最常见问题先说端口占用。SpringBoot默认8080前端开发Server默认5173如果你本机端口被其他进程占了启动会直接报错。解决方式很简单改application.yml里的server.port或者改前端vite.config.js里的代理目标保持两边一致即可。再说前端运行依赖。前端工程需要Node.js环境建议用长期支持版本先npm install再npm run dev。如果node_modules安装慢可以换国内镜像源。这里提醒一句源码压缩包里通常不会带node_modules一定要先装依赖再跑前端这个步骤不能跳过。6.3 答辩现场怎么演示和讲思路答辩的时间一般不长演示要抓重点我建议按这个顺序来先演示用户端完整购物场景注册/登录 → 浏览潮鞋商品 → 点击详情选尺码SKU → 加入购物车 → 结算生成订单 → 模拟支付 → 查看订单状态。这条链路跑通业务闭环就展示清楚了。切换到商户端演示发货流程进入订单管理找到已支付订单执行发货订单状态变为已发货。切换到平台端展示商户审核流程和数据看板说明平台如何介入管理。打开数据库设计文档或表结构重点讲“多商户如何隔离”“订单如何拆分”“库存如何防超卖”。答辩时老师大概率会问这几个问题项目难点是什么、某个状态是怎么流转的、如果并发高怎么办。对应的回答思路分别是多商户数据权限隔离、订单状态机设计待支付→已支付→已发货→已收货→已完成、乐观锁扣库存配合事务保证一致性。6.4 如果还想往上加分可以在哪些点上扩展做完基础版本之后时间和精力允许的话有几个扩展点性价比很高商品搜索接Elasticsearch替换掉SQL模糊查询。这个改动比较大但讲出来就是一个完整的进阶亮点。秒杀场景复用已有的SKU库存表加上Redis预扣库存可以讲高并发削峰。后台增加Spring Security替换手写拦截器虽然学习成本高一点但安全这块专业度会明显提升。图表展示订单趋势、销售排行使用ECharts很容易实现视觉效果好答辩时挺加分的。我的建议是如果当前版本已经稳定优先保证把核心链路吃透扩展点只在你有余力的时候再加。毕业设计的本质是“用一学期的时间证明你能独立完成一个完整软件系统的分析、设计、开发、测试和文档编写”而不是堆砌功能数量。源码头尾的README里我写了详细的启动步骤、账号密码和演示脚本照着走就能跑出效果。希望这篇内容能帮你少走几个我在开发时踩过的弯路也希望你答辩那天能从容地把每一处设计讲清楚。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑