简介基于SpringBoot与Vue实现的前后端分离商城系统源码定位为适合JavaWeb学习者、毕业设计或中小型电商项目二次开发参考的完整示例。系统拆分为前台用户端与后台管理端用户端覆盖注册登录、商品检索、购物车、总价计算与订单提交流程管理端提供管理员注册登录、分页、权限管理、关键字查询以及对商品、分类、订单、用户、轮播图的增删改查操作可直观对照学习前后台接口交互方式。压缩包共3217个文件大小约6.79MB其中vue、js、ts构成前端页面与逻辑css/scss负责样式java与xml/yml构成后端服务与配置README等辅助资料便于快速了解项目结构。资源已有2015人学习适合用来梳理前后端分离商城从用户下单到后台管理的完整链路也可作为拓展权限控制、商品模块与订单状态的改造基底。1. 这个 SpringBoot Vue 前后端分离商城源码能直接拿来改吗“前后端分离商城系统”这个词搜的人多但真正把压缩包下载下来能一次跑起来的不多。这套 SpringBoot Vue 的商城源码价值在于它是一套完整的参考实现后端是 SpringBoot 单体应用Controller、Service、Mapper 分层清楚购物车、订单、商品、用户这些模块都有前端是 Vue 单页应用路由、API 封装、页面组件按真实项目的组织方式来写另外还带了数据库 SQL 脚本和完整的配置文件。它不是那种打开只有几个页面的 Demo而是能支撑课程设计、毕业设计、企业内部演示的全流程样例。适合正在做毕设的学生、刚学完 SpringBoot 和 Vue 想找个完整项目对照的进阶者以及需要快速搭商城原型的从业者。下面几章我把它从架构到排错拆开讲照着操作能少踩很多坑。2. 先看懂架构再动手后端三层结构、前端路由与目录盘点拿到任何一套源码直接启动都是大忌。前后端分离项目最怕的就是“前端自己跑起来了后端也对但两边连不上”。要避免这种局面得先搞清楚这套代码是怎么组织的、请求链路是怎么走的。看懂以后你才有底气改而不是一路靠猜。2.1 后端请求链路从 Controller 到 Mapper 的典型写法这套商城后端的核心链路是“Controller 接收请求 → Service 处理业务 → Mapper 操作数据库”。以商品列表接口为例// GoodsController.java - 商品列表接口 RestController RequestMapping(/api/goods) public class GoodsController { private final GoodsMapper goodsMapper; public GoodsController(GoodsMapper goodsMapper) { this.goodsMapper goodsMapper; } GetMapping(/list) public Result list(RequestParam(defaultValue 1) Integer page, RequestParam(defaultValue 10) Integer size) { IPageGoods goodsPage goodsMapper.selectPage( new Page(page, size), new QueryWrapperGoods().eq(status, 1) ); return Result.ok(goodsPage); } }这一段是商城列表接口最标准的写法RestController让返回值自动转成 JSON/api/goods/list是前端 axios 请求的路径。分页用的是 MyBatis-Plus 的IPage和Page配合QueryWrapper做条件过滤比手写 SQL 分页省事也避免了最容易被攻击的字符串拼接查询。参数说明page是当前页码默认 1size是每页条数默认 10前端传参时如果不带这两个字段就按默认走eq(status, 1)是只查上架商品下架商品不会出现在列表里。这种写法在这套源码里基本是统一的你后面改任何一个模块照这个套路套就行。2.2 统一返回体前后端通信的“协议”前后端分离项目里接口返回格式必须统一不然前端处理数据时得写一堆if (res.data.xxx undefined)之类的判断。这套源码里你到处能看到Result这个类// Result.java - 统一响应体 public class ResultT { private Integer code; // 200 成功500 失败 private String message; // 提示信息 private T data; // 业务数据 public static T ResultT ok(T data) { ResultT r new Result(); r.code 200; r.message 操作成功; r.data data; return r; } public static T ResultT fail(String msg) { ResultT r new Result(); r.code 500; r.message msg; return r; } }这个类是前后端约定好的“协议”前端拿到响应先判断code 200不是就直接弹出message是才继续用data渲染页面。注意data才是真正的业务数据message只用来提示用户。我接手过的几个分离项目中后端以前喜欢直接返回裸数据后来全部强制统一成这种结构联调效率高了不少——你不用一遍遍去问后端“这个接口到底返回什么”。2.3 前端路由组织Vue Router 的页面分布前端这边关键是路由配置它决定了你能访问哪些页面、参数怎么传// router/index.js - Vue Router 路由配置 import { createRouter, createWebHistory } from vue-router const routes [ { path: /, redirect: /home }, { path: /home, component: () import(/views/HomeView.vue) }, { path: /goods/:id, component: () import(/views/GoodsDetail.vue) }, { path: /cart, component: () import(/views/CartView.vue) }, { path: /login, component: () import(/views/LoginView.vue) }, ] const router createRouter({ history: createWebHistory(), routes, }) export default router这段路由里值得注意的有三点。第一createWebHistory()是 HTML5 history 模式地址栏不带#看着干净但生产环境部署到 Nginx 时必须配try_files兜底否则刷新二级页面就 404。第二组件用() import()懒加载访问到对应路径才加载对应文件首屏加载更快。第三/goods/:id是动态路由商品详情页通过this.$route.params.id拿到商品 ID再调详情接口。2.4 拿到压缩包第一件事盘点目录与关键配置解压之后不要急着启动先花五分钟核对下面这几个文件能帮你避掉 80% 的启动问题路径作用重点关注/sql/shop.sql数据库初始化脚本导入前确认 MySQL 版本兼容/server/src/main/resources/application.yml后端配置数据库密码、端口、Redis 地址/web/src/api目录前端 API 封装baseURL 是否统一指向/api/web/vite.config.js或/web/vue.config.js前端代理配置决定开发联调要不要处理跨域我一般会先打开application.yml看一眼端口和连接串再扫一遍 SQL 脚本里的建表语句心里有个底再动手。前后端分离项目里“配置对不上”是比代码报错更隐蔽的问题它不告诉你哪里错就是页面空白、接口 404。3. 环境准备JDK、Node、MySQL、Redis 的版本参数不会辜负你源码本身没问题跑不起来十有八九是环境版本或配置参数不对。这一章把每一环的参数说清楚照做就能从“拿到源码”顺利走到“能启动”。3.1 JDK 与 Maven版本匹配是首要的大坑SpringBoot 项目对 JDK 版本敏感。打开pom.xml第一件事看这个!-- pom.xml 关键片段 -- properties java.version1.8/java.version spring-boot.version2.7.18/spring-boot.version /properties如果java.version写的 1.8那就老实装 JDK 8 或 JDK 11。强行装 JDK 17 的话大概率会遇到一串莫名其妙的报错Lombok 注解失效、反射访问受限、TLS 证书校验被拒。这些问题的根子不在你的代码是 SpringBoot 2.7 在 JDK 17 下的兼容性不够稳。Maven 建议用 3.6.3 以上版本不要用太老的 3.5。装好后改一下本地仓库位置和镜像能省大量下载时间!-- settings.xml 片段 -- localRepositoryD:/maven-repo/localRepository mirrors mirror idaliyun/id urlhttps://maven.aliyun.com/repository/public/url mirrorOfcentral/mirrorOf /mirror /mirrors参数说明localRepository是本地依赖仓库路径默认在 C 盘用户目录下换成 D 盘方便重装系统后保留依赖mirror配阿里云镜像下载 SpringBoot 相关依赖会快很多。3.2 MySQL 建库与导入字符集和时区一步到位这套商城源码的数据库脚本一般放在/sql目录下。导入时最怕两件事中文乱码和时区报错。先建库再导入# 1. 建库字符集和排序规则一次性定好 mysql -uroot -p -e CREATE DATABASE IF NOT EXISTS shop DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; # 2. 导入数据 mysql -uroot -p --default-character-setutf8mb4 shop sql/shop.sql # 3. 验证导入结果 mysql -uroot -p -e USE shop; SHOW TABLES; SELECT COUNT(*) FROM goods;参数说明--default-character-setutf8mb4强制客户端以 utf8mb4 编码传输中文和 emoji 都不会乱码COLLATE utf8mb4_general_ci是通用排序规则。导入完成后重点看goods表有没有数据如果商品表是空的说明 SQL 脚本没执行完整后续接口查出来全是空列表。然后改后端连接串这一步很多人漏掉# application.yml 中数据源配置 spring: datasource: url: jdbc:mysql://localhost:3306/shop?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/ShanghaiuseSSLfalseallowPublicKeyRetrievaltrue username: root password: your-password注意serverTimezoneAsia/Shanghai必须加否则 SpringBoot 启动会直接报时区错误或者日期字段对不上比如下单时间差 8 小时。allowPublicKeyRetrievaltrue是给 MySQL 8 用的不然可能报 Public Key Retrieval is not allowed。3.3 前端环境Node 版本与依赖安装前端是 Vue 项目不管它是用 Vue CLI 还是 Vite 搭的Node 环境都得先检查node -v # 推荐 16.x 或 18.x LTS npm -v # 与 node 匹配即可 # 切换淘宝镜像解决依赖下载超时 npm config set registry https://registry.npmmirror.com # 进入前端目录安装依赖 cd web npm install这里的版本选择有个规律如果项目根目录有vite.config.js说明用的是 ViteNode 18 更稳妥如果只有vue.config.js那是 Vue CLINode 16 最保险。npm install报错最常见的两种一是网络超时改 registry 镜像就行二是依赖版本冲突报ERESOLVE时在后面追加--legacy-peer-deps重试npm install --legacy-peer-deps简单说前端环境比后端好伺候只要 Node 版本不离谱、镜像通、依赖装全基本不会卡住。4. 手动跑通全流程数据库导入、前后端启动与联调验证环境齐了现在进入实操。以下每一步都是可以照着敲的顺序不要乱先导库再起后端最后起前端。很多人习惯“先起项目等报错再查”结果报错一堆不知道从哪入手其实按顺序来反而好定位。4.1 数据库初始化三步走建库、导入、验证三条命令按顺序执行# 1. 建库 mysql -uroot -p -e CREATE DATABASE IF NOT EXISTS shop DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; # 2. 导入 SQL 脚本 mysql -uroot -p --default-character-setutf8mb4 shop sql/shop.sql # 3. 验证 mysql -uroot -p -e USE shop; SHOW TABLES; SELECT COUNT(*) FROM goods;第二步如果报“Unknown command”之类的错常见是因为 Windows 命令行对 SQL 里的反斜杠和特殊字符处理有问题。这时候不用改 SQL 文件改用 source 命令mysql -uroot -p --default-character-setutf8mb4 -e source C:/path/to/sql/shop.sql提示source 后面的路径要写绝对路径并且用正斜杠/而不是反斜杠\否则路径解析会失败。验证结果里SHOW TABLES应该能列出用户表、商品表、订单表、购物车表等核心表goods表里应该有几条测试数据。没有数据的话后面页面上什么都点不出来。4.2 后端启动jar 包还是直接 run数据库就绪后进到server目录启动后端cd server # 开发模式直接以 SpringBoot 内置 Tomcat 启动 mvn spring-boot:run启动日志里看到类似Started ShopApplication in 12.34 seconds的字样就说明后端起来了。然后先验证接口能不能通curl http://localhost:8080/api/goods/list?page1size10正常情况下会返回一段 JSONcode字段是 200data里有商品列表。如果 curl 返回 404 或连接断开回到第 3.2 节检查数据库连接串和端口配置。想打包成可执行 jar用下面命令mvn clean package -DskipTests java -jar target/shop-server.jar --spring.profiles.activeprod-DskipTests跳过单元测试能省不少编译时间--spring.profiles.activeprod是切换生产环境配置如果项目里没有application-prod.yml就不要加这个参数。开发阶段直接mvn spring-boot:run最省事改完代码自动重启。4.3 前端启动npm run dev 与端口确认另一终端进到web目录cd web npm install npm run dev启动成功后终端会打印一行本地访问地址一般是http://localhost:5173或http://localhost:8081具体看 Vite 或 Vue CLI 的默认端口。如果端口被占可以在启动命令里指定npm run dev -- --port 5174打开浏览器看到登录页说明前端本身没问题。但此刻前后端还没打通你点登录大概率报跨域或 404接下来做联调。4.4 开发环境联调代理配置怎么做开发时前端端口和后端 8080 不同源浏览器会拦截跨域请求。这套源码最省事的联调方式是配置代理让前端把/api开头的请求转发到后端// vite.config.js 中的 server 配置 server: { proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } }参数说明target是后端服务地址changeOrigin: true保证转发时请求头里的 Host 被替换成后端的地址避免后端做域名校验时拒绝请求。改完配置重启前端再点登录就不会跨域了。5. 避坑指南前后端分离商城最常见的五个翻车现场跑这套源码的过程中下面五个问题出现频率最高。每条都是实际踩过的坑按“现象 → 原因 → 解决”的顺序写排查时直接对照。5.1 前端登录接口 404后端日志没动静现象浏览器控制台报POST http://localhost:5173/api/user/login 404但后端控制台没有任何请求记录。 原因前端请求路径里带了/api而后端RequestMapping写的可能是/user/login两边路径对不上或者代理配置没生效请求根本没到后端。 解决先看后端控制台有没有日志没有日志说明请求没过来检查 agent 配置里的/api路径和vite.config.js的 proxy 是否能匹配有日志但 404打开后端源码里的 LoginController核对RequestMapping的完整路径。5.2 跨域报错 Request Origin is not allowed现象前端页面能打开但所有请求都在控制台报跨域错误后端能收到请求但响应被浏览器拦截。 原因开发时前端和后端端口不同浏览器同源策略把响应拦了而代码里既没配代理也没开 CORS。 解决二选一。开发环境优先用代理方案见 4.4 节如果非要用后端开 CORS把配置写在全局配置类里Configuration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/api/**) .allowedOriginPatterns(*) .allowedMethods(GET, POST, PUT, DELETE) .allowCredentials(true); } }allowedOriginPatterns(*)表示所有来源都能访问allowCredentials(true)允许携带 Cookie。注意同时开代理和 CORS 会让问题更难排查建议开发只用其中一种。5.3 MyBatis 报 Invalid bound statement (not found)现象后端启动正常但一访问涉及数据库的接口就报Invalid bound statement (not found): xxx.Mapper.xxx。 原因Mapper 接口编译进了 class但对应的 XML 映射文件没被扫描到。 解决在application.yml里检查 MyBatis 配置mybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.example.shop.entitymapper-locations指定 XML 文件位置type-aliases-package指定实体类包名。默认这套源码的 XML 放在resources/mapper目录下只要路径对就能扫到。如果你改过目录结构这里必须同步改。5.4 MySQL 报 Public Key Retrieval is not allowed现象后端启动时报错或者第一次查数据时报这个异常。 原因MySQL 8 默认使用caching_sha2_password认证插件JDBC 驱动默认不自动获取公钥需要连接串显式授权。 解决在application.yml的连接串末尾追加参数url: jdbc:mysql://localhost:3306/shop?serverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrueuseSSLfalseuseSSLfalse是本地开发环境常用配置生产环境建议根据实际情况改成 true 并配置证书避免明文传输。5.5 Redis 没启动登录和购物车一直转圈现象前端页面能打开但登录后一直 loading购物车数据也没反应后端日志没有任何异常。 原因用户 token、购物车缓存依赖 Redis但 Redis 服务没起来请求全都卡在连接 Redis 的超时上。 解决先确认本机 Redis 是否启动redis-cli ping能返回PONG说明服务正常。没正常就启动 Redis然后检查application.yml里的spring.redis.host和spring.redis.port是否和本地一致。这套源码里 Redis 是硬依赖跳过它会导致一堆功能看着像“没做”其实只是没连上。6. 进阶玩法JWT 鉴权、Redis 缓存与 Nginx 部署项目跑通以后如果你还打算拿它做毕设答辩或面试作品这几件事值得做深一点它们也是前后端分离商城项目里最常被追问的技术点。6.1 JWT 登录鉴权怎么串起来用户登录成功后后端生成一个 token 返回给前端。前端把它存在localStorage或 Pinia 状态里之后每一次请求都在 header 里带上Authorization。后端用一个拦截器统一校验不用在每个 Controller 里重复写鉴权代码Component public class JwtInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token request.getHeader(Authorization); if (!JwtUtil.verify(token)) { response.setStatus(401); response.getWriter().write({\code\:401,\message\:\未登录或token已过期\}); return false; } return true; } }参数说明Authorization头是前后端约好的存放位置一般前端在 axios 拦截器里统一添加401 状态码配合统一响应格式前端拦截到后自动跳转登录页。注意注册拦截器时要放行登录接口本身否则登录请求也会被拦住。6.2 Redis 缓存热点商品数据首页商品列表和高频查询的商品详情每次查数据库都浪费。常见做法是 先查 Redis命中直接返回没命中再查数据库并把结果回填到 Redis 设置过期时间。这套源码里你可以在商品列表服务里加上这条逻辑用StringRedisTemplate或RedisTemplate操作即可。6.3 生产部署Nginx 反向代理与前端静态资源前后端分离项目上线时前端打包成静态文件后端打成 jar 包独立运行中间用 Nginx 做反向代理# Nginx 配置片段 server { listen 80; server_name your-domain.com; location / { root /var/www/shop-web; index index.html; try_files $uri $uri/ /index.html; } location /api/ { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; } }try_files $uri $uri/ /index.html是 history 路由模式的关键配置它让用户直接刷新/goods/123这类地址时不至于 404而是重新加载前端入口文件。proxy_set_header Host $host保证后端收到正确的域名。如果你环境里规定必须用外部 Tomcat 部署也可以把后端打成 war 包放进 Tomcat 的 webapps但生产环境更推荐 jar 包 Nginx 这种轻量组合。从那以后我每次拿到一个前后端分离的商城源码包第一件事都是打开配置文件看端口和数据库连接先导库再起后端最后才碰前端而且每次都会把“代理、跨域、mapper 扫描”这三个老坑先自己认一遍——提前确认五分钟能省后面排错两小时。这套项目如果你能跑通并把这几个点讲清楚不管是交作业还是面试聊项目都已经足够了希望帮到你。本文还有配套的精品资源点击获取
