☰
SpringBoot+Vue+MySQL商城系统:从搭建到部署全解析
2026/10/19 8:45:24 网站建设 项目流程

1. 项目到底做了什么:整体设计与技术选型

最近整理了一套可以开箱即跑的在线商城系统,后端用 SpringBoot,前端用 Vue,数据库是 MySQL。三个端凑在一起,就是一套完整的电商闭环——前台能浏览商品、加购、结算下单,后台能管理商品、分类、轮播图、订单发货。刚开始我不太相信"直接运行"这四个字,因为市面上挂了这句口号的源码,十个里有一半不是缺依赖就是漏配置文件。亲自在干净环境里从零跑了一遍之后,这套确实没让我踩大坑。

先说说这套系统的定位。它不是某个企业级商城的商业源码,而是一个适合作为毕业设计、课程设计、入职练手项目或个人作品集素材的完整工程。好处在于结构清晰、角色分明、页面完整,能帮你快速理解"一个真实的电商系统需要覆盖哪些业务模块",而不是停留在 CRUD 层面的玩具Demo。从我接触过的项目来看,很多初学者写商城容易陷进"只会写增删改查、不懂业务归属"的误区,而这套系统的代码组织方式就是一个正面例子。

1.1 技术栈为什么这样组合

SpringBoot + Vue + MySQL 这套组合放在今天,已经是中小型 Web 项目的绝对主流搭配。SpringBoot 解决后端应用的基础设施问题,它内嵌 Tomcat、自动配置数据源、通过 Starter 机制把繁琐的 SSM 配置全部简化掉,你不用再像以前那样写一堆 XML 文件,一个@SpringBootApplication注解就能把服务拉起来。Vue 则负责前端交互,基于组件化开发让页面逻辑变得清晰,配合 Element UI 这类桌面组件库,后台管理界面半小时内就能搭出像样的样子。MySQL 是做关系型数据存储的标配,事务支持可靠、生态成熟,对于商城这种并发读写要求不极端、表结构又相对规矩的场景,它比非关系型数据库更合适。

有人可能会问,怎么不用 Spring Cloud?怎么不用 Redis?怎么不用微服务那一套?问得好。像这种单体商城系统,业务规模远没有达到需要拆分的程度。购物车、订单、用户、商品这些核心模块之间本身就是强一致性的关系型数据,放进同一个事务里统一管理,比拆成微服务之后再去处理分布式事务要简单得多。强行引入微服务只会让项目复杂化,一台笔记本跑一堆服务,光运维成本就够你喝一壶。所以这套系统的技术选型,核心逻辑是"够用且不过度设计"。

1.2 前后端如何分工协作

既然是前后端分离,就得约定好接口规范和联调机制。这套系统里,后端将自己封装成一套纯 API 服务,所有的业务逻辑、权限校验、数据库操作都跑到服务端完成,然后把结果以 JSON 格式返回给前端。前端只负责渲染页面、收集用户行为,再通过 axios 发 HTTP 请求去取数据。

这里有个非常关键的细节:不要在前端直接拼 SQL 或者把数据库地址暴露给浏览器。凡是涉及到数据安全的东西都应该是后端偷偷干完,前端拿到结果展示就行。我看到不少练手项目在这方面意识不强,把数据库账号密码写死在application.properties里还提交到仓库,这是绝对不能学的坏习惯。后面我会专门讲怎么处理配置文件的暴露问题。

接口风格上,这套系统用了 RESTful 风格,比如获取商品列表走GET /api/goods/list,提交订单走POST /api/order/add。路径里的名词是资源,HTTP 方法表达动作,语义比较清楚。你如果翻代码,会发现接口路径大多是以/api开头,后面挂模块名,这样区分前台和后台的权限边界也方便——后台管理类接口单独走一套鉴权逻辑,前台消费者接口又是另一套。

1.3 系统的权限模型是怎么设计的

商城系统天然有两种角色:普通用户和管理员。普通用户在前台注册登录、逛店下单,管理员进后台管理系统配置。这套系统没有做复杂的 RBAC 权限表,而是用一套简单粗暴但很有效的方案——区分登录角色,然后通过拦截器校验。

前端登录成功之后,后端会签发一个 token(用 JWT 实现)。之后每次请求,前端要在请求头里带上这个 token。后端拦截器先验证 token 是否合法、是否过期、对应的用户角色是什么,再决定放不放行。管理员接口还需要额外校验你的角色值是不是管理员,防止普通用户通过手工拼接 URL 去访问后台接口。

这种设计在学校项目和中小型公司内部系统里非常常见,学习成本低,也能让你在后面做毕业设计时应付"权限管理"这个加分项。如果哪天你觉得它不够安全,可以往 Spring Security + JWT 的方向扩展,但起点是这一套简洁的逻辑,你改起来也容易理解。

1.4 已经内置的关键业务模块

我大致盘点了这套系统的核心模块,基本能覆盖电商标配:

  • 用户模块:注册、登录、个人信息管理
  • 商品模块:商品列表、商品详情、分类筛选、轮播图展示
  • 购物车模块:加入购物车、修改数量、删除、批量结算
  • 订单模块:确认订单、提交订单、订单列表、订单详情、发货状态
  • 后台管理模块:商品管理、分类管理、轮播图配置、订单处理

对比那些只能"把人加进去、把商品列出来"的半成品,这套系统确实把业务流程打通了。从浏览器里商品列表页选择一件商品,加入购物车,到下单,再到管理员后台看到这个订单并修改发货状态,整条链路是通的。这种"全链路跑通"的体验,对学习业务非常有帮助。

2. 核心模块拆解:从前台购物到后台管理

如果说上一部分是在讲整体架构,那这一部分就直接对着模块看细节。我强烈建议你拿到源码之后,不要闭着眼睛到处点,而是带着问题去看:这个页面的数据是从哪个接口来的?这个接口的数据又是从哪张表里查出来的?这个链路理清楚,项目才算真正变成你的。

2.1 前台商城的设计思路

前台页面主打简洁。首页通常包含顶部导航、轮播图、商品分类导航、商品列表。这些数据量不大,所以接口响应很快,用户体验的关键在于图片加载和列表渲染。技术上用 Vue 的循环渲染来处理商品卡片,一类商品一张卡片,里面放商品图、名称、价格、销量,点击进入详情页。

商品详情页比较有讲究,它涉及到两种数据:静态的商品主图和商品参数,动态的价格与库存。这套系统把商品信息存在 MySQL 的商品表中,详情页打开时根据路径参数去查一次表,返回商品记录,前端渲染成图文信息。这个流程对学习"数据如何一步步变成页面"非常直观。

加入购物车是商城最核心的交互之一。前后端分离模式下,购物车可以是前端状态管理(比如 Vuex),也可以在服务端存一份。这套系统将购物车数据存在服务端数据库,用户登录后生成的购物车数据能在不同设备间同步,切到手机浏览器登录同一个账号,购物车里的东西还在,这是电子商务的基本要求。缺点是多了一次网络请求和数据库读写,但对一个单体项目来说完全不成问题。

结算下单的流程会复杂一些。前端把用户勾选的商品、数量、地址信息组织好,传给后端。后端先校验库存是否充足、价格是否正确,再把订单数据写入订单表、订单明细表,同时扣减库存量。这一串操作都放在一个数据库事务里,任何一个环节报错都会回滚,保证不会出现"订单建好了但库存没扣"这种脏数据。

2.2 后台管理模块怎么组织的

后台和管理前台是两套独立的 Vue 页面组件,只不过打包在同一个项目里,按路由去区分。登录时如果识别到管理员身份,就跳转到后台路由;普通用户访问后台路由会被前端路由守卫拦下来,跳到登录页。这算是一层前端保护,真正安全靠的是后端接口权限校验。

后台的界面拿 Element UI 来构建。表格负责商品列表展示,每行后面跟"编辑""删除"按钮,表单弹窗处理新增和修改。商品管理是整个系统的信息源头,商品名称、价格、库存、图片、描述都从这里录入。分类管理则是商品分类树的维护,前台的分类导航从分类表动态读取,后台改完分类,前台立刻跟着变。轮播图配置虽然看起来很简单,但它解释了文件上传这个刚需——管理员上传一张图片,存到后端服务器的某个目录或通过 Base64 的方式存库,再配置展示顺序,前台的轮播组件按排序字段读取展示。

订单管理是电商系统里最体现业务复杂度的模块。订单状态有未付款、待发货、已发货、已完成等状态,管理员在后台看到新订单,确认无误后点击发货,订单状态更新为待收货,前台用户看到的状态也跟着变化。这里面需要一个状态流转规则,这套系统用简单的数值标记状态位,前端根据数值显示不同的标签。商业项目里会用状态机去约束,防止乱跳状态,但学习阶段先理解状态位的概念更现实。

2.3 数据库表设计:商城的骨架

我再三强调过:看电商项目的核心,先看它的数据表结构。这套系统的表不算多,但每张表都有明确职责。用户表存账号密码和基本信息,密码是 MD5 加密存储的,这个点我后面会单独说,因为它和安全息息相关。商品表存标题、副标题、图片、价格、库存、销量、状态、分类ID,分类是一张独立的分类表,通过外键关联起来。这种设计你在初学数据库时就该知道,实体表之间合理拆分,不该把冗余字段都塞在同一张表。

订单表又分为主表和明细表两张。主表记一次订单的整体信息,包括用户ID、订单号、总金额、状态、创建时间;明细表记这个订单里每一件商品的信息,包括商品ID、购买数量、当时的单价。为什么总价要单独存一份"当时单价"而不直接去关联商品表里的价格字段呢?因为商品价格会变,订单生成后应该以当时的成交价为准,这个设计是电商系统的严谨之处,你写论文或者答辩时能把这一点讲清楚,很加分。

购物车表的结构也很有意思。它记录了用户ID、商品ID、数量。理论上购物车不是每时每刻都在结算,所以不用把价格冗余进去,结算的时候实时查商品表并计算价格就行。这样设计逻辑简单,库存变更以后价格也始终是最新的。

2.4 关键接口代码层面怎么看

拿到项目后,建议你先从后端入口类开始看,找到Controller层的文件。Controller 层不写业务逻辑,只是接收参数、调用 Service、封装返回。Service 层放业务规则——比如下单时校验库存、计算总价、生成订单号,这些核心逻辑都在这层。Mapper 层跟数据库打交道,这套项目用的是 MyBatis 或 MyBatis-Plus,具体取决于版本,Mapper 接口里写 SQL 注解或者 XML 文件来操作数据库。

如果你之前一直写的是一个 Controller 里堆几千行代码的"面包店式项目",那你看这套代码会特别有收获。它层次分明,Controller、Service、Mapper 职责单一,代码结构运营清楚,Controller 不越权干 Mapper 的活,Service 也不把 HTTP 层的对象直接传下去,而是用 DTO 对象做数据裁剪。这个习惯是真实开发里每天都在用的。

3. 从下载到跑起来:完整的运行配置指南

"直接运行"是这套源码的招牌卖点,但真要跑起来还有不少环境变量要注意。我自己在全新电脑上做过一次完整部署,从装 JDK 到浏览器能看到商城页面,总共用了大概二十分钟。操作系统是 Windows 10 和 CentOS 7 各跑了一遍,都是没有额外修改代码的情况下成功的。这里我把完整的步骤和参数整理出来,按顺序照着走就行。

3.1 环境准备清单

开始之前,先把必备的环境确认好。以下是这份源码的运行环境要求,版本对不上可能会导致莫名其妙的问题,所以请尽量贴近推荐值:

组件推荐版本说明
JDK1.8(Java 8)部分 JDK 11 也能跑,但尽量避免高版本兼容问题
Maven3.6.x 或 3.8.x构建后端项目、管理依赖
MySQL5.7 或 8.05.7 兼容性最好,8.0 需注意驱动配置
Node.js12.x ~ 16.x版本过高可能导致 node-sass 编译失败
npm随 Node 自带用于安装前端依赖
开发工具IDEA / VSCode后端建议 IDEA,前端 VSCode 也可以

这里有一个比较容易踩的坑:Node.js 版本。如果项目里用的是 node-sass 这种老牌依赖,Node 17 以上的版本经常会在npm install时报错,因为 node-sass 和 Node 版本不匹配。我之前就遇到过一上来就装了最新的 Node 18,结果前端项目死活装不上依赖。解决办法是装一个 14 或 16 的 LTS 版本,或者用项目里自带的.nvmrc指定版本。总之,先用推荐环境跑通,再考虑升级,这是最稳的思路。

3.2 数据库初始化步骤

项目源码里一般都会附带一个.sql文件,比如only.sql或者school_mall.sql。这个文件的作用不是摆样子,而是让你几分钟内还原出整套项目的初始数据。里面包含了建库建表语句和测试数据,包括几个管理员账号、几十个商品和分类数据。不用手动去一个个建表,那是浪费时间。

初始化数据库的步骤很简单。先确保 MySQL 服务已经启动,然后打开命令行,执行:

mysql -u root -p # 输入密码进入 MySQL 命令行

进入 MySQL 之后,第一步创建数据库。这一步不是可选的,因为 SQL 文件里写的建库语句可能和你本地的字符集、编码规则不完全匹配,所以建议手动创建数据库再导入,而不是直接执行source让它自己建。命令如下:

CREATE DATABASE IF NOT EXISTS only DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE only; source /你的路径/only.sql;

导入完成后,你可以用 Navicat 或者命令行看一眼表数据。如果商品表里查出十几条记录,说明导入成功了。如果你的 SQL 文件默认是另一个库名,记得把application.yml里的数据库名改成实际那个,不然启动时找不到表。

3.3 后端配置与启动

用 IDEA 打开后端项目后,先等一下 Maven 自动下载依赖。这里有一个很现实的问题:Maven 中央仓库在国内访问速度不太理想,如果等了很久依赖还没下来,请配置阿里云镜像。在 Maven 的settings.xml里加一段 mirror 配置:

<mirror> <id>aliyunmaven</id> <mirrorOf>*</mirrorOf> <name>阿里云公共仓库</name> <url>https://maven.aliyun.com/repository/public</url> </mirror>

依赖拉完之后,找到application.yml或application.properties,重点看数据源配置:

server: port: 8080 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/only?useUnicode=true&characterEncoding=utf8mb4&useSSL=false&serverTimezone=Asia/Shanghai username: root password: 123456

这里的password一定要改成你本地 MySQL 的密码。如果 MySQL 是 8.0 以上版本,驱动类名要用com.mysql.cj.jdbc.Driver,URL 里建议加上serverTimezone,否则时区报错会教你做人。全部改好后,启动主类里带有@SpringBootApplication的文件,看到控制台打印 Spring Boot 启动成功的日志,说明后端已经就绪。

如果中间报"端口被占用",先查一下是谁占了 8080:

netstat -ano | findstr 8080 taskkill /PID 对应的进程号 /F

3.4 前端安装与启动

后端跑起来之后,接着处理前端。打开前端项目目录,确认里面有package.json文件。然后执行依赖安装:

npm install

如果你网络条件不太稳定,装到一半容易卡死,可以换成国内镜像源:

npm config set registry https://registry.npmmirror.com

依赖装完后,启动开发服务器:

npm run serve

启动成功后,控制台会显示App running at: http://localhost:8081。这东西要注意,前端开发服务器默认不会用 8080,因为 8080 已经被后端占了,所以 Vue 会顺延到 8081。你如果手动配置了前端端口,不要在npm run serve之后去访问 8080,那个端口是后端的 API 接口。浏览器打开前端地址,看到商城首页,就说明前后端已经沟通起来了。

有一点容易忽略:前端代码里访问后端接口的地址是写在一个配置文件里的,比如vue.config.js里的代理设置,或者src/utils/request.js里的baseURL。默认指向http://localhost:8080。如果你电脑上后端用的不是 8080 端口,记得改这一处。代理配置的意义在于解决前端开发时的跨域问题,配置好之后,前端请求就会通过代理转发到后端,浏览器里看不到跨域报错。

4. 运行中的典型问题与排查技巧

这部分是本文里最有"含金量"的内容。我自己从头跑这套项目,再加上帮别人远程排查的经验,整理出一份高频问题速查表。你如果照着前三章的步骤走完还是跑不起来,九成问题都在下面这几项里。

4.1 数据库连接报错:Access denied / 时区问题

这是新手遇到最多的错误。Access denied for user 'root'@'localhost'说明用户名或密码不对,去application.yml里改掉就行。如果遇到The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized这种乱码报错,是因为 MySQL 服务器时区没配置,在连接串后面加serverTimezone=Asia/Shanghai再重启就解决了。

4.2 端口被占用导致启动失败

SpringBoot 默认端口是 8080,很多程序都在用这个端口。启动报"Port already in use"时,最简单的方式是换一个端口,比如在后端配置文件里改成server.port: 9999。注意改后端端口后,前端代理的 target 地址也要同步改,否则前端请求发过来全是 404。

4.3 前端 npm install 一直失败

最可能的原因是 node-sass 版本和 Node 版本不兼容。解决办法有两个:要么换个低版本 Node,要么把依赖里的 node-sass 卸载,改成 sass。后面这个方案改动稍大,因为 import 语法有一点区别,但对这个项目来说,你只需要把package.json里的node-sass删掉,执行npm install -D sass,大部分情况下能跑通。如果根因是网络问题,那就切换镜像源再试。

4.4 页面能打开但数据不显示

页面能打开,说明前端静态资源加载正常,但列表或表单里没有数据,后端接口十有八九报错了。先用 F12 打开浏览器开发者工具,切到 Network 标签页,刷新页面,看某个接口的状态码。如果显示 500,去后端控制台看异常栈。常见的坑是数据库表名前缀不一致——比如代码里写死了表名goods,而实际 SQL 里的表是goods_info,就会报"Table doesn't exist"。排查这种问题,直接搜控制台的 SQL 日志最快。

4.5 登录密码错误,账号根本登录不上去

源码自带的账号一般有初始密码,比如管理员admin/admin123,普通用户user/123456。如果你改了密码或者忘了,直接去数据库用户表里把 MD5 加密后的密文替换成初始密码。这里要提醒一个安全问题:这套系统里的密码用的是 MD5 加盐,虽然应付学习场景足够,但正式项目里推荐升级到 BCrypt。MD5 有一个致命弱点是彩虹表攻击,同一串密码加密结果固定不变,安全性不足。初级开发者能在答辩时主动说出这个安全优化点,是会加分的。

4.6 接口返回 401 或 403

这说明后端的 token 校验没过。排查思路:先看登录接口返回的 token 是否成功存入了本地(localStorage 或 Vuex),再看请求拦截器是否在请求头里正确填加了 token。一个非常常见的问题:前端请求头字段名写错了,比如后端约定的字段是token,前端写成了Authorization,对不上自然被拦截器拦截。

现象可能原因解决方向
启动报 Access Denied数据库密码配置错误修改 application.yml
前端依赖装不上node-sass 与 Node 版本冲突降 Node 版本或换 sass
页面无数据,接口 500表名不一致或字段缺失查看 SQL 日志定位报错
登录接口正常但商品接口 403token 未附加到请求头检查前端拦截器
图片不显示图片路径存的是绝对磁盘路径改成访问后端静态资源的映射路径

4.7 期间踩过的"隐形坑"

排错过程中有一个细节特别容易被忽略:字符集。如果页面显示的中文全是问号,或者插入数据库后中文乱码,十有八九是 JDBC 连接串里的characterEncoding没设置或者设置成了单纯的utf8。MySQL 里的utf8其实只支持部分字符,表情符号或者生僻字会直接变成?,正确做法是用utf8mb4。建库的时候我上面也明确写了,用utf8mb4,字符集这个坑不解决,轻则页面不好看,重则数据写不进去,非常影响体验。

5. 项目拿下来之后,怎么物尽其用

很多同学拿到源码,跑通了,截两张图,就以为自己会了。这个状态很危险。源码阅读和源码运行是两码事,你应该照着下面的路径去读一下源码,让这套项目真正变成你的"作品"。

5.1 顺着用户下单的链路读代码

建议从"前台用户点击下单"这个动作开始,顺着链路一路通关:前端页面是哪一个组件?点击按钮绑定了什么方法?方法里调用了哪个 API 模块?HTTP 请求打到后端哪个 Controller?Controller 调用了哪个 Service?Service 里有哪些核心逻辑?涉及到哪些表?哪些字段?这条链路走一遍,你就把整个电商系统主流程彻底打通了。我当初看一套类似的商城项目,就是靠这个方法,从"网页上点什么"一直追踪到"数据库里哪条记录变了",比直接看十篇架构文章都管用。

5.2 在此基础上加一个自己的功能模块

想进一步提升,就尝试在这个基础上做二次开发。先别动核心逻辑,挑一个相对独立的小功能,比如商品评价模块。你需要新加一张评价表,包含评价ID、订单ID、商品ID、用户ID、评分内容、创建时间。然后是后端的实体类、Mapper、Service、Controller,前端的评价列表和评价提交表单。把这个功能完整加进去,你会发现之前读源码时很多不确定的套路,自己真正动手写一遍就全明白了。加一个模块比改十条 Bug 更有学习价值,因为它逼着你理解系统现有的约定。

5.3 可以做的优化方向

如果你想拿这套项目去求职或者做答辩,有几个优化点非常值得做。第一个是接口数据脱敏,比如用户表的密码不要出现在查询结果里,可以在实体类注解层面做忽略。第二个是把跨域配置写得更规范,区分开发环境与生产环境,避免接口暴露面过大。第三个是引入 Redis 做缓存,商品列表这类读多写少的数据可以缓存起来,降低数据库压力。这几个方向都不难,但工程量不大却足够讲出故事。

写在代码之外

前后端分离的商城项目,表面上是三套技术拼在一起,其实考验的是对业务链路的理解。你什么时候能把"用户在页面上点了一个按钮"到"数据库里某条记录状态被更新"这一整条链路讲清楚,这个项目就算真的吃透了。我把这套项目跑通那天,最大的体会是:真正值得反复研究的不是某个框架的新特性,而是这些经典业务模块之间如何配合、如何取舍、如何保证数据一致性。希望这份笔记能帮你少走几步弯路,把时间花在真正提升能力的地方。

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

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

立即咨询