☰
SpringBoot+Vue前后端分离商城系统实战:从分层架构到JWT认证完整实现
2026/10/20 3:20:16 网站建设 项目流程

先说一下这套东西最适合谁:准备做毕业设计的在校生、刚接触前后端分离开发想找个完整项目练手的初级工程师,以及公司里需要快速搭一套内部演示系统但又不想从零写业务代码的团队。相比那些只贴了几张截图、代码一跑就报错的“半残”资源,这套源码的价值在于它是真能跑通全流程的完整闭环,从前端页面到后端接口再到数据库表结构,一个环节都不缺。你可以把它当成一个标准模板,拆开揉碎看懂每一层在干什么,以后再遇到类似的业务系统需求,就有了一个可以直接参考的骨架。

1. 项目定位与整体技术方案拆解

1.1 为什么是SpringBoot + Vue这套组合

现在做Web应用,前后端分离基本是事实标准了。这套商城系统选择SpringBoot做后端、Vue做前端、MySQL存数据,正好踩在国内中小型项目最主流的技术选型上。

后端用SpringBoot,核心原因是它把过去Spring全家桶那套繁琐的XML配置全砍掉了,用自动配置和约定大于配置的思路,让开发者能集中精力写业务代码。你拿到源码后会发现,一个Controller类就是一个接口集合,一个Service类就是一块业务逻辑,分层非常干净,阅读起来不会有那种“代码绕了三层还找不到入口”的窒息感。

前端选Vue,看中的是它的渐进式架构和组件化开发模式。商城这种系统,页面之间有很多共享的部分——导航栏、商品卡片、购物车角标,把这些拆成独立组件后,改一处全站生效,开发效率和后期维护成本都会好很多。而且Vue的响应式数据绑定机制对电商这种交互密集的场景特别友好,商品数量加减、购物车总价实时刷新这类操作,不需要手动操作DOM,数据变了页面自动跟着变。

MySQL更不用说了,关系型数据库里最普及的选择之一,电商业务天生就适合用关系模型来管理,用户、商品、订单这些实体之间有清晰的外键关联,事务处理能力也能保证下单支付这类关键操作的可靠性。

1.2 分层架构设计:从Controller到Mapper的思路

整个项目采用经典的三层架构,自上而下依次是控制层、业务层、数据访问层,外加一个实体层贯穿始终。

控制层(Controller)负责接收前端请求和返回响应数据,本身不包含任何业务逻辑。你可以把它看成前台接待员,客户说要干什么,它就记录需求然后传给后面处理。请求参数校验、统一响应格式封装这些非业务性的工作在控制层完成。

业务层(Service)是系统的核心大脑,所有规则和逻辑都在这里运算。比如下单时先查库存是否充足、再计算总价、然后生成订单号并扣减库存,这是一个完整的事务边界,必须放在Service层由事务注解统一管理,保证任何一步失败都能整体回滚。

数据访问层(Mapper)和后端实体(Entity)负责处理数据库操作。这块用了MyBatis框架,SQL语句可以自己控制,相比Hibernate那种全自动的ORM工具,对SQL性能调优更友好。商城系统的查询场景往往比较复杂,商品列表要按分类筛选、按价格排序、还要分页,自己写SQL更直观可控。

这套分层的价值在做前后端分离开发时尤其明显:后端只需要把接口文档定义清楚,前端就可以并行开发,双方约定好数据格式,完全不需要互相等待。

1.3 前后端分离的关键:统一响应格式与交互流程

前后端分离后,最先要解决的就是数据格式统一的问题。这套源码里后端设计了一个统一的响应体包装类,所有接口返回的数据都遵循同样的结构。

{ "code": 200, "message": "操作成功", "data": { "token": "xxxxxx", "userInfo": {} } }

code是状态码,200代表成功,500代表服务器异常,401代表未登录或凭证过期。message是对状态的文字描述。data是业务数据的载体,可以是对象、数组或者分页结果。

前端Vue项目里封装了统一的axios请求工具,所有HTTP请求都会经过它,自动做两件事:一是把后端返回的原始JSON解包,拿到data部分交给业务代码使用;二是全局拦截错误状态码,比如遇到401就统一跳转到登录页,避免每个页面都写一遍重复的错误处理代码。

整个交互流程就是:前端发起HTTP请求,携带JWT令牌作为身份凭证,后端过滤器验证令牌有效性,路由到对应Controller处理,Service层执行业务逻辑,Mapper层操作数据库,最后结果层层返回,前端拿到数据渲染页面。

2. 数据库设计与后端核心模块实现

2.1 数据表结构设计与字段规划

拿到的数据库脚本里,核心表有八张左右,各司其职。我挑几个关键的说:

用户表(sys_user)是最基础的账户体系,字段包含用户名、密码、昵称、手机号、邮箱、头像地址、创建时间。密码存的是BCrypt加密后的密文,而不是明文,这一点很重要。很多初学者直接存明文密码,一旦数据库泄露,用户在其他网站上的账号也会跟着遭殃。

商品表,字段包含商品名称、商品描述、主图地址、原价、现价、库存数量、所属分类、上架状态、点击量。价格字段的设计有个细节可以记一下:这里用十进制数而不是浮点数,因为浮点数在计算机里是二进制存储的,0.1加0.2会得到0.30000000000000004这种结果,涉及金额计算时必须用精确的十进制类型来避免误差。

购物车表设计的时候做了个取舍:把用户ID和商品ID建了联合唯一索引,意思是同一个用户的购物车里同一个商品只有一个记录,数量字段可以增加或减少,但不会出现两行一模一样的数据。这个设计避免了购物车爆炸的情况。

订单表和订单明细表是一对多的关系。订单表只管总金额、订单状态、收货信息这些大局数据,订单明细表记录每一件商品的单价、数量、小计。为什么要拆开?因为同一个订单里可能有多件不同商品,把明细独立出来,后续要做退款单件、发货单件、统计热卖单品这些操作,数据才能拆得开、算得清。

2.2 用户认证与权限控制:JWT令牌机制说明

这套系统用JWT做登录认证,取代了传统的Session方案。Session方案需要在服务器内存里存会话数据,如果部署了多个实例,还得引入共享Session机制,否则用户在A服务器登录了,请求打到B服务器又得重新登录。JWT是无状态令牌,服务器不存任何会话数据,用户身份信息全部编码在令牌里,后端只需要用密钥验签即可确认令牌真伪。

登录流程是这样的:用户提交用户名和密码,后端校验通过后,生成一个包含用户ID、用户名、过期时间等信息的JWT令牌返回给前端。前端把令牌存在本地存储或Cookie里,后续每次请求都在HTTP头里带上这个令牌。后端拦截器会先从请求头里取令牌、验签、解析出用户身份,然后放行或者拒绝。

使用JWT有几个细节要注意:一是令牌要设置合理的过期时间,太长了不安全,太短了用户要频繁重新登录,一般两个小时左右比较合适;二是服务端如果要实现“强制注销”功能,光删掉本地令牌没用,因为令牌本身还能验签通过,需要配合黑名单机制来处理;三是密钥绝对不能硬编码在代码里然后跟着源码一起传阅。

2.3 商品搜索、购物车与下单流程的后端逻辑

商品搜索功能,实现思路比较简单实用:在MySQL里用模糊匹配和条件拼接查询。前端传入关键词、分类ID、价格区间、排序方式这些参数,后端Service层根据参数动态拼接SQL,返回商品列表和总条数。这个方案对付中小规模数据量完全够用,不需要引入Elasticsearch这种重量级的搜索引擎。

购物车加购的代码逻辑走的是先查后插的路线——根据用户ID和商品ID查购物车表,有记录就更新数量,没有就新增一条。同时会检验商品状态是否正常、库存是否充足,商品已下架或者库存为0,会返回明确提示。

下单流程是这套系统里最值得研究的业务代码。整个流程放在一个事务方法里,步骤包括:获取购物车选中项和收货地址,逐件校验商品状态和库存,计算订单总金额,生成订单主记录和明细记录,扣减商品库存,清空购物车对应商品。任何一个环节抛异常,事务回滚,所有数据恢复原样。这里可以做个测试来验证:在扣减库存的代码后面故意抛一个异常,然后查看数据库,会发现订单记录没生成、库存没变化、购物车也没清空,这就说明事务生效了。

3. 前端工程结构与核心页面实现

3.1 Vue项目目录结构与组件划分

前端工程采用的是Vue CLI标准结构,我习惯按src目录往下看:

  • src/views:放页面级组件,每个路由对应一个目录,比如首页、商品列表页、商品详情页、购物车页、订单页、登录注册页、个人中心页。
  • src/components:放可复用组件,比如导航栏、商品卡片、分页组件、数量加减器,这些组件在多个页面里被引用。
  • src/router:路由配置文件,定义了URL和页面组件的映射关系,还设置了路由守卫来做登录拦截。
  • src/store:状态管理模块,主要存用户登录信息、购物车商品数量这类需要在多个页面间共享的全局数据。
  • src/api:接口请求模块,每个后端接口都在这里封装成一个函数,比如login(data)、getGoodsList(params)、addCart(params)。

组件划分讲究的是复用性和单一职责。商品卡片组件就是一个很好的例子,商品列表页、搜索结果页、首页推荐位三处都用到了它,只是传入的商品数据不同,渲染出来的样子保持一致。如果哪天想给卡片加个“热卖”角标,只改这一处,三个页面同时生效。

3.2 状态管理与路由守卫:前端数据流转设计

Vue项目里,多个页面需要共享同一份数据,典型就是登录后的用户信息和购物车角标数量。这套系统引入了Vuex状态管理库来负责这件事。

核心思路是把共享数据放进state里,页面通过调用actions里的异步方法去获取数据,然后通过mutations同步更新state。比如登录成功后,把用户信息存入state,导航栏组件实时显示用户名;购物车商品数量存入state,添加商品、删除商品后重新拉取数量并更新,全网所有组件里的角标数字同时刷新。前端不直接修改state,而是统一走方法,这样数据流向是单向的,出了问题也好排查。

路由守卫是另一道关键防线。配置路由时给需要登录才能访问的页面标记requiresAuth: true,然后注册全局前置守卫:每次路由跳转前检查目标路由是否需要认证,需要的话再检查当前是否有有效的登录令牌,没有就强制跳转到登录页,并在URL上挂上redirect参数,登录成功后自动跳回原来想去的页面。这个体验细节很实用,避免了用户被突然打断的割裂感。

3.3 多角色视图与移动端适配

这套系统同时服务两类人群:普通用户和管理员。前端通过菜单级的权限控制来实现角色区隔。登录接口返回的JSON里除了用户基本信息,还带了一个角色标识字段,前端拿到后存进Vuex。渲染导航菜单时,管理员能看到用户管理、商品管理、订单管理这些后台入口,普通用户看不到。这只是一种界面层级的隐藏,真正的安全性还是由后端接口的权限校验兜底的,仅靠前端藏一下菜单并不能防止有技术能力的人直接请求后台接口。

移动端适配这方面,整体布局采用的是响应式设计加弹性布局,在手机和iPad上打开页面,商品的卡片流会自动从四列变成两列,购物车结算按钮固定在底部跟随手指操作。现在手机端的访问占比普遍超过一半,做商城类系统如果没有基础适配能力,损失会很大。

4. 本地运行全流程实操指南

4.1 环境准备:JDK、Maven、Node、MySQL

先把环境装齐。这三个工具缺一不可:

  • JDK 1.8或以上版本,建议8或11,这两个版本在兼容性和稳定性上最稳妥。
  • Maven 3.6以上,用来管理后端依赖,安装后需要配置阿里云的镜像仓库,不然下载依赖的速度会让你怀疑人生。
  • Node.js 14以上,Vue项目的构建和依赖管理全靠它,npm工具随Node一起安装。

MySQL版本建议5.7或8.0。装的时候要注意字符集选择utf8mb4,这个编码能完整支持中文和emoji字符。如果用5.7之前的版本,可能会出现中文乱码问题。

确认环境版本可以在命令行分别执行java -version、mvn -v、node -v、npm -v,能正常输出版本号就说明安装没问题。

4.2 数据库初始化与后端启动步骤

数据库配置是很多新手翻车的高发区。先用Navicat或者命令行工具执行项目提供的SQL脚本文件,完成建库建表。然后打开后端项目的配置文件,重点检查这几项:

server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/mall_db?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai username: root password: 123456 jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT+8

曾遇到过用户卡在这一步:连接地址里的serverTimezone参数没填,MySQL驱动版本比较高的话,直接抛异常提示无法识别时区。这个参数必须按本机时区写,国内统一填Asia/Shanghai就行。

配置确认无误后,在项目根目录执行mvn spring-boot:run命令,或者用IDE的启动按钮运行主类。后端启动成功的标志是控制台打印Tomcat started的日志,表示8080端口已经对外服务。

4.3 前端依赖安装与代理配置

后端起来后,另开一个终端,进入前端目录执行npm install安装依赖。这一步耗时长,耐心等。国内开发者的老话:npm install装的慢,直接改用淘宝镜像源,执行npm config set registry https://registry.npmmirror.com再装,速度会快一个量级。

前端项目的接口地址配置在环境变量文件里:

VUE_APP_BASE_API = '/api'

同时配置了代理服务,把开发环境里所有以/api开头的请求转发到后端地址:

proxy: { '/api': { target: 'http://localhost:8080', changeOrigin: true, pathRewrite: { '^/api': '' } } }

为什么开发环境要用代理而不是直接写完整的后端接口地址?因为跨域问题。浏览器里直连不同端口会被同源策略拦截,而通过代理转发到後端,浏览器看到的请求始终是同源的。

最后执行npm run serve启动开发服务器,控制台会给出访问地址,默认是http://localhost:8081,浏览器打开就能看到商城首页。建议首次登录的时候,如果系统里有预设的管理员账号,先登录看看后台长什么样,再注册一个普通用户测试前台流程。

5. 常见问题排查与项目扩展建议

5.1 启动报错排查表

我在社区里看到拿到这套源码后反馈最多的问题,集中在下面几个点,整理出来直接对应处理:

数据库连接失败:检查MySQL服务是否启动、用户名密码是否正确、数据库是否成功create;在配置文件里改完密码后,一定要确认改的是当前生效的那份配置,有时候存在多环境配置,开发环境默认优先读取。

端口被占用:后端的8080或前端的8081端口已经被其他程序占用。在命令行执行netstat -ano | findstr 8080(Windows)或lsof -i:8080(Mac),查到占用进程的PID后在任务管理器里结束它,或者干脆改配置文件里的端口号。

前端依赖安装失败:大概率是npm源访问外网不通导致超时。执行命令换源后,删掉node_modules文件夹和package-lock.json,重新执行npm install。不要直接去node_modules里手动补依赖,那样容易越弄越乱。

登录后接口报401:后端生成的JWT密钥和前端存储的令牌对不上。解决办法是清掉浏览器本地存储里的旧token,重新登录。如果反复出现,检查后端日志有没有密钥异常配置的报错。

图片加载不出来:商品图片如果走的是本地存储路径,要把项目里的upload目录指到实际存放图片的位置,或者检查数据库里的图片地址和实际文件路径是否一致。

5.2 数据库账号密码权限问题

还有一个容易忽略的细节:本地MySQL的root账号默认做了localhost限制,在一些可视化安装的版本里root账号的认证方式是auth_socket插件,意味着只能本机的系统用户通过特定socket通道连接,外部程序用密码连接会被拒绝。如果碰到Access denied for user 'root'@'localhost'的报错,建议新建一个专用账号来连接:

CREATE USER 'mall_dev'@'localhost' IDENTIFIED BY 'your_password'; GRANT ALL PRIVILEGES ON mall_db.* TO 'mall_dev'@'localhost'; FLUSH PRIVILEGES;

然后把后端配置里的用户名密码替换成新建的账号。这样做还比直接用root更规范一些,避免项目代码里的数据库权限过大。

5.3 如何基于这套系统进行二次开发

拿到手的源码跑通只是第一步,真正有价值的用法是理解之后去改造它。我提几个适合练手的方向:

把商品搜索换成接入Elasticsearch或者MySQL全文索引。现在的模糊匹配方式在数据量小的前提下没问题,但商品过万条时搜索性能会有明显下降。全文索引可以作为零成本演进方案,改造成本适中,效果提升明显。

增加点赞和收藏功能。商城系统有了用户行为数据才算完整。需要新增用户收藏表,在商品详情页增加收藏按钮,个人中心增加收藏列表页面,后端增加收藏的增删查接口,逻辑简单但能让你练到完整的增删改查循环。

对接第三方支付。这是电商绕不开的核心能力。可以对接沙箱环境,跑通统一下单、回调验签、订单状态修改这条完整链路。支付绝对是面试和实际工作中含金量最高的技能点,没有之一。

把图片存储改造为对象存储。现在图片存在本地磁盘,上线后单机磁盘空间很容易吃紧。接入云对象存储,在文件上传接口里调用SDK,把URL存到数据库,替换前端图片地址字段内容,这个改造能让你理解“应用服务器和静态文件分离”的设计思想。

5.4 项目优化方向与实际体会

我实际把这套系统部署到云服务器上测试过,应用服务器用的是性能适中的配置,MySQL和SpringBoot部署在同一台机器上。压测下来,同时在线百人级别的访问量完全能扛得住,接口响应稳定在几百毫秒内。基础的缓存优化也能明显提升性能。比如把商品分类和热门商品这类不经常变化的数据,在Redis里设置一段时间过期时间,做一层缓存,并发一上来,走缓存和应用直连数据库的响应时间差距会非常明显。

这套系统的架构还留了很多可以补全的模块:优惠券、秒杀活动、售后工单、物流跟踪、会员积分,这些在真实电商平台里都是标配能力,但代码量都不算大。拿它当骨架,照着这些方向一个个补进去,就是一份非常好的系统设计实践。

我一直觉得,拿到一个能跑通的全栈项目,最忌讳的事情是读都不读直接改个名字交作业。正确的打开方式是:先把每个模块的代码从头到尾读一遍,把调用链捋清楚,然后在关键方法上打断点,跟一遍调试,亲眼看着一次完整的请求从浏览器出发到Controller再到Service再到Mapper最后带着结果返回,这个过程走完,你才算真正拥有了这套代码。之后任你改也好、拆也好、延伸也好,都是在自己的能力圈里做文章。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询