SpringBoot+Vue网上服装商城管理系统:完整前后端分离实战解析

发布时间:2026/10/5 19:49:20
SpringBoot+Vue网上服装商城管理系统:完整前后端分离实战解析 网上服装商城管理系统算是我把SpringBootVue这一套组合从“会写接口”到“能完整交付一个项目”的关键练手作品。这个项目后端用SpringBoot Java MySQL MyBatis前端用Vue全家桶实现了用户注册登录、商品浏览搜索、购物车、下单流程、订单管理、后台商品管理等功能。对刚准备做毕设或者想熟悉前后端分离开发流程的同学来说这是一套可以直接参考甚至跑起来的完整源码不是零散Demo而是完整业务闭环。先说清楚它解决的问题很多初学者写商城项目容易出现前端是一套后端是另一套最后硬凑在一起对不上接口或者只做好了商品展示订单模块直接放弃。这个项目在设计之初就把“前后端分离、接口先行、状态明确”作为核心把商品、用户、购物车、订单这条主链路全部打通。下面我从技术选型、数据库设计、后端实现、前端实现到部署排错完整聊聊这个系统是怎么做出来的以及实测中踩过哪些坑。如果你正处于以下阶段需要交一个课程设计或毕业设计想了解真实项目里SpringBoot如何整合MyBatis或者想知道Vue项目打包后怎么放进SpringBoot统一部署这篇内容都能给你一个比较完整的参考路径。完整源码的骨架并不复杂但把它讲透能少走不少弯路。1. 项目概述与系统目标1.1 为什么选择SpringBootVue组合先聊选型。市面上的商城项目模板很多有用JSP的也有前后端完全分离的但SpringBootVue这套组合在校园项目和企业初期项目中尤其常见。SpringBoot解决了Spring繁琐的XML配置问题用自动配置和starter依赖让一个Web服务几分钟就能跑起来Vue则用组件化和响应式数据绑定把页面交互做得很轻快。两者结合正好是“后端负责数据和业务规则前端负责展示和交互”的清晰分工。我选择这套组合还有一个现实原因资料多、招人问得多。无论是Java面试还是前端面试SpringBoot和Vue都属于高频考点做完这个项目之后去面Java开发岗聊项目经历至少能说清楚“用户从注册到下单这条链路里每一步数据是怎么流转的”。而且部署也简单后端可以打成Jar包前端可以打成静态文件放进SpringBoot一个进程就能跑整个系统对服务器资源不宽裕的场景非常友好。1.2 系统核心角色与功能边界整个商城系统分成两个角色普通用户和后台管理员。用户端主要功能包括注册登录、商品分类浏览、关键词搜索、商品详情、加入购物车、下单、查看订单列表和订单状态。后台管理端则包括商品分类管理、商品上架下架、库存调整、订单发货、用户列表查看等。功能边界一定要在设计初期划清楚否则写着写着就会膨胀。比如用户端要不要做支付我在这版源码里用“模拟支付”处理下单后默认待发货避免审单、对账这些复杂逻辑。后台要不要做权限细分管理员直接用一个角色访问后台接口时统一拦截。这样既保证了核心流程完整又不至于让代码量失控。你要做毕设也建议先划好这个边界把“核心链路跑通”放在第一位再考虑优惠券、秒杀这类扩展功能。2. 技术栈选型与整体架构2.1 后端SpringBoot MyBatis的组合逻辑后端基础框架是SpringBoot 2.x MyBatis MySQL额外用到了Lombok减少实体类样板代码、Hutool或Apache Commons处理字符串和集合、JWT做登录令牌。SpringBoot负责接收HTTP请求、参数校验、依赖注入和全局异常处理MyBatis负责把Java方法映射成SQL语句灵活度比JPA更高适合我这种喜欢直接控制SQL的人。有些同学喜欢用MyBatis-Plus确实能省不少CRUD代码但这版源码我保留的是纯MyBatis原因是网上商城有大量动态查询和关联查询纯XML能更清楚地看到每一条SQL。比如商品列表有分类ID、关键字、价格区间、上下架状态等多个筛选条件MyBatis的动态SQL可以按需拼接where语句执行计划更可控。真实业务里SQL出问题往往是性能瓶颈最大的地方所以把SQL握在自己手里更踏实。2.2 前端Vue Element UI Axios前端用的Vue 2 Vue Router Vuex Element UI。Vue 2在国内项目里存量很大教程好找生态稳定选它不容易掉进新版本兼容的坑。Element UI提供了一套现成的后台管理组件像表格、表单、对话框、分页器这些直接拿来用页面效果也算专业。Axios用于发送HTTP请求统一封装了请求拦截器和响应拦截器。请求拦截器里从localStorage取token加到请求头响应拦截器里判断HTTP状态码和业务状态码如果登录过期就跳转到登录页。这套写法几乎每个前后端分离项目都用值得记下来。另外Vue Router路由表按模块拆分商品页、购物车、订单中心、后台管理每个模块独立懒加载初次加载体积更小。2.3 后端包结构与接口设计后端采用经典分层controller负责接收请求参数和返回结果service负责业务逻辑mapper负责数据库操作pojo里放实体类dto放接收参数的传输对象vo放返回给前端的视图对象。如果项目里遇到多个模块都要用的通用返回结构就放在common包。接口设计统一走RESTful风格GET /api/product/list表示分页查询商品POST /api/cart/add表示加入购物车PUT /api/order/status表示更新订单状态。后端统一返回Result对象结构是code、message、data三个字段。这样前端只用判断code是否为200逻辑统一避免了“有的接口返回JSON有的接口直接返回字符串”这种混乱情况。前端配合request.js里的拦截器基本不用在每个页面重复处理错误提示。3. 数据库设计与核心表结构3.1 数据建模的核心思路数据库设计是这个项目最值得花时间的地方。我一般先画业务链路用户注册后浏览商品商品属于分类用户把商品加入购物车购物车中的条目最终生成订单订单里包含多个订单项。所以最基本的表是user、category、product、cart_item、order、order_item。另外还需要一张address表存收货地址用来在下单时生成收货信息。设计表的时候要特别注意关联关系。一个订单对应多个订单项所以订单表和订单项表是“主表-子表”结构订单项里存下单时的商品快照包括商品名称、图片、单价、数量。为什么存快照因为商品价格和名称后续可能会改如果只关联商品ID历史订单显示的数据可能和用户当时购买的不一致。所有需要保留历史状态的业务都要做这种快照设计。3.2 核心表结构与字段解析用户表的主要字段有id、username、password、nickname、phone、avatar、role、create_time。密码不能存明文我用了BCrypt加密登录时比对加密后的哈希值。商品分类表很简单id、name、sort、status。商品表字段稍微多id、category_id、title、cover、images、detail、price、stock、sales、status、create_time。images可以用JSON字符串存多张商品轮播图查询时前端再解析price用decimal(10,2)避免浮点数精度问题stock用int每次下单都做库存校验。购物车表字段是id、user_id、product_id、quantity、checked用user_id product_id建唯一索引防止同一个商品重复添加。3.3 订单状态流转和订单项设计订单表字段要多一些id、order_no、user_id、address_id、total_amount、status、pay_time、delivery_time、finish_time、create_time。这里order_no建议用“时间戳随机数”生成比如20250114120345加六位随机数避免并发下重复。订单状态我用0待付款、1待发货、2待收货、3已完成、4已取消这几个值前端根据状态值显示对应的操作按钮。订单项表字段包括id、order_id、product_id、product_title、product_image、product_price、quantity。下单时在事务里做三件事插入订单主表、批量插入订单项表、清空购物车对应条目。这里必须用数据库事务任何一步失败都要整体回滚否则会出现“订单创建了但购物车没清空”或者“库存扣了但订单没生成”的数据不一致问题。4. 后端核心功能实现4.1 用户注册登录与JWT拦截器用户模块最核心的就是密码加密和身份校验。注册接口接收用户名和密码先校验用户名是否已存在存在则直接返回“用户名已被注册”否则用BCrypt加密后写入数据库。登录接口根据用户名查出用户用BCryptPasswordEncoder.matches()比对密码比对成功就生成JWT令牌返回给前端。JWT令牌里我只放userId和role签名密钥配置在application.yml里。后端写一个LoginInterceptor拦截器拦截所有以/api/**开头的请求放行/api/user/login、/api/user/register、/api/product/**等公开接口其余接口校验请求头里的token。有一个坑前端请求时可能把token写成Authorization后端也要在拦截器里从request.getHeader(Authorization)取否则会一直提示未登录排查半天还找不到原因。4.2 商品分页查询与多条件动态SQL商品列表页要支持分页、分类筛选、关键字搜索、价格区间这是MyBatis动态SQL最典型的应用场景。我写一个ProductMapper.xml核心SQL大概是select idselectPage resultTypecom.example.shop.pojo.Product select * from product where if testcategoryId ! null and category_id #{categoryId} /if if testkeyword ! null and keyword ! and title like concat(%, #{keyword}, %) /if if testminPrice ! null and price gt; #{minPrice} /if if testmaxPrice ! null and price lt; #{maxPrice} /if and status 1 /where order by id desc limit #{offset}, #{pageSize} /select这里status 1是强制条件保证前端只能看到上架商品。分页没有用PageHelper插件而是手动传入offset和pageSize虽然多写两行代码但能看到很清晰的SQL逻辑。where标签会自动去掉多余的and比直接用where 11更规范也更容易写对。注意价格比较的gt;和lt;是XML中大于等于、小于等于的转义写法漏掉转义启动时会报XML解析错误。4.3 购物车与订单提交的事务控制购物车模块相对简单加入购物车时先查购物车表里有没有该用户和该商品的记录有就累加数量没有就新增。购物车里展示数据时要关联商品表查出最新的商品标题、单价、图片和库存前端让用户勾选需要结算的商品。订单提交是整个后端逻辑最重的部分。我在OrderService里写了一个带Transactional的方法先校验下单的商品是否还有库存然后算总价生成订单号插入订单和订单项最后扣减库存并清空购物车。库存扣减的SQL要写成update product set stock stock - #{quantity} where id #{id} and stock #{quantity}这一句用数据库行锁防止超卖。如果你直接把库存查出来在Java里减并发下一定会超卖这个坑我测试时用JMeter压过几十个并发就出了问题。4.4 MyBatis的Mapper接口、缓存与踩坑写Mapper接口时方法参数多个时要加Param注解比如ListProduct selectPage(Param(categoryId) Integer categoryId, Param(keyword) String keyword);不加的话MyBatis会提示Parameter xxx not found。实体属性和表字段不一致时要么开启驼峰映射map-underscore-to-camel-case: true要么用resultMap显式映射二选一即可。我建议两种都掌握因为面试时候很可能会被问到。关于MyBatis缓存项目里我没开二级缓存。商城系统的商品库存和价格是实时数据缓存稍不注意就会给用户展示过期信息。虽然一级缓存默认开启但不同会话不共享意义不大。如果以后要做高并发更合适的办法是引入Redis缓存商品列表热点数据MyBatis缓存就不要在订单这类写多场景里用了。这一块如果面试官问你可以很自信地聊出来。5. 前端页面与交互实现5.1 Vue项目搭建与路由设计前端我直接用Vue CLI创建项目命令是vue create shop-web选择Router和Vuex后续再手动安装Element UI和Axios。路由设计上用户访问首页、商品列表、商品详情、购物车、订单列表后台管理单独放在/admin路径下用嵌套路由把商品管理、分类管理、订单管理串起来。路由守卫是前端必须做的校验。我在router.beforeEach里判断目标路由的meta.requiresAuth如果为真就检查localStorage里的token没有token就跳转登录页。后台管理路由再加一层meta.role admin的判断普通用户无权限访问。注意用户登录后刷新页面Vuex里的用户信息会丢失所以持久化用户信息要用localStorage刷新时再从本地读取并重新初始化Vuex。5.2 商品列表与购物车交互商品列表页用el-card配合图片懒加载展示商品点击卡片跳转到详情页。搜索框输入关键字后触发列表接口重新请求分页组件绑定currentPage和pageSize每次翻页都调用fetchList()方法。这里有个小细节切换页码时要把滚动条滚回顶部否则用户翻页后还停留在页面底部体验很差。加入购物车时页面调POST /api/cart/add成功后在顶部显示“已加入购物车”的轻提示。购物车页面的每个条目都可以修改数量、勾选/取消勾选、删除。结算按钮读取当前勾选的条目把商品ID和数量提交给订单创建接口。前端要知道一件事购物车里的数量不能超过库存下单接口也会二次校验所以前端要提前禁用超出部分减少无效请求。5.3 Axios统一封装与接口对接前端所有请求统一走src/utils/request.js这个文件里用Axios创建实例设置baseURL为/api超时时间10秒。请求拦截器里从localStorage取token并放到Header响应拦截器里先判断HTTP状态码200后再看后端返回的code字段。code不是200时通过Element UI的Message.error弹出错误信息同时把Promise reject掉避免页面里到处写try catch。接口对接过程中最烦的是日期格式。Java后端返回的LocalDateTime默认序列化成2025-01-14T12:30:00这种格式前端展示起来不好看我直接在实体类的日期字段上加JsonFormat(pattern yyyy-MM-dd HH:mm:ss, timezone GMT8)统一成中国时区的常用格式。还有一个协同问题后端接口字段命名用驼峰前端用下划线两边经常对不上。我让后端统一返回驼峰JSON前端全部按驼峰取字段约定好了以后联调成本立刻降下来。6. 完整源码运行与部署指南6.1 本地环境准备运行这套源码前先把环境准备好。JDK要求1.8以上我推荐用JDK 8或者JDK 11太新的版本可能会出现某些依赖兼容问题。MySQL我用5.7也可以用8.0但要注意8.0的驱动类名是com.mysql.cj.jdbc.Driver连接串里要加serverTimezoneAsia/Shanghai否则会报时区错误。前端环境需要Node.js我用的是14版本。如果你装的是Node 18以上也可以跑但Vue CLI 5对高版本Node的兼容性问题偶尔会出现用了新版本Node可以先执行npm install看有没有报错再决定是否降级。IDE方面后端用IDEA前端用VS Code两者都装好。数据库工具推荐Navicat或者DataGrip导入SQL文件方便。6.2 数据库初始化与配置修改源码包里会有一个shop.sql文件里面包含建库、建表和初始化数据。用Navicat新建一个数据库字符集选utf8mb4排序规则选utf8mb4_general_ci然后直接运行SQL脚本。脚本里会默认创建管理员账号admin和测试用户方便你登录测试。后端配置在src/main/resources/application.yml里需要修改的主要是数据源spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/shop?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: 你的数据库密码 mybatis: mapper-locations: classpath:mapper/*.xml configuration: map-underscore-to-camel-case: true另外JWT的secret和token过期时间也在这个文件里测试阶段可以直接用默认值。改完密码后启动如果控制台出现Tomcat started on port(s): 8080说明后端已经跑起来了。6.3 后端启动与接口验证后端启动有两种方式。第一种是IDEA里直接运行主类Application.java适合开发调试。第二种是打包后运行java -jar shop-admin.jar适合部署。打包命令是mvn clean package -DskipTests打包前确保测试用例不会影响构建如果某个测试类纯属多余可以加SpringBootTest的排除配置或者直接删掉测试目录。启动后可以用Postman或者Apifox验证接口。先调POST /api/user/login拿到token后放到请求头再调GET /api/product/list看是否能返回商品分页数据。验证接口通过后再启动前端避免前端一打开就全是网络错误。6.4 前端启动与打包放进SpringBoot前端开发环境启动很简单npm install npm run serve默认端口是8080但后端的SpringBoot也占8080所以我一般把vue/cli服务端口改成8081在vue.config.js里配置devServer.port 8081并设置proxy把/api代理到http://localhost:8080这样开发时就不存在跨域问题。如果现在你用的是Vite创建的项目对应配置写在vite.config.js里逻辑类似。正式部署时执行npm run build生成dist目录里面是编译后的index.html和静态JS/CSS文件。后端为了让前端能一起跑把dist里的所有文件复制到SpringBoot项目的src/main/resources/static目录下再重新打Jar包。这样用户访问http://localhost:8080时SpringBoot会直接返回前端页面。Vue打包放进SpringBoot的关键就是这步静态资源目录映射很多同学卡在这里原因多半是复制了dist文件夹本身而不是复制里面的内容。7. 常见问题与避坑实录7.1 运行时典型问题速查表我在跑项目过程中整理过一张问题速查表可以直接对照排查。现象常见原因解决办法前端访问接口404请求baseURL配置错误或代理没生效检查vue.config.js中proxy配置重启前端服务登录后接口提示未登录拦截器没取到token或token过期查看请求Header里有没有Authorization字段下单失败但购物车空了事务没控制好或异常被吞掉service方法加Transactional(rollbackForException.class)中文乱码数据库字符集或连接串编码问题数据库设为utf8mb4连接串加characterEncodingutf8商品列表查不到数据接口库中有status0的下架商品列表SQL强制status1后台管理员可上下架端口被占用之前启动的实例没关掉杀掉占用端口进程或改SpringBoot端口前端打包后刷新404Vue Router使用了history模式改用hash模式或后端配置forward到index.htmlMySQL 8.0连接失败驱动或时区配置问题使用com.mysql.cj.jdbc.Driver加serverTimezone这些基本都是项目里实测会遇到的高频问题。特别是前端打包后刷新404因为Vue Router如果用了history模式前端路由路径在服务端并不存在刷新时后端找不到资源就只能返回404。简单方案是改用hash模式URL里会多个#不美观但省事。如果坚持history模式就在SpringBoot里增加一个WebMvcConfigurer把非静态资源的路径都转发到index.html。7.2 我在实际开发中总结的几条经验第一数据库表设计一定要预留create_time和update_time两个字段就算做的时候没用到后续排查问题也能看到数据是什么时候变化的。最好再统一一个字段命名风格不要有的表叫user_id有的表叫userId顺手写个命名规范文档很有用。第二后端返回结果要统一尽量别让前端去猜。项目里所有接口都返回Result结构即使异常也要返回一个标准JSON。如果出现空指针全局异常处理器统一兜底返回code500和“服务器开小差了”这样的提示避免前端拿到一长串堆栈信息既难看又暴露内部实现。第三写购物车和订单时要站在“数据最终一致”的角度思考。比如用户下单前先加购物车购物车里的价格只是展示用真正下单价要以订单接口校验后的商品价格为准。前端传过来的价格后端一律不信任金额计算全部在后端重新计算这是商城项目的基本安全底线。第四前后端接口要做好字段约束。比如数量字段必须传正数价格为负数要拦截String类型长度要做校验。我早期懒省事没做参数校验测试时发现用户能通过接口直接改订单状态后面补上权限校验和参数校验才安心。以后做任何系统接口的第一道关口一定是参数校验不能等着前端帮你挡。最后说点实际体会这个项目做完之后我最大的感受是写商城系统难的不是某个单独技术点而是把各种细节串起来。SpringBoot和Vue本身都有很多“开箱即用”的东西但真正到联调、部署、排查问题的时候才会发现自己对HTTP状态码、数据库事务、JWT生效机制、前端路由模式这些基础知识的理解还不够扎实。建议你拿到源码后不要只跑起来看效果而是跟着链路改一改代码比如把商品表加个字段、给订单增加一个取消理由改一次比看十遍效果都好。最后再分享一个小技巧本地开发时前端代理跨域后端接口写日志两者配合调试效率会高很多。后端加一个简单的拦截器把请求路径、耗时、参数都打印出来前端请求出错时看后端日志比猜前端代码快得多。这个习惯我一直保留到现在遇到线上问题也能快速定位。希望这份源码和踩坑记录能帮你少走点弯路。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询